I have run into a problem when I tried to curve fit some data. I got some errors, so I came back to the basics of the lmfit library. I tried to curve fit a simple example and I got the same problem.
import numpy
from lmfit import Model, Parameters
x = numpy.arange(1,20)
y = numpy.arange(1,20)*2
def funTE(x, coeff0, coeff1):
return x * coeff0 + coeff1
model = Model(funTE, independent_vars=['x'], param_names=["coeff0", "coeff1"])
params = Parameters()
params.add("coeff0", vary=True)
params.add("coeff1", vary=True)
result = model.fit(data=y[:], param=params, x=x[:])
This error occurred:
ValueError: The model function generated NaN values and the fit aborted! Please check your model function and/or set boundaries on parameters where applicable. In cases like this, using "nan_policy='omit'" will probably not work.
If any of you might know how I can fix this, I would greatly appreciate it (already lost quite some time on it).
First things first, you have a typo in the last line. The parameters argument is actually called params
. The typo comes up as a warning, which is easy to miss in this case, considering the rest of the traceback.
Onto your actual problem. By not assigning a starting value for your parameters, they default to -inf, which is what causes the NaN. When you don't set an initial value, it will default to the lower bound the parameter can get, which if also not defined will default to -inf. I am surprised the documentation doesn't draw your attention to that fact with huge red arrows and circles. Or at least throw a warning when a parameter is created with an initial value of infinity.
The fix
params = Parameters()
params.add("coeff0", value=0)
params.add("coeff1", value=0)
# Typo fixed!
result = model.fit(data=y, params=params, x=x)
You could also let the model automatically generate the parameters, but you must provide an initial value as above to avoid the same infinity problem.
params = model.make_params(coeff0=0, coeff1=0)
By the way, if the params
argument is not defined, the script will internally generate the parameters with model.make_params()
, which will cause all initial values to be -inf as mentioned above.
In a more general scenario where one has defined the initial values and they still get NaN, there is likely an issue with the model which must be addressed, e.g., division by 0, roots/logarithms of negative numbers, large values that cause overflow, etc.