Fit result doens't give back parameter errors

265 views
Skip to first unread message

Giovanni Volta

unread,
Mar 30, 2020, 4:58:36 AM3/30/20
to lmfi...@googlegroups.com
I am fitting a dataset with a composite model. The fit works well but I am not able to get back the errors on the parameter.
Here below I am posting few lines of the code.
It might be an obvious error but I am not able to figure out. Do you have any comments/suggestios?


gauss_exp = lm.models.ExponentialGaussianModel(prefix='gexp_')
box = lm.models.RectangleModel(prefix='box_', form='logistic')
linear = lm.models.ConstantModel(prefix='flat_')

template = gauss_exp + box + linear

template.set_param_hint('gexp_amplitude', value=5.5, min=5, max=6.5)
template.set_param_hint('gexp_center', value=152, min=145, max=160)
template.set_param_hint('gexp_sigma', value=5, min=3, max=5.5)
template.set_param_hint('gexp_gamma', value=0.09999, min=0.07, max=1.01)

template.set_param_hint('box_amplitude', value=0.87e-2, min=0.7e-2, max=1.1e-2)
template.set_param_hint('box_center1', value=127.772182, min=115, max=135, vary=True)
template.set_param_hint('box_sigma1', value=9.35035299, min=8, max=25, vary=True)
template.set_param_hint('box_center2', value=325, min=310, max=335)
template.set_param_hint('box_sigma2', value=10, min=3, max=20)

template.set_param_hint('flat_c', value=4e-3, min=3e-3, max=6e-3)

mask = np.where((x>80)&(x<400))
result_fit = template.fit(data=y_norm[mask], x=x[mask], weights=1.0/y_err_norm[mask], nan_policy='raise', verbose=True)
dely = result_fit.eval_uncertainty(x=x[mask])

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-151-7f32b3c77b72> in <module>
      1 mask = np.where((x>80)&(x<400))
      2 result_fit = template.fit(data=y_norm[mask], x=x[mask], weights=1.0/y_err_norm[mask], nan_policy='raise', verbose=True)
----> 3 dely = result_fit.eval_uncertainty(x=x[mask])

~/.local/lib/python3.6/site-packages/lmfit/model.py in eval_uncertainty(self, params, sigma, **kwargs)
   1486             pname = self.var_names[i]
   1487             val0 = pars[pname].value
-> 1488             dval = pars[pname].stderr/3.0
   1489 
   1490             pars[pname].value = val0 + dval

TypeError: unsupported operand type(s) for /: 'NoneType' and 'float'


Matt Newville

unread,
Mar 30, 2020, 9:08:57 AM3/30/20
to lmfit-py
Giovanni,
Well, if the uncertainties in the best-fit parameters cannot be estimated, then the `stderr` attribute will be `None`, which would explain the exception you are seeing.   You are asking to evaluate the uncertainties in the model when the uncertainties in the parameters are not known - that is the error.

So, you'll want to check why the uncertainties could not be estimated.  

Your example does not print out the fit report.  That would have shown that uncertainties could not be estimated, and may have given hints about why. 
I cannot help but notice that you set rather tight and specific bounds on every single parameter.   I would strongly suspect that at least one of your parameters has hit a boundary, making uncertainties hard (and often impossible) to estimate. 

Without knowing anything about the problem or sort of data you are working with, let me state clearly some general advice:  Do NOT place tight bounds on parameters.  First and foremost, use bounds to prevent physically meaningless results.  Secondarily, use them to prevent values from drifting way off scale.   If you are doing anything like
 
      template.set_param_hint('gexp_amplitude', value=5.5, min=5, max=6.5)

you should *definitely* know that a value below 5 or above 6.5 makes no sense.   I very much that this is actually the case for all of your parameters.

--Matt

Renee Otten

unread,
Mar 30, 2020, 9:24:16 AM3/30/20
to lmfi...@googlegroups.com
hi Giovanni, 


you don’t show the output of the fit using, for example, lm.report_fit(result_fit). The error message indeeds tells you that the “stderr” is not determined and is None. Ideally looking at the fit result will tell you why, but if I had to guess though I suspect it is because you have very tight boundaries on the parameters. 

As a side note, I don’t think your use of set_param_hint is really intended like that (these are only used when you call “make_params” afterwards. Typically, one would just initialize a Parameter class and then set initial values/boundaries and such. For example like:

gauss_exp = lm.models.ExponentialGaussianModel(prefix='gexp_')
box = lm.models.RectangleModel(prefix='box_', form='logistic')
linear = lm.models.ConstantModel(prefix='flat_')

template = gauss_exp + box + linear
pars = template.make_params()

pars[‘gexp_amplitude’].set(value=5.5, min=5, max=6.5)
etcetera

Hope this helps, 
Renee


On Mar 30, 2020, at 4:58 AM, Giovanni Volta <gvol...@gmail.com> wrote:

I am fitting a dataset with a composite model. The fit works well but I am not able to get back the errors on the parameter.
Here below I am posting few lines of the code.

It might be an obvious error but I am not able to figure out. Do you have any comments/suggestions?


--
You received this message because you are subscribed to the Google Groups "lmfit-py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lmfit-py+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lmfit-py/4c179ca0-5b86-4493-9e63-ef740b0f67bd%40googlegroups.com.

Giovanni Volta

unread,
Mar 31, 2020, 5:30:00 AM3/31/20
to lmfit-py
Hi Matt,

thank you so much the reply.

Giovanni,
Well, if the uncertainties in the best-fit parameters cannot be estimated, then the `stderr` attribute will be `None`, which would explain the exception you are seeing.   You are asking to evaluate the uncertainties in the model when the uncertainties in the parameters are not known - that is the error.

So, you'll want to check why the uncertainties could not be estimated.  

You were right, few parameters reached the boundary and then the errors were impossible to compute.
 
Without knowing anything about the problem or sort of data you are working with, let me state clearly some general advice:  Do NOT place tight bounds on parameters.  First and foremost, use bounds to prevent physically meaningless results.  Secondarily, use them to prevent values from drifting way off scale.   If you are doing anything like
 
      template.set_param_hint('gexp_amplitude', value=5.5, min=5, max=6.5)

you should *definitely* know that a value below 5 or above 6.5 makes no sense.   I very much that this is actually the case for all of your parameters.

 I will remember your advice for the future. Thank you again.

Giovanni

Giovanni Volta

unread,
Mar 31, 2020, 5:33:13 AM3/31/20
to lmfit-py
Hi Reene,

hi Giovanni, 


you don’t show the output of the fit using, for example, lm.report_fit(result_fit). The error message indeeds tells you that the “stderr” is not determined and is None. Ideally looking at the fit result will tell you why, but if I had to guess though I suspect it is because you have very tight boundaries on the parameters. 

Indeed you right, the report_fit didn't show any errors.


As a side note, I don’t think your use of set_param_hint is really intended like that (these are only used when you call “make_params” afterwards. Typically, one would just initialize a Parameter class and then set initial values/boundaries and such. For example like:

gauss_exp = lm.models.ExponentialGaussianModel(prefix='gexp_')
box = lm.models.RectangleModel(prefix='box_', form='logistic')
linear = lm.models.ConstantModel(prefix='flat_')

template = gauss_exp + box + linear
pars = template.make_params()

pars[‘gexp_amplitude’].set(value=5.5, min=5, max=6.5)
etcetera

Using make_params() and set() it is better. Now it compute the errors. Thank you.
Giovanni
Reply all
Reply to author
Forward
0 new messages