示例#1
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
示例#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)
示例#3
0
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)
示例#4
0
    def _multivariate_ls_fit(self):
        wy, wx = self._wy, self._wx
        k = len(wx)
        if self.constraints is not None:
            cons = self.constraints
            x = blocked_diag_product(wx, eye(len(wx)))
            y = np.vstack(wy)
            xt = x @ cons.t
            # TODO: Make more memory efficient
            # Replace with t.T @ xpx @ t
            xpx = xt.T @ xt
            # Replace with t.T @ xpy - t.T @ xpx @ a.T
            xpy = xt.T @ (y - x @ cons.a.T)
            paramsc = np.linalg.solve(xpx, xpy)
            params = cons.t @ paramsc + cons.a.T
        else:
            xpx = blocked_inner_prod(wx, eye(len(wx)))
            xpy = []
            for i in range(k):
                xpy.append(wx[i].T @ wy[i])
            xpy = np.vstack(xpy)
            xpx, xpy = xpx, xpy
            params = solve(xpx, xpy)

        beta = params
        loc = 0
        eps = []
        for i in range(k):
            nb = wx[i].shape[1]
            b = beta[loc:loc + nb]
            eps.append(wy[i] - wx[i] @ b)
            loc += nb
        eps = hstack(eps)

        return beta, eps
示例#5
0
    def __init__(self,
                 x,
                 eps,
                 sigma,
                 full_sigma,
                 gls=False,
                 debiased=False,
                 constraints=None):
        super(HeteroskedasticCovariance,
              self).__init__(x,
                             eps,
                             sigma,
                             full_sigma,
                             gls=gls,
                             debiased=debiased,
                             constraints=constraints)
        self._name = 'Heteroskedastic (Robust) Covariance'

        k = len(x)
        weights = inv(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]
        xe = zeros((nobs, m))
        for i in range(nobs):
            xe[i, :] = bigxe[i::nobs].sum(0)[None, :]
        self._moments = xe
示例#6
0
    def __init__(
        self,
        x: List[ndarray],
        eps: NDArray,
        sigma: NDArray,
        full_sigma: NDArray,
        *,
        gls: bool = False,
        debiased: bool = False,
        constraints: Optional[LinearConstraint] = None,
    ) -> None:

        super(HeteroskedasticCovariance, self).__init__(
            x,
            eps,
            sigma,
            full_sigma,
            gls=gls,
            debiased=debiased,
            constraints=constraints,
        )
        self._name = "Heteroskedastic (Robust) Covariance"

        k = len(x)
        nobs = eps.shape[0]

        if gls:
            weights = inv(sigma)
            bigx = blocked_diag_product(x, weights)
            e = eps.T.ravel()[:, None]
            bigxe = bigx * e
            m = bigx.shape[1]
            xe = zeros((nobs, m))
            for i in range(nobs):
                xe[i, :] = bigxe[i::nobs].sum(0)[None, :]
        else:
            # Do not require blocking when not using GLS
            k_tot = sum(map(lambda a: a.shape[1], x))
            xe = empty((nobs, k_tot))
            loc = 0
            for i in range(k):
                offset = x[i].shape[1]
                xe[:, loc:loc + offset] = x[i] * eps[:, i:i + 1]
                loc += offset

        self._moments = xe
示例#7
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
示例#8
0
def test_diag_product(data):
    y, x, sigma = data
    efficient = blocked_diag_product(x, sigma)
    nobs = x[0].shape[0]
    omega = np.kron(sigma, np.eye(nobs))
    k = len(x)
    bigx = []
    for i in range(k):
        row = []
        for j in range(k):
            if i == j:
                row.append(x[i])
            else:
                row.append(np.zeros((nobs, x[j].shape[1])))
        bigx.append(np.hstack(row))
    bigx = np.vstack(bigx)
    expected = omega @ bigx
    assert_allclose(efficient, expected)
示例#9
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)