'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'

def fit(self, maxiter=50, tol=1e-08, scale_est='mad', init=None, cov='H1', update_scale=True, conv='dev'):

    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']
    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)
    return RLMResultsWrapper(results)
