def test_kernel(self, data, kernel, bandwidth): c = IVGMMCovariance( data.x, data.y, data.z, data.params, data.i, "kernel", kernel=kernel.kernel, bandwidth=bandwidth, ) s = KernelWeightMatrix(kernel=kernel.kernel, bandwidth=bandwidth).weight_matrix( data.x, data.z, data.e) x, z, nobs = data.x, data.z, data.nobs xzwswzx = x.T @ z @ s @ z.T @ x / data.nobs cov = data.xzizx_inv @ xzwswzx @ data.xzizx_inv cov = (cov + cov.T) / 2 assert_allclose(c.cov, cov) assert c.config["kernel"] == kernel.kernel assert c.config["debiased"] is False assert c.config["bandwidth"] == bandwidth or nobs - 2 c = IVGMMCovariance(data.x, data.y, data.z, data.params, data.i, "kernel") assert "Kernel" in str(c)
def test_clustered(self, data): c = IVGMMCovariance(data.x, data.y, data.z, data.params, data.i, 'clustered', clusters=data.clusters) s = OneWayClusteredWeightMatrix(clusters=data.clusters).weight_matrix(data.x, data.z, data.e) x, z = data.x, data.z xzwswzx = x.T @ z @ s @ z.T @ x / data.nobs cov = data.xzizx_inv @ xzwswzx @ data.xzizx_inv cov = (cov + cov.T) / 2 assert_allclose(c.cov, cov) assert c.config['debiased'] is False assert_equal(c.config['clusters'], data.clusters) c = IVGMMCovariance(data.x, data.y, data.z, data.params, data.i, 'clustered') assert 'Clustered' in str(c)
def test_heteroskedastic(self, data): c = IVGMMCovariance(data.x, data.y, data.z, data.params, data.i, 'robust') s = HeteroskedasticWeightMatrix().weight_matrix(data.x, data.z, data.e) x, z = data.x, data.z xzwswzx = x.T @ z @ s @ z.T @ x / data.nobs cov = data.xzizx_inv @ xzwswzx @ data.xzizx_inv cov = (cov + cov.T) / 2 assert_allclose(c.cov, cov) assert c.config['debiased'] is False
def fit( self, *, iter_limit: int = 2, tol: float = 1e-4, initial_weight: NDArray = None, cov_type: str = "robust", debiased: bool = False, **cov_config: Any, ) -> Union[OLSResults, IVGMMResults]: """ Estimate model parameters Parameters ---------- iter_limit : int, default 2 Maximum number of iterations. Default is 2, which produces two-step efficient GMM estimates. Larger values can be used to iterate between parameter estimation and optimal weight matrix estimation until convergence. tol : float, default 1e-4 Convergence criteria. Measured as covariance normalized change in parameters across iterations where the covariance estimator is based on the first step parameter estimates. initial_weight : ndarray, default None Initial weighting matrix to use in the first step. If not specified, uses the average outer-product of the set containing the exogenous variables and instruments. cov_type : str, default "robust" Name of covariance estimator to use. Available covariance functions are: * 'unadjusted', 'homoskedastic' - Assumes moment conditions are homoskedastic * 'robust', 'heteroskedastic' - Allows for heteroskedasticity but not autocorrelation * 'kernel' - Allows for heteroskedasticity and autocorrelation * 'cluster' - Allows for one-way cluster dependence debiased : bool, default False Flag indicating whether to debiased the covariance estimator using a degree of freedom adjustment. **cov_config Additional parameters to pass to covariance estimator. Supported parameters depend on specific covariance structure assumed. See :class:`linearmodels.iv.gmm.IVGMMCovariance` for details on the available options. Defaults are used if no covariance configuration is provided. Returns ------- IVGMMResults Results container See also -------- linearmodels.iv.gmm.IVGMMCovariance """ wy, wx, wz = self._wy, self._wx, self._wz nobs = wy.shape[0] weight_matrix = self._weight.weight_matrix wmat = inv(wz.T @ wz / nobs) if initial_weight is None else initial_weight sv = IV2SLS( self.dependent, self.exog, self.endog, self.instruments, weights=self.weights, ) _params = params = asarray(sv.fit().params)[:, None] # _params = params = self.estimate_parameters(wx, wy, wz, wmat) iters, norm = 1, 10 * tol + 1 while iters < iter_limit and norm > tol: eps = wy - wx @ params wmat = inv(weight_matrix(wx, wz, eps)) params = self.estimate_parameters(wx, wy, wz, wmat) delta = params - _params if iters == 1: xpz = wx.T @ wz / nobs v = (xpz @ wmat @ xpz.T) / nobs vinv = inv(v) _params = params norm = delta.T @ vinv @ delta iters += 1 cov_config["debiased"] = debiased cov_estimator = IVGMMCovariance(wx, wy, wz, params, wmat, cov_type, **cov_config) results = self._post_estimation(params, cov_estimator, cov_type) gmm_pe = self._gmm_post_estimation(params, wmat, iters) results.update(gmm_pe) return self._result_container(results, self)
def fit( self, *, starting: NDArray = None, display: bool = False, cov_type: str = "robust", debiased: bool = False, opt_options: Optional[Dict[str, Any]] = None, **cov_config: Any, ) -> Union[OLSResults, IVGMMResults]: r""" Estimate model parameters Parameters ---------- starting : ndarray, default None Starting values to use in optimization. If not provided, 2SLS estimates are used. display : bool, default False Flag indicating whether to display optimization output cov_type : str, default "robust" Name of covariance estimator to use debiased : bool, default False Flag indicating whether to debiased the covariance estimator using a degree of freedom adjustment. opt_options : dict, default None Additional options to pass to scipy.optimize.minimize when optimizing the objective function. If not provided, defers to scipy to choose an appropriate optimizer. **cov_config Additional parameters to pass to covariance estimator. Supported parameters depend on specific covariance structure assumed. See :class:`linearmodels.iv.gmm.IVGMMCovariance` for details on the available options. Defaults are used if no covariance configuration is provided. Returns ------- IVGMMResults Results container Notes ----- Starting values are computed by IVGMM. See also -------- linearmodels.iv.gmm.IVGMMCovariance """ wy, wx, wz = self._wy, self._wx, self._wz weight_matrix = self._weight.weight_matrix if starting is None: exog = None if self.exog.shape[1] == 0 else self.exog endog = None if self.endog.shape[1] == 0 else self.endog instr = None if self.instruments.shape[1] == 0 else self.instruments res = IVGMM( self.dependent, exog, endog, instr, weights=self.weights, weight_type=self._weight_type, **self._weight_config, ).fit() starting = asarray(res.params) else: starting = asarray(starting) if len(starting) != self.exog.shape[1] + self.endog.shape[1]: raise ValueError("starting does not have the correct number " "of values") params, iters = self.estimate_parameters(starting, wx, wy, wz, display, opt_options=opt_options) eps = wy - wx @ params wmat = inv(weight_matrix(wx, wz, eps)) cov_config["debiased"] = debiased cov_estimator = IVGMMCovariance(wx, wy, wz, params, wmat, cov_type, **cov_config) results = self._post_estimation(params, cov_estimator, cov_type) gmm_pe = self._gmm_post_estimation(params, wmat, iters) results.update(gmm_pe) return self._result_container(results, self)
def test_unknown(self, data): with pytest.raises(ValueError): IVGMMCovariance(data.x, data.y, data.z, data.params, data.i, 'unknown').cov
def fit(self, *, starting=None, display=False, cov_type='robust', **cov_config): r""" Estimate model parameters Parameters ---------- starting : ndarray, optional Starting values to use in optimization. If not provided, 2SLS estimates are used. display : bool, optional Flag indicating whether to display optimization output cov_type : str, optional Name of covariance estimator to use **cov_config Additional parameters to pass to covariance estimator Returns ------- results : IVGMMResults Results container Notes ----- Additional covariance parameters depend on specific covariance used. The see the docstring of specific covariance estimator for a list of supported options. Defaults are used if no covariance configuration is provided. Starting values are computed by IVGMM. .. todo:: * Expose method to pass optimization options """ wy, wx, wz = self._wy, self._wx, self._wz weight_matrix = self._weight.weight_matrix if starting is None: exog = None if self.exog.shape[1] == 0 else self.exog endog = None if self.endog.shape[1] == 0 else self.endog instr = None if self.instruments.shape[1] == 0 else \ self.instruments res = IVGMM(self.dependent, exog, endog, instr, weights=self.weights, weight_type=self._weight_type, **self._weight_config).fit() starting = res.params.values else: starting = asarray(starting) if len(starting) != self.exog.shape[1] + self.endog.shape[1]: raise ValueError('starting does not have the correct number ' 'of values') params, iters = self.estimate_parameters(starting, wx, wy, wz, display) eps = wy - wx @ params wmat = inv(weight_matrix(wx, wz, eps)) cov_estimator = IVGMMCovariance(wx, wy, wz, params, wmat, cov_type, **cov_config) results = self._post_estimation(params, cov_estimator, cov_type) gmm_pe = self._gmm_post_estimation(params, wmat, iters) results.update(gmm_pe) return self._result_container(results, self)
def fit(self, *, iter_limit=2, tol=1e-4, initial_weight=None, cov_type='robust', **cov_config): """ Estimate model parameters Parameters ---------- iter_limit : int, optional Maximum number of iterations. Default is 2, which produces two-step efficient GMM estimates. Larger values can be used to iterate between parameter estimation and optimal weight matrix estimation until convergence. tol : float, optional Convergence criteria. Measured as covariance normalized change in parameters across iterations where the covariance estimator is based on the first step parameter estimates. initial_weight : ndarray, optional Initial weighting matrix to use in the first step. If not specified, uses the average outer-product of the set containing the exogenous variables and instruments. cov_type : str, optional Name of covariance estimator to use **cov_config Additional parameters to pass to covariance estimator Returns ------- results : IVGMMResults Results container Notes ----- Additional covariance parameters depend on specific covariance used. The see the docstring of specific covariance estimator for a list of supported options. Defaults are used if no covariance configuration is provided. Available covariance functions are: * 'unadjusted', 'homoskedastic' - Assumes moment conditions are homoskedastic * 'robust', 'heteroskedastic' - Allows for heteroskedasticity by not autocorrelation * 'kernel' - Allows for heteroskedasticity and autocorrelation * 'cluster' - Allows for one-way cluster dependence """ wy, wx, wz = self._wy, self._wx, self._wz nobs = wy.shape[0] weight_matrix = self._weight.weight_matrix wmat = inv(wz.T @ wz / nobs) if initial_weight is None else initial_weight sv = IV2SLS(self.dependent, self.exog, self.endog, self.instruments, weights=self.weights) _params = params = sv.fit().params.values[:, None] # _params = params = self.estimate_parameters(wx, wy, wz, wmat) iters, norm = 1, 10 * tol while iters < iter_limit and norm > tol: eps = wy - wx @ params wmat = inv(weight_matrix(wx, wz, eps)) params = self.estimate_parameters(wx, wy, wz, wmat) delta = params - _params if iters == 1: xpz = wx.T @ wz / nobs v = (xpz @ wmat @ xpz.T) / nobs vinv = inv(v) _params = params norm = delta.T @ vinv @ delta iters += 1 cov_estimator = IVGMMCovariance(wx, wy, wz, params, wmat, cov_type, **cov_config) results = self._post_estimation(params, cov_estimator, cov_type) gmm_pe = self._gmm_post_estimation(params, wmat, iters) results.update(gmm_pe) return self._result_container(results, self)