def test_equivalence_with_wls(self, check): res = WLS(self.endog1, self.exog1).fit() minres = _MinimalWLS(self.endog1, self.exog1, check_endog=check, check_weights=check).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog2, self.exog2).fit() minres = _MinimalWLS(self.endog2, self.exog2, check_endog=check, check_weights=check).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog1, self.exog1, weights=self.weights1).fit() minres = _MinimalWLS(self.endog1, self.exog1, weights=self.weights1, check_endog=check, check_weights=check).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog2, self.exog2, weights=self.weights2).fit() minres = _MinimalWLS(self.endog2, self.exog2, weights=self.weights2, check_endog=check, check_weights=check).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid)
def test_inf_nan(self, bad_value): with pytest.raises(ValueError) as err: endog = self.endog1.copy() endog[0] = bad_value _MinimalWLS(endog, self.exog1, self.weights1, check_endog=True, check_weights=True).fit() assert err.type is ValueError assert 'endog' in str(err) with pytest.raises(ValueError) as err: weights = self.weights1.copy() weights[-1] = bad_value _MinimalWLS(self.endog1, self.exog1, weights, check_endog=True, check_weights=True).fit() assert err.type is ValueError assert 'weights' in str(err)
def test_equivalence_with_wls(self): res = WLS(self.endog1, self.exog1).fit() minres = _MinimalWLS(self.endog1, self.exog1).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog2, self.exog2).fit() minres = _MinimalWLS(self.endog2, self.exog2).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog1, self.exog1, weights=self.weights1).fit() minres = _MinimalWLS(self.endog1, self.exog1, weights=self.weights1).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid) res = WLS(self.endog2, self.exog2, weights=self.weights2).fit() minres = _MinimalWLS(self.endog2, self.exog2, weights=self.weights2).fit() assert_allclose(res.params, minres.params) assert_allclose(res.resid, minres.resid)
def test_inf_nan(self, bad_value): with pytest.raises(ValueError, match=r'detected in endog, estimation infeasible'): endog = self.endog1.copy() endog[0] = bad_value _MinimalWLS(endog, self.exog1, self.weights1, check_endog=True, check_weights=True).fit() with pytest.raises( ValueError, match=r'detected in weights, estimation infeasible'): weights = self.weights1.copy() weights[-1] = bad_value _MinimalWLS(self.endog1, self.exog1, weights, check_endog=True, check_weights=True).fit()
def test_inf_nan(self, bad_value): with pytest.raises(ValueError) as err: endog = self.endog1.copy() endog[0] = bad_value _MinimalWLS(endog, self.exog1, self.weights1, check_endog=True, check_weights=True).fit() assert err.type is ValueError assert 'endog' in str(err) with pytest.raises(ValueError) as err: weights = self.weights1.copy() weights[-1] = bad_value _MinimalWLS(self.endog1, self.exog1, weights, check_endog=True, check_weights=True).fit() assert err.type is ValueError assert 'weights' in str(err)
def fit(self, maxiter=50, tol=1e-8, scale_est='mad', init=None, cov='H1', update_scale=True, conv='dev'): """ Fits the model using iteratively reweighted least squares. The IRLS routine runs until the specified objective converges to `tol` or `maxiter` has been reached. Parameters ---------- conv : string Indicates the convergence criteria. Available options are "coefs" (the coefficients), "weights" (the weights in the iteration), "sresid" (the standardized residuals), and "dev" (the un-normalized log-likelihood for the M estimator). The default is "dev". cov : string, optional 'H1', 'H2', or 'H3' Indicates how the covariance matrix is estimated. Default is 'H1'. See rlm.RLMResults for more information. init : string Specifies method for the initial estimates of the parameters. Default is None, which means that the least squares estimate is used. Currently it is the only available choice. maxiter : int The maximum number of iterations to try. Default is 50. scale_est : string or HuberScale() 'mad' or HuberScale() Indicates the estimate to use for scaling the weights in the IRLS. The default is 'mad' (median absolute deviation. Other options are 'HuberScale' for Huber's proposal 2. Huber's proposal 2 has optional keyword arguments d, tol, and maxiter for specifying the tuning constant, the convergence tolerance, and the maximum number of iterations. See statsmodels.robust.scale for more information. tol : float The convergence tolerance of the estimate. Default is 1e-8. update_scale : Bool If `update_scale` is False then the scale estimate for the weights is held constant over the iteration. Otherwise, it is updated for each fit in the iteration. Default is True. Returns ------- results : object statsmodels.rlm.RLMresults """ if cov.upper() not in ["H1", "H2", "H3"]: raise ValueError("Covariance matrix %s not understood" % cov) else: self.cov = cov.upper() conv = conv.lower() if conv not in ["weights", "coefs", "dev", "sresid"]: raise ValueError("Convergence argument %s not understood" \ % conv) self.scale_est = scale_est wls_results = lm.WLS(self.endog, self.exog).fit() if not init: self.scale = self._estimate_scale(wls_results.resid) history = dict(params=[np.inf], scale=[]) if conv == 'coefs': criterion = history['params'] elif conv == 'dev': history.update(dict(deviance=[np.inf])) criterion = history['deviance'] elif conv == 'sresid': history.update(dict(sresid=[np.inf])) criterion = history['sresid'] elif conv == 'weights': history.update(dict(weights=[np.inf])) criterion = history['weights'] # done one iteration so update history = self._update_history(wls_results, history, conv) iteration = 1 converged = 0 while not converged: self.weights = self.M.weights(wls_results.resid / self.scale) wls_results = reg_tools._MinimalWLS(self.endog, self.exog, weights=self.weights, check_weights=True).fit() if update_scale is True: self.scale = self._estimate_scale(wls_results.resid) history = self._update_history(wls_results, history, conv) iteration += 1 converged = _check_convergence(criterion, iteration, tol, maxiter) results = RLMResults(self, wls_results.params, self.normalized_cov_params, self.scale) history['iteration'] = iteration results.fit_history = history results.fit_options = dict(cov=cov.upper(), scale_est=scale_est, norm=self.M.__class__.__name__, conv=conv) #norm is not changed in fit, no old state #doing the next causes exception #self.cov = self.scale_est = None #reset for additional fits #iteration and history could contain wrong state with repeated fit return RLMResultsWrapper(results)
def fit(self, maxiter=50, tol=1e-8, scale_est='mad', init=None, cov='H1', update_scale=True, conv='dev'): """ Fits the model using iteratively reweighted least squares. The IRLS routine runs until the specified objective converges to `tol` or `maxiter` has been reached. Parameters ---------- conv : string Indicates the convergence criteria. Available options are "coefs" (the coefficients), "weights" (the weights in the iteration), "sresid" (the standardized residuals), and "dev" (the un-normalized log-likelihood for the M estimator). The default is "dev". cov : string, optional 'H1', 'H2', or 'H3' Indicates how the covariance matrix is estimated. Default is 'H1'. See rlm.RLMResults for more information. init : string Specifies method for the initial estimates of the parameters. Default is None, which means that the least squares estimate is used. Currently it is the only available choice. maxiter : int The maximum number of iterations to try. Default is 50. scale_est : string or HuberScale() 'mad' or HuberScale() Indicates the estimate to use for scaling the weights in the IRLS. The default is 'mad' (median absolute deviation. Other options are 'HuberScale' for Huber's proposal 2. Huber's proposal 2 has optional keyword arguments d, tol, and maxiter for specifying the tuning constant, the convergence tolerance, and the maximum number of iterations. See statsmodels.robust.scale for more information. tol : float The convergence tolerance of the estimate. Default is 1e-8. update_scale : Bool If `update_scale` is False then the scale estimate for the weights is held constant over the iteration. Otherwise, it is updated for each fit in the iteration. Default is True. Returns ------- results : object statsmodels.rlm.RLMresults """ if not cov.upper() in ["H1","H2","H3"]: raise ValueError("Covariance matrix %s not understood" % cov) else: self.cov = cov.upper() conv = conv.lower() if not conv in ["weights","coefs","dev","sresid"]: raise ValueError("Convergence argument %s not understood" \ % conv) self.scale_est = scale_est wls_results = lm.WLS(self.endog, self.exog).fit() if not init: self.scale = self._estimate_scale(wls_results.resid) history = dict(params = [np.inf], scale = []) if conv == 'coefs': criterion = history['params'] elif conv == 'dev': history.update(dict(deviance = [np.inf])) criterion = history['deviance'] elif conv == 'sresid': history.update(dict(sresid = [np.inf])) criterion = history['sresid'] elif conv == 'weights': history.update(dict(weights = [np.inf])) criterion = history['weights'] # done one iteration so update history = self._update_history(wls_results, history, conv) iteration = 1 converged = 0 while not converged: self.weights = self.M.weights(wls_results.resid/self.scale) wls_results = reg_tools._MinimalWLS(self.endog, self.exog, weights=self.weights).fit() if update_scale is True: self.scale = self._estimate_scale(wls_results.resid) history = self._update_history(wls_results, history, conv) iteration += 1 converged = _check_convergence(criterion, iteration, tol, maxiter) results = RLMResults(self, wls_results.params, self.normalized_cov_params, self.scale) history['iteration'] = iteration results.fit_history = history results.fit_options = dict(cov=cov.upper(), scale_est=scale_est, norm=self.M.__class__.__name__, conv=conv) #norm is not changed in fit, no old state #doing the next causes exception #self.cov = self.scale_est = None #reset for additional fits #iteration and history could contain wrong state with repeated fit return RLMResultsWrapper(results)