| LMFIT | Contents | Download |
| Non-Linear Least-Squares Minimization and Curve-Fitting for Python | FAQ | Develop |

# Performing Fits, Analyzing Outputs

As shown in the previous chapter, a simple fit can be performed with the `minimize()` function. For more sophisticated modeling, the `Minimizer` class can be used to gain a bit more control, especially when using complicated constraints or comparing results from related fits.

Warning

Upgrading scripts from version 0.8.3 to 0.9.0? See Version 0.9.0 Release Notes

## The `minimize()` function

The `minimize()` function is a wrapper around `Minimizer` for running an optimization problem. It takes an objective function (the function that calculates the array to be minimized), a `Parameters` object, and several optional arguments. See Writing a Fitting Function for details on writing the objective.

`minimize`(function, params[, args=None[, kws=None[, method='leastsq'[, scale_covar=True[, iter_cb=None[, **fit_kws]]]]]])

  find values for the `params` so that the sum-of-squares of the array returned from `function` is minimized.

  Parameters:

  - function (callable.) – function to return fit residual. See Writing a Fitting Function for details.
  - params (`Parameters`.) – a `Parameters` dictionary. Keywords must be strings that match `[a-z_][a-z0-9_]*` and cannot be a python reserved word. Each value must be `Parameter`.
  - args (tuple) – arguments tuple to pass to the residual function as positional arguments.
  - kws (dict) – dictionary to pass to the residual function as keyword arguments.
  - method (string (default `leastsq`)) – name of fitting method to use. See Choosing Different Fitting Methods for details
  - scale_covar (bool (default `True`)) – whether to automatically scale covariance matrix (`leastsq` only)
  - iter_cb (callable or `None`) – function to be called at each fit iteration. See Using a Iteration Callback Function for details.
  - fit_kws (dict) – dictionary to pass to `scipy.optimize.leastsq()` or `scipy.optimize.minimize()`.

  Returns: | `MinimizerResult` instance, which will contain the optimized parameter, and several goodness-of-fit statistics.

Changed in version 0.9.0: return value changed to `MinimizerResult`

On output, the params will be unchanged. The best-fit values, and where appropriate, estimated uncertainties and correlations, will all be contained in the returned `MinimizerResult`. See MinimizerResult – the optimization result for further details.

For clarity, it should be emphasized that this function is simply a wrapper around `Minimizer` that runs a single fit, implemented as:

    fitter = Minimizer(fcn, params, fcn_args=args, fcn_kws=kws,
                       iter_cb=iter_cb, scale_covar=scale_covar, **fit_kws)
    return fitter.minimize(method=method)

## Writing a Fitting Function

An important component of a fit is writing a function to be minimized – the objective function. Since this function will be called by other routines, there are fairly stringent requirements for its call signature and return value. In principle, your function can be any python callable, but it must look like this:

`func(params, *args, **kws):`

  calculate objective residual to be minimized from parameters.

  Parameters:

  - params (`Parameters`.) – parameters.
  - args – positional arguments. Must match `args` argument to `minimize()`
  - kws – keyword arguments. Must match `kws` argument to `minimize()`

  Returns: | residual array (generally data-model) to be minimized in the least-squares sense.
  Return type: | numpy array. The length of this array cannot change between calls.

A common use for the positional and keyword arguments would be to pass in other data needed to calculate the residual, including such things as the data array, dependent variable, uncertainties in the data, and other data structures for the model calculation.

The objective function should return the value to be minimized. For the Levenberg-Marquardt algorithm from `leastsq()`, this returned value must be an array, with a length greater than or equal to the number of fitting variables in the model. For the other methods, the return value can either be a scalar or an array. If an array is returned, the sum of squares of the array will be sent to the underlying fitting method, effectively doing a least-squares optimization of the return values.

Since the function will be passed in a dictionary of `Parameters`, it is advisable to unpack these to get numerical values at the top of the function. A simple way to do this is with `Parameters.valuesdict()`, as with:

    def residual(pars, x, data=None, eps=None):
        # unpack parameters:
        #  extract .value attribute for each parameter
        parvals = pars.valuesdict()
        period = parvals['period']
        shift = parvals['shift']
        decay = parvals['decay']

        if abs(shift) > pi/2:
            shift = shift - sign(shift)*pi

        if abs(period) < 1.e-10:
            period = sign(period)*1.e-10

        model = parvals['amp'] * sin(shift + x/period) * exp(-x*x*decay*decay)

        if data is None:
            return model
        if eps is None:
            return (model - data)
        return (model - data)/eps

In this example, `x` is a positional (required) argument, while the `data` array is actually optional (so that the function returns the model calculation if the data is neglected). Also note that the model calculation will divide `x` by the value of the ‘period’ Parameter. It might be wise to ensure this parameter cannot be 0. It would be possible to use the bounds on the `Parameter` to do this:

    params['period'] = Parameter(value=2, min=1.e-10)

but putting this directly in the function with:

    if abs(period) < 1.e-10:
        period = sign(period)*1.e-10

is also a reasonable approach. Similarly, one could place bounds on the `decay` parameter to take values only between `-pi/2` and `pi/2`.

## Choosing Different Fitting Methods

By default, the Levenberg-Marquardt algorithm is used for fitting. While often criticized, including the fact it finds a local minima, this approach has some distinct advantages. These include being fast, and well-behaved for most curve-fitting needs, and making it easy to estimate uncertainties for and correlations between pairs of fit variables, as discussed in MinimizerResult – the optimization result.

Alternative algorithms can also be used by providing the `method` keyword to the `minimize()` function or `Minimizer.minimize()` class as listed in the Table of Supported Fitting Methods.

> Table of Supported Fitting Method, eithers:

> Fitting Method | `method` arg to `minimize()` or `Minimizer.minimize()`
> --- | ---
> Levenberg-Marquardt | `leastsq`
> Nelder-Mead | `nelder`
> L-BFGS-B | `lbfgsb`
> Powell | `powell`
> Conjugate Gradient | `cg`
> Newton-CG | `newton`
> COBYLA | `cobyla`
> Truncated Newton | `tnc`
> Dogleg | `dogleg`
> Sequential Linear Squares Programming | `slsqp`
> Differential Evolution | `differential_evolution`

Note

The objective function for the Levenberg-Marquardt method must return an array, with more elements than variables. All other methods can return either a scalar value or an array.

Warning

Much of this documentation assumes that the Levenberg-Marquardt method is the method used. Many of the fit statistics and estimates for uncertainties in parameters discussed in MinimizerResult – the optimization result are done only for this method.

## `MinimizerResult` – the optimization result

class `MinimizerResult`(**kws)

New in version 0.9.0.

An optimization with `minimize()` or `Minimizer.minimize()` will return a `MinimizerResult` object. This is an otherwise plain container object (that is, with no methods of its own) that simply holds the results of the minimization. These results will include several pieces of informational data such as status and error messages, fit statistics, and the updated parameters themselves.

Importantly, the parameters passed in to `Minimizer.minimize()` will be not be changed. To to find the best-fit values, uncertainties and so on for each parameter, one must use the `MinimizerResult.params` attribute.

`params`

  the `Parameters` actually used in the fit, with updated values, `stderr` and `correl`.

`var_names`

  ordered list of variable parameter names used in optimization, and useful for understanding the the values in `init_vals` and `covar`.

`covar`

  covariance matrix from minimization (leastsq only), with rows/columns using `var_names`.

`init_vals`

  list of initial values for variable parameters using `var_names`.

`nfev`

  number of function evaluations

`success`

  boolean (`True`/`False`) for whether fit succeeded.

`errorbars`

  boolean (`True`/`False`) for whether uncertainties were estimated.

`message`

  message about fit success.

`ier`

  integer error value from `scipy.optimize.leastsq()` (leastsq only).

`lmdif_message`

  message from `scipy.optimize.leastsq()` (leastsq only).

`nvarys`

  number of variables in fit \(N_{\rm varys}\)

`ndata`

  number of data points: \(N\)

`nfree ``

  degrees of freedom in fit: \(N - N_{\rm varys}\)

`residual`

  residual array, return value of `func()`: \({\rm Resid}\)

`chisqr`

  chi-square: \(\chi^2 = \sum_i^N [{\rm Resid}_i]^2\)

`redchi`

  reduced chi-square: \(\chi^2_{\nu}= {\chi^2} / {(N - N_{\rm varys})}\)

`aic`

  Akaike Information Criterion statistic (see below)

`bic`

  Bayesian Information Criterion statistic (see below).

### Goodness-of-Fit Statistics

> Table of Fit Results: These values, including the standard Goodness-of-Fit statistics, are all attributes of the `MinimizerResult` object returned by `minimize()` or `Minimizer.minimize()`.

Attribute Name | Description / Formula
--- | ---
nfev | number of function evaluations
nvarys | number of variables in fit \(N_{\rm varys}\)
ndata | number of data points: \(N\)
nfree ` | degrees of freedom in fit: \(N - N_{\rm varys}\)
residual | residual array, return value of `func()`: \({\rm Resid}\)
chisqr | chi-square: \(\chi^2 = \sum_i^N [{\rm Resid}_i]^2\)
redchi | reduced chi-square: \(\chi^2_{\nu}= {\chi^2} / {(N - N_{\rm varys})}\)
aic | Akaike Information Criterion statistic (see below)
bic | Bayesian Information Criterion statistic (see below)
var_names | ordered list of variable parameter names used for init_vals and covar
covar | covariance matrix (with rows/columns using var_names
init_vals | list of initial values for variable parameters

Note that the calculation of chi-square and reduced chi-square assume that the returned residual function is scaled properly to the uncertainties in the data. For these statistics to be meaningful, the person writing the function to be minimized must scale them properly.

After a fit using using the `leastsq()` method has completed successfully, standard errors for the fitted variables and correlations between pairs of fitted variables are automatically calculated from the covariance matrix. The standard error (estimated \(1\sigma\) error-bar) go into the `stderr` attribute of the Parameter. The correlations with all other variables will be put into the `correl` attribute of the Parameter – a dictionary with keys for all other Parameters and values of the corresponding correlation.

In some cases, it may not be possible to estimate the errors and correlations. For example, if a variable actually has no practical effect on the fit, it will likely cause the covariance matrix to be singular, making standard errors impossible to estimate. Placing bounds on varied Parameters makes it more likely that errors cannot be estimated, as being near the maximum or minimum value makes the covariance matrix singular. In these cases, the `errorbars` attribute of the fit result (`Minimizer` object) will be `False`.

### Akaike and Bayesian Information Criteria

The `MinimizerResult` includes the tradtional chi-square and reduced chi-square statistics:

\[\begin{eqnarray*} \chi^2 &=& \sum_i^N r_i^2 \\ \chi^2_\nu &=& = \chi^2 / (N-N_{\rm varys}) \end{eqnarray*}\]

where \(r\) is the residual array returned by the objective function (likely to be `(data-model)/uncertainty` for data modeling usages), \(N\) is the number of data points (`ndata`), and \(N_{\rm varys}\) is number of variable parameters.

Also included are the Akaike Information Criterion, and Bayesian Information Criterion statistics, held in the `aic` and `bic` attributes, respectively. These give slightly different measures of the relative quality for a fit, trying to balance quality of fit with the number of variable parameters used in the fit. These are calculated as

\[\begin{eqnarray*} {\rm aic} &=& N \ln(\chi^2/N) + 2 N_{\rm varys} \\ {\rm bic} &=& N \ln(\chi^2/N) + \ln(N) *N_{\rm varys} \\ \end{eqnarray*}\]

When comparing fits with different numbers of varying parameters, one typically selects the model with lowest reduced chi-square, Akaike information criterion, and/or Bayesian information criterion. Generally, the Bayesian information criterion is considered the most conservative of these statistics.

## Using a Iteration Callback Function

An iteration callback function is a function to be called at each iteration, just after the objective function is called. The iteration callback allows user-supplied code to be run at each iteration, and can be used to abort a fit.

`iter_cb(params, iter, resid, *args, **kws):`

  user-supplied function to be run at each iteration

  Parameters:

  - params (`Parameters`.) – parameters.
  - iter (integer) – iteration number
  - resid (ndarray) – residual array.
  - args – positional arguments. Must match `args` argument to `minimize()`
  - kws – keyword arguments. Must match `kws` argument to `minimize()`

  Returns: | residual array (generally data-model) to be minimized in the least-squares sense.
  Return type: | `None` for normal behavior, any value like `True` to abort fit.

Normally, the iteration callback would have no return value or return `None`. To abort a fit, have this function return a value that is `True` (including any non-zero integer). The fit will also abort if any exception is raised in the iteration callback. When a fit is aborted this way, the parameters will have the values from the last iteration. The fit statistics are not likely to be meaningful, and uncertainties will not be computed.

## Using the `Minimizer` class

For full control of the fitting process, you’ll want to create a `Minimizer` object.

class `Minimizer`(function, params, fcn_args=None, fcn_kws=None, iter_cb=None, scale_covar=True, **kws)

  creates a Minimizer, for more detailed access to fitting methods and attributes.

  Parameters:

  - function (callable.) – objective function to return fit residual. See Writing a Fitting Function for details.
  - params (dict) – a dictionary of Parameters. Keywords must be strings that match `[a-z_][a-z0-9_]*` and is not a python reserved word. Each value must be `Parameter`.
  - fcn_args (tuple) – arguments tuple to pass to the residual function as positional arguments.
  - fcn_kws (dict) – dictionary to pass to the residual function as keyword arguments.
  - iter_cb (callable or `None`) – function to be called at each fit iteration. See Using a Iteration Callback Function for details.
  - scale_covar – flag for automatically scaling covariance matrix and uncertainties to reduced chi-square (`leastsq` only)
  - kws (dict) – dictionary to pass as keywords to the underlying `scipy.optimize` method.

The Minimizer object has a few public methods:

`minimize`(method='leastsq', params=None, **kws)

  perform fit using either `leastsq()` or `scalar_minimize()`.

  Parameters:

  - method (str.) – name of fitting method. Must be one of the naemes in Table of Supported Fitting Methods
  - params (`Parameters` or None) – a `Parameters` dictionary for starting values

  Returns: | `MinimizerResult` object, containing updated parameters, fitting statistics, and information.

Changed in version 0.9.0: return value changed to `MinimizerResult`

Additonal keywords are passed on to the correspond `leastsq()` or `scalar_minimize()` method.

`leastsq`(params=None, scale_covar=True, **kws)

  perform fit with Levenberg-Marquardt algorithm. Keywords will be passed directly to `scipy.optimize.leastsq()`. By default, numerical derivatives are used, and the following arguments are set:

  > `leastsq()` arg | Default Value | Description
  > --- | --- | ---
  > xtol | 1.e-7 | Relative error in the approximate solution
  > ftol | 1.e-7 | Relative error in the desired sum of squares
  > maxfev | 2000*(nvar+1) | maximum number of function calls (nvar= # of variables)
  > Dfun | `None` | function to call for Jacobian calculation

Changed in version 0.9.0: return value changed to `MinimizerResult`

`scalar_minimize`(method='Nelder-Mead', params=None, hess=None, tol=None, **kws)

  perform fit with any of the scalar minimization algorithms supported by `scipy.optimize.minimize()`.

  > `scalar_minimize()` arg | Default Value | Description
  > --- | --- | ---
  > method | `Nelder-Mead` | fitting method
  > tol | 1.e-7 | fitting and parameter tolerance
  > hess | None | Hessian of objective function

Changed in version 0.9.0: return value changed to `MinimizerResult`

`prepare_fit`(**kws)

  prepares and initializes model and Parameters for subsequent fitting. This routine prepares the conversion of `Parameters` into fit variables, organizes parameter bounds, and parses, “compiles” and checks constrain expressions. The method also creates and returns a new instance of a `MinimizerResult` object that contains the copy of the Parameters that will actually be varied in the fit.

  This method is called directly by the fitting methods, and it is generally not necessary to call this function explicitly.

Changed in version 0.9.0: return value changed to `MinimizerResult`

## Getting and Printing Fit Reports

`fit_report`(result, modelpars=None, show_correl=True, min_correl=0.1)

  generate and return text of report of best-fit values, uncertainties, and correlations from fit.

  Parameters:

  - result – `MinimizerResult` object as returned by `minimize()`.
  - modelpars – Parameters with “Known Values” (optional, default None)
  - show_correl – whether to show list of sorted correlations [`True`]
  - min_correl – smallest correlation absolute value to show [0.1]

  If the first argument is a `Parameters` object, goodness-of-fit statistics will not be included.

`report_fit`(result, modelpars=None, show_correl=True, min_correl=0.1)

  print text of report from `fit_report()`.

An example fit with report would be

which would write out:

    [[Fit Statistics]]
        # function evals   = 85
        # data points      = 1001
        # variables        = 4
        chi-square         = 498.812
        reduced chi-square = 0.500
    [[Variables]]
        amp:      13.9121944 +/- 0.141202 (1.01%) (init= 13)
        period:   5.48507044 +/- 0.026664 (0.49%) (init= 2)
        shift:    0.16203677 +/- 0.014056 (8.67%) (init= 0)
        decay:    0.03264538 +/- 0.000380 (1.16%) (init= 0.02)
    [[Correlations]] (unreported correlations are <  0.100)
        C(period, shift)             =  0.797
        C(amp, decay)                =  0.582
        C(amp, shift)                = -0.297
        C(amp, period)               = -0.243
        C(shift, decay)              = -0.182
        C(period, decay)             = -0.150