How Does Fit
Work?¶
How does Fit
get from a (named) model and some data to a fit? Consider the following example:
from symfit.api import parameters, variables, Fit
a, b = parameters('a, b')
x, y = variables('x, y')
model = {y: a * x + b}
fit = Fit(model, x=x_data, y=y_data, sigma_y=sigma_data)
fit_result = fit.execute()
The first thing symfit
does is build \(\chi^2\) for your model:
chi_squared = sum((y - f)**2/sigmas[y]**2 for y, f in model.items())
In this line sigmas
is a defaultdict which contains all vars that where given a value, but returns 1 otherwise.
This \(\chi^2\) is then transformed into a python function which can then be used to do the numerical calculations:
vars, params = seperate_symbols(chi_squared)
py_chi_squared = lambdify(vars + params, chi_squared)
We are now almost there. Just two steps left. The first is to wrap all the data into the py_chi_squared
function using partial
into the function to be optimized:
from functools import partial
error = partial(py_chi_squared, **data_per_var)
where data_per_var
is a dict containing variable names: value pairs.
Now all that is left is to call leastsqbound
and have it find the best fit parameters:
best_fit_parameters, covariance_matrix = leastsqbound(
error,
self.guesses,
self.eval_jacobian,
self.bounds,
)
That’s it! Finally there are some steps to generate a FitResult object, but these are not important for our current discussion.
What if the model is unnamed?¶
Simple. Suppose our model had been the following:
model = a * x + b
fit = Fit(model, x=x_data, data=y_data, sigma=sigma_data)
fit_result = fit.execute()
symfit
will generate an extra variable in this case: data. Then the previous process will be applied.