def _multivariate_ls_fit(self): wy, wx = self._wy, self._wx k = len(wx) if self.constraints is not None: cons = self.constraints xpx_full = blocked_inner_prod(wx, eye(len(wx))) xpy = [] for i in range(k): xpy.append(wx[i].T @ wy[i]) xpy = np.vstack(xpy) xpy = cons.t.T @ xpy - cons.t.T @ xpx_full @ cons.a.T xpx = cons.t.T @ xpx_full @ cons.t params_c = np.linalg.solve(xpx, xpy) params = cons.t @ params_c + 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
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 weight_matrix( self, x: Sequence[NDArray], z: Sequence[NDArray], eps: NDArray, *, sigma: ndarray, ) -> NDArray: """ Construct a GMM weight matrix for a model. Parameters ---------- x : list[ndarray] List of containing model regressors for each equation in the system z : list[ndarray] List of containing instruments for each equation in the system eps : ndarray Model errors (nobs by neqn) sigma : ndarray, default None Fixed covariance of model errors. If None, estimated from eps. Returns ------- ndarray Covariance of GMM moment conditions. """ nobs = z[0].shape[0] w = blocked_inner_prod(z, sigma) / nobs return w
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
def _omega(self) -> NDArray: z = self._z nobs = z[0].shape[0] sigma = self._sigma omega = blocked_inner_prod(z, sigma) omega /= nobs return omega
def _mvreg_cov(self) -> NDArray: x = self._x xeex = blocked_inner_prod(x, self._sigma) xpx = blocked_inner_prod(self._x, eye(len(x))) 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 _omega(self) -> Float64Array: z = self._z nobs = z[0].shape[0] sigma = self._sigma assert sigma is not None omega = blocked_inner_prod(z, sigma) omega /= nobs return omega
def _gls_cov(self) -> NDArray: x = self._x sigma = self._sigma sigma_inv = inv(sigma) xpx = blocked_inner_prod(x, sigma_inv) # Handles case where sigma_inv is not inverse of full_sigma xeex = blocked_inner_prod(x, sigma_inv @ self._full_sigma @ sigma_inv) 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 _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
def test_inner_product(data): y, x, sigma = data efficient = blocked_inner_prod(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 = bigx.T @ omega @ bigx assert_allclose(efficient, expected)
def _cov(self, gls): x = self._x nobs = x[0].shape[0] k = len(x) sigma = self.sigma weights = inv(sigma) if gls else eye(k) xpx = blocked_inner_prod(x, weights) / nobs xeex = self._xeex() 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 / nobs
def weight_matrix(self, x, z, eps, *, sigma=None): """ Parameters ---------- x : ndarray List of containing model regressors for each equation in the system z : ndarray List of containing instruments for each equation in the system eps : ndarray Model errors (nobs by neqn) sigma : ndarray Fixed covariance of model errors Returns ------- weight : ndarray Covariance of GMM moment conditions. """ nobs = z[0].shape[0] w = blocked_inner_prod(z, sigma) / nobs return w