Beispiel #1
0
def test_inv_matrix_sqrt(data):
    y, x, sigma = data
    k = sigma.shape[0]
    sigma_m12 = inv_matrix_sqrt(sigma)
    assert_allclose(sigma_m12 - sigma_m12.T, np.zeros((k, k)))
    assert_allclose(np.linalg.inv(sigma_m12 @ sigma_m12), sigma)
    assert_allclose(sigma_m12 @ sigma @ sigma_m12, np.eye(k), atol=1e-14)
Beispiel #2
0
def test_ols_against_gls(data):
    mod = SUR(data)
    res = mod.fit(method='gls')
    sigma = res.sigma
    sigma_m12 = inv_matrix_sqrt(sigma)
    key = list(data.keys())[0]

    if isinstance(data[key], Mapping):
        y = [data[key]['dependent'] for key in data]
        x = [data[key]['exog'] for key in data]
        try:
            w = [data[key]['weights'] for key in data]
        except KeyError:
            w = [np.ones_like(data[key]['dependent']) for key in data]
    else:
        y = [data[key][0] for key in data]
        x = [data[key][1] for key in data]
        try:
            w = [data[key][2] for key in data]
        except IndexError:
            w = [np.ones_like(data[key][0]) for key in data]

    wy = [_y * np.sqrt(_w / _w.mean()) for _y, _w in zip(y, w)]
    wx = [_x * np.sqrt(_w / _w.mean()) for _x, _w in zip(x, w)]

    wy = blocked_column_product(wy, sigma_m12)
    wx = blocked_diag_product(wx, sigma_m12)

    ols_res = OLS(wy, wx).fit(debiased=False)
    assert_allclose(res.params, ols_res.params)
Beispiel #3
0
    def _cov(self, gls):
        x = self._x
        eps = self._eps
        k = len(x)
        sigma = self.sigma
        weights = inv(sigma) if gls else eye(k)
        xpx = blocked_inner_prod(x, weights)

        weights = inv_matrix_sqrt(sigma) if gls else eye(k)
        bigx = blocked_diag_product(x, weights)
        nobs = eps.shape[0]
        e = eps.T.ravel()[:, None]
        bigxe = bigx * e
        m = bigx.shape[1]
        xeex = zeros((m, m))
        for i in range(nobs):
            xe = bigxe[i::nobs].sum(0)[None, :]
            xeex += xe.T @ xe

        if self._constraints is None:
            xpxi = inv(xpx)
            cov = xpxi @ xeex @ xpxi
        else:
            cons = self._constraints
            xpx = cons.t.T @ xpx @ cons.t
            xpxi = inv(xpx)
            xeex = cons.t.T @ xeex @ cons.t
            cov = cons.t @ (xpxi @ xeex @ xpxi) @ cons.t.T

        cov = (cov + cov.T) / 2
        return cov
def test_ols_against_gls(data):
    mod = SUR(data)
    res = mod.fit(method="gls")
    if isinstance(data[list(data.keys())[0]], dict):
        predictions = mod.predict(res.params, equations=data)
        predictions2 = mod.predict(np.asarray(res.params)[:, None],
                                   equations=data)
        assert_allclose(predictions, predictions2)
    sigma = res.sigma
    sigma_m12 = inv_matrix_sqrt(np.asarray(sigma))
    key = list(data.keys())[0]

    if isinstance(data[key], Mapping):
        y = [data[key]["dependent"] for key in data]
        x = [data[key]["exog"] for key in data]
        try:
            w = [data[key]["weights"] for key in data]
        except KeyError:
            w = [np.ones_like(data[key]["dependent"]) for key in data]
    else:
        y = [data[key][0] for key in data]
        x = [data[key][1] for key in data]
        try:
            w = [data[key][2] for key in data]
        except IndexError:
            w = [np.ones_like(data[key][0]) for key in data]

    wy = [_y * np.sqrt(_w / _w.mean()) for _y, _w in zip(y, w)]
    wx = [_x * np.sqrt(_w / _w.mean()) for _x, _w in zip(x, w)]

    wy = blocked_column_product(wy, sigma_m12)
    wx = blocked_diag_product(wx, sigma_m12)

    ols_res = OLS(wy, wx).fit(debiased=False)
    assert_allclose(res.params, ols_res.params)
Beispiel #5
0
    def _gls_estimate(self, eps, nobs, total_cols, ci, full_cov, debiased):
        """Core estimation routine for iterative GLS"""
        wx, wy = self._wx, self._wy
        sigma = self._sigma
        if sigma is None:
            sigma = eps.T @ eps / nobs
            sigma *= self._sigma_scale(debiased)

        if not full_cov:
            sigma = diag(diag(sigma))
        sigma_inv = inv(sigma)

        k = len(wy)
        if self.constraints is not None:
            cons = self.constraints
            sigma_m12 = inv_matrix_sqrt(sigma)
            x = blocked_diag_product(wx, sigma_m12)
            y = blocked_column_product(wy, sigma_m12)
            xt = x @ cons.t
            xpx = xt.T @ xt
            xpy = xt.T @ (y - x @ cons.a.T)
            paramsc = solve(xpx, xpy)
            params = cons.t @ paramsc + cons.a.T
        else:
            xpx = blocked_inner_prod(wx, sigma_inv)
            xpy = zeros((total_cols, 1))
            for i in range(k):
                sy = zeros((nobs, 1))
                for j in range(k):
                    sy += sigma_inv[i, j] * wy[j]
                xpy[ci[i]:ci[i + 1]] = wx[i].T @ sy

            params = solve(xpx, xpy)

        beta = params

        loc = 0
        for j in range(k):
            _wx = wx[j]
            _wy = wy[j]
            kx = _wx.shape[1]
            eps[:, [j]] = _wy - _wx @ beta[loc:loc + kx]
            loc += kx

        return beta, eps, sigma
Beispiel #6
0
    def fit(self, *, method=None, full_cov=True, iterate=False, iter_limit=100, tol=1e-6,
            cov_type='robust', **cov_config):
        """
        Estimate model parameters

        Parameters
        ----------
        method : {None, 'gls', 'ols'}
            Estimation method.  Default auto selects based on regressors,
            using OLS only if all regressors are identical. The other two
            arguments force the use of GLS or OLS.
        full_cov : bool
            Flag indicating whether to utilize information in correlations
            when estimating the model with GLS
        iterate : bool
            Flag indicating to iterate GLS until convergence of iter limit
            iterations have been completed
        iter_limit : int
            Maximum number of iterations for iterative GLS
        tol : float
            Tolerance to use when checking for convergence in iterative GLS
        cov_type : str
            Name of covariance estimator. Valid options are

            * 'unadjusted', 'homoskedastic' - Classic covariance estimator
            * 'robust', 'heteroskedastic' - Heteroskedasticit robust
              covariance estimator

        **cov_config
            Additional parameters to pass to covariance estimator. All
            estimators support debiased which employs a small-sample adjustment

        Returns
        -------
        results : SURResults
            Estimation results
        """
        cov_type = cov_type.lower()
        if cov_type not in ('unadjusted', 'robust', 'homoskedastic', 'heteroskedastic'):
            raise ValueError('Unknown cov_type: {0}'.format(cov_type))
        cov_type = 'unadjusted' if cov_type in ('unadjusted', 'homoskedastic') else 'robust'
        k = len(self._dependent)
        col_sizes = [0] + list(map(lambda v: v.ndarray.shape[1], self._exog))
        col_idx = cumsum(col_sizes)
        total_cols = col_idx[-1]
        beta, eps = self._multivariate_ls_fit()
        nobs = eps.shape[0]
        debiased = cov_config.get('debiased', False)
        full_sigma = sigma = (eps.T @ eps / nobs) * self._sigma_scale(debiased)
        if (self._common_exog and method is None and self._constraints is None) or method == 'ols':
            return self._multivariate_ls_finalize(beta, eps, sigma, cov_type, **cov_config)

        beta_hist = [beta]
        nobs = eps.shape[0]
        iter_count = 0
        delta = inf
        while ((iter_count < iter_limit and iterate) or iter_count == 0) and delta >= tol:
            beta, eps, sigma = self._gls_estimate(eps, nobs, total_cols, col_idx,
                                                  full_cov, debiased)
            beta_hist.append(beta)
            delta = beta_hist[-1] - beta_hist[-2]
            delta = sqrt(np.mean(delta ** 2))
            iter_count += 1

        sigma_m12 = inv_matrix_sqrt(sigma)
        wy = blocked_column_product(self._wy, sigma_m12)
        wx = blocked_diag_product(self._wx, sigma_m12)
        gls_eps = wy - wx @ beta

        y = blocked_column_product(self._y, eye(k))
        x = blocked_diag_product(self._x, eye(k))
        eps = y - x @ beta

        return self._gls_finalize(beta, sigma, full_sigma, gls_eps,
                                  eps, cov_type, iter_count, **cov_config)