示例#1
0
def _compute_betas(y, x):
    """
    compute MLE coefficients using iwls routine

    Methods: p189, Iteratively (Re)weighted Least Squares (IWLS),
    Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
    Geographically weighted regression: the analysis of spatially varying relationships.
    """
    xT = x.T
    xtx = spdot(xT, x)
    xtx_inv = la.inv(xtx)
    xtx_inv = sp.csr_matrix(xtx_inv)
    xTy = spdot(xT, y, array_out=False)
    betas = spdot(xtx_inv, xTy)
    return betas
示例#2
0
def logp_lambda_prec(state, val):
    """
    Compute the log likelihood of the upper-level spatial correlation parameter using 
    sparse operations and the precision matrix, rather than the covariance matrix. 
    """
    st = state

    if (val < st.Lambda_min) or (val > st.Lambda_max):
        return np.array([-np.inf])

    PsiLambdai = st.Psi_2i(val, st.M, sparse=True)
    logdet = -splogdet(PsiLambdai)  #negative because precision

    kernel = spdot(spdot(st.Alphas.T, PsiLambdai), st.Alphas) / st.Tau2

    return -.5 * logdet - .5 * kernel + st.Log_Lambda0(val)
示例#3
0
def logp_rho_prec(state, val):
    """
    This computes the logp of the spatial parameter using the precision, rather than the covariance. This results in fewer matrix operations in the case of a SE formulation, but not in an SMA formulation.
    """
    st = state

    #must truncate in logp otherwise sampling gets unstable
    if (val < st.Rho_min) or (val > st.Rho_max):
        return np.array([-np.inf])

    PsiRhoi = st.Psi_1i(val, st.W, sparse=True)
    logdet = splogdet(PsiRhoi)

    eta = st.Y - st.XBetas - st.DeltaAlphas
    kernel = spdot(spdot(eta.T, PsiRhoi), eta) / st.Sigma2

    return .5 * logdet - .5 * kernel + st.Log_Rho0(
        val)  #since precision, no negative on ld
示例#4
0
def logp_lambda_prec(state, val):
    """
    The logp for upper level spatial parameters in this case has the same form
    as a multivariate normal distribution, sampled over the variance matrix,
    rather than over Y.
    """
    st = state

    #must truncate
    if (val < st.Lambda_min) or (val > st.Lambda_max):
        return np.array([-np.inf])

    PsiLambdai = st.Psi_2i(val, st.M)
    logdet = splogdet(PsiLambdai)

    kernel = spdot(spdot(st.Alphas.T, PsiLambdai), st.Alphas) / st.Tau2

    return .5 * logdet - .5 * kernel + st.Log_Lambda0(val)
示例#5
0
def logp_rho_prec(state, val):
    """
    Compute the log likelihood of the lower-level spatial correlation parameter using
    sparse operations and the precision matrix, rather than the covariance matrix. 
    """
    st = state

    if (val < st.Rho_min) or (val > st.Rho_max):
        return np.array([-np.inf])

    PsiRhoi = st.Psi_1i(val, st.W, sparse=True)
    logdet = -splogdet(PsiRhoi)

    eta = st.Y - st.XBetas - st.DeltaAlphas

    kernel = spdot(spdot(eta.T, PsiRhoi), eta) / st.Sigma2

    return -.5 * logdet - .5 * kernel + st.Log_Rho0(val)
示例#6
0
def logp_rho_cov(state, val):
    """
    The logp for lower-level spatial parameters in this case has the same
    form as a multivariate normal distribution, sampled over the variance matrix, rather than over y.
    """
    st = state

    #must truncate in logp otherwise sampling gets unstable
    if (val < st.Rho_min) or (val > st.Rho_max):
        return np.array([-np.inf])

    PsiRho = st.Psi_1(val, st.W)
    logdet = splogdet(PsiRho)

    eta = st.Y - st.XBetas - st.DeltaAlphas
    kernel = spdot(eta.T, spsolve(PsiRho, eta)) / st.Sigma2

    return -.5 * logdet - .5 * kernel + st.Log_Rho0(val)
示例#7
0
 def normalized_cov_params(self):
     return la.inv(spdot(self.w.T, self.w))
示例#8
0
def iwls(y, x, family, offset, y_fix,
         ini_betas=None, tol=1.0e-8, max_iter=200, wi=None):
    """
    Iteratively re-weighted least squares estimation routine

    Parameters
    ----------
    y           : array
                  n*1, dependent variable

    x           : array
                  n*k, designs matrix of k independent variables

    family      : family object
                  probability models: Gaussian, Poisson, or Binomial

    offset      : array
                  n*1, the offset variable for each observation.

    y_fix       : array
                  n*1, the fixed intercept value of y for each observation

    ini_betas   : array
                  1*k, starting values for the k betas within the iteratively
                  weighted least squares routine

    tol         : float
                  tolerance for estimation convergence

    max_iter    : integer maximum number of iterations if convergence not met

    wi          : array
                  n*1, weights to transform observations from location i in GWR



    Returns
    -------

    betas       : array
                  k*1, estimated coefficients

    mu          : array
                  n*1, predicted y values

    wx          : array
                  n*1, final weights used for iwls for GLM

    n_iter      : integer
                  number of iterations that when iwls algorithm terminates

    w           : array
                  n*1, final weights used for iwls for GWR

    z           : array
                  iwls throughput

    v           : array
                  iwls throughput

    xtx_inv_xt  : array
                  iwls throughout to compute GWR hat matrix
                  [X'X]^-1 X'

    """
    n_iter = 0
    diff = 1.0e6

    if ini_betas is None:
        betas = np.zeros((x.shape[1], 1), np.float)
    else:
        betas = ini_betas

    if isinstance(family, Binomial):
        y = family.link._clean(y)
    if isinstance(family, Poisson):
        y_off = y / offset
        y_off = family.starting_mu(y_off)
        v = family.predict(y_off)
        mu = family.starting_mu(y)
    else:
        mu = family.starting_mu(y)
        v = family.predict(mu)

    while diff > tol and n_iter < max_iter:
        n_iter += 1
        w = family.weights(mu)
        z = v + (family.link.deriv(mu) * (y - mu))
        w = np.sqrt(w)
        if not isinstance(x, np.ndarray):
            w = sp.csr_matrix(w)
            z = sp.csr_matrix(z)
        wx = spmultiply(x, w, array_out=False)
        wz = spmultiply(z, w, array_out=False)
        if wi is None:
            n_betas = _compute_betas(wz, wx)
        else:
            n_betas, xtx_inv_xt = _compute_betas_gwr(wz, wx, wi)
        v = spdot(x, n_betas)
        mu = family.fitted(v)

        if isinstance(family, Poisson):
            mu = mu * offset

        diff = min(abs(n_betas - betas))
        betas = n_betas

    if wi is None:
        return betas, mu, wx, n_iter
    else:
        return betas, mu, v, w, z, xtx_inv_xt, n_iter
示例#9
0
    def _iteration(self):
        st = self.state

        ### Sample the Beta conditional posterior
        ### P(beta | . ) \propto L(Y|.) \dot P(\beta)
        ### is
        ### N(Sb, S) where
        ### S = (X' Sigma^{-1}_Y X + S_0^{-1})^{-1}
        ### b = X' Sigma^{-1}_Y (Y - Delta Alphas) + S^{-1}\mu_0
        covm_update = st.X.T.dot(st.X) / st.Sigma2
        covm_update += st.Betas_cov0i
        covm_update = la.inv(covm_update)

        resids = st.Y - st.Delta.dot(st.Alphas)
        XtSresids = st.X.T.dot(resids) / st.Sigma2
        mean_update = XtSresids + st.Betas_cov0i.dot(st.Betas_mean0)
        mean_update = np.dot(covm_update, mean_update)
        st.Betas = chol_mvn(mean_update, covm_update)
        st.XBetas = np.dot(st.X, st.Betas)

        ### Sample the Random Effect conditional posterior
        ### P( Alpha | . ) \propto L(Y|.) \dot P(Alpha | \lambda, Tau2)
        ###                               \dot P(Tau2) \dot P(\lambda)
        ### is
        ### N(Sb, S)
        ### Where
        ### S = (Delta'Sigma_Y^{-1}Delta + Sigma_Alpha^{-1})^{-1}
        ### b = (Delta'Sigma_Y^{-1}(Y - X\beta) + 0)
        covm_update = st.Delta.T.dot(st.Delta) / st.Sigma2
        covm_update += st.PsiLambdai / st.Tau2
        covm_update = np.asarray(covm_update)
        covm_update = la.inv(covm_update)

        resids = st.Y - st.XBetas
        mean_update = st.Delta.T.dot(resids) / st.Sigma2
        mean_update = np.dot(covm_update, mean_update)
        mean_update = np.asarray(mean_update)
        st.Alphas = chol_mvn(mean_update, covm_update)
        st.DeltaAlphas = np.dot(st.Delta, st.Alphas)

        ### Sample the Random Effect aspatial variance parameter
        ### P(Tau2 | .) \propto L(Y|.) \dot P(\Alpha | \lambda, Tau2)
        ###                            \dot P(Tau2) \dot P(\lambda)
        ### is
        ### IG(J/2 + a0, u'(\Psi(\lambda))^{-1}u * .5 + b0)
        bn = spdot(st.Alphas.T, spdot(st.PsiLambdai,
                                      st.Alphas)) * .5 + st.Tau2_b0
        st.Tau2 = stats.invgamma.rvs(st.Tau2_an, scale=bn)

        ### Sample the response aspatial variance parameter
        ### P(Sigma2 | . ) \propto L(Y | .) \dot P(Sigma2)
        ### is
        ### IG(N/2 + a0, eta'Psi(\rho)^{-1}eta * .5 + b0)
        ### Where eta is the linear predictor, Y - X\beta + \DeltaAlphas
        eta = st.Y - st.XBetas - st.DeltaAlphas
        bn = eta.T.dot(eta) * .5 + st.Sigma2_b0
        st.Sigma2 = stats.invgamma.rvs(st.Sigma2_an, scale=bn)

        ### P(Psi(\rho) | . ) \propto L(Y | .) \dot P(\rho)
        ### is
        ### |Psi(rho)|^{-1/2} exp(1/2(eta'Psi(rho)^{-1}eta * Sigma2^{-1})) * 1/(emax-emin)
        st.Lambda = self.configs.Lambda(st)
        st.PsiLambdai = st.Psi_2i(st.Lambda, st.M)