值错误:输入包含nan值-来自lmfit模型,尽管输入不包含NaN。

8

我正在尝试使用lmfit (文档链接)构建一个模型,但我似乎无法找出为什么在尝试拟合模型时不断收到ValueError:The input contains nan values的原因。

from lmfit import minimize, Minimizer, Parameters, Parameter, report_fit, Model
import numpy as np

def cde(t, Qi, at, vw, R, rhob_cb, al, d, r):
    # t (time), is the independent variable
    return Qi / (8 * np.pi * ((at * vw)/R) * t * rhob_cb * (np.sqrt(np.pi * ((al * vw)/R * t))))  * \
        np.exp(- (R * (d - (t * vw)/ R)**2) / (4 * (al * vw) * t) - (R * r**2)/ (4 * (at * vw) * t))

model_cde =  Model(cde)


# Allowed to vary
model_cde.set_param_hint('vw', value =10**-4, min=0.000001)
model_cde.set_param_hint('d', value = -0.038, min = 0.0001)
model_cde.set_param_hint('r', value = 5.637e-10)
model_cde.set_param_hint('at', value =0.1)
model_cde.set_param_hint('al', value =0.15)

# Fixed
model_cde.set_param_hint('Qi', value = 1000, vary = False)
model_cde.set_param_hint('R', value =1.7, vary = False)
model_cde.set_param_hint('rhob_cb', value =3000, vary = False)

# test data
data = [ 1.37,  1.51,  1.65,  1.79,  1.91,  2.02,  2.12,  2.2 ,
        2.27,  2.32,  2.36,  2.38,  2.4 ,  2.41,  2.42,  2.41,  2.4 ,
        2.39,  2.37,  2.35,  2.33,  2.31,  2.29,  2.26,  2.23,  2.2 ,
        2.17,  2.14,  2.11,  2.08,  2.06,  2.02,  1.99,  1.97,  1.94,
        1.91,  1.88,  1.85,  1.83,  1.8 ,  1.78,  1.75,  1.72,  1.7 ,
        1.68,  1.65,  1.63,  1.61,  1.58]

time = list(range(5,250,5))

model_cde.fit(data, t= time)

会产生以下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-16-785fcc6a994b> in <module>()
----> 1 model_cde.fit(data, t= time)

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/model.py in fit(self, data, params, weights, method, iter_cb, scale_covar, verbose, fit_kws, **kwargs)
    539                              scale_covar=scale_covar, fcn_kws=kwargs,
    540                              **fit_kws)
--> 541         output.fit(data=data, weights=weights)
    542         output.components = self.components
    543         return output

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/model.py in fit(self, data, params, weights, method, **kwargs)
    745         self.init_fit    = self.model.eval(params=self.params, **self.userkws)
    746 
--> 747         _ret = self.minimize(method=self.method)
    748 
    749         for attr in dir(_ret):

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/minimizer.py in minimize(self, method, params, **kws)
   1240                     val.lower().startswith(user_method)):
   1241                     kwargs['method'] = val
-> 1242         return function(**kwargs)
   1243 
   1244 

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/minimizer.py in leastsq(self, params, **kws)
   1070         np.seterr(all='ignore')
   1071 
-> 1072         lsout = scipy_leastsq(self.__residual, vars, **lskws)
   1073         _best, _cov, infodict, errmsg, ier = lsout
   1074         result.aborted = self._abort

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/scipy/optimize/minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    385             maxfev = 200*(n + 1)
    386         retval = _minpack._lmdif(func, x0, args, full_output, ftol, xtol,
--> 387                                  gtol, maxfev, epsfcn, factor, diag)
    388     else:
    389         if col_deriv:

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/minimizer.py in __residual(self, fvars, apply_bounds_transformation)
    369 
    370         out = self.userfcn(params, *self.userargs, **self.userkws)
--> 371         out = _nan_policy(out, nan_policy=self.nan_policy)
    372 
    373         if callable(self.iter_cb):

/home/bprodz/.virtualenvs/phd_dev/lib/python3.5/site-packages/lmfit/minimizer.py in _nan_policy(a, nan_policy, handle_inf)
   1430 
   1431         if contains_nan:
-> 1432             raise ValueError("The input contains nan values")
   1433         return a
   1434 

ValueError: The input contains nan values

然而,以下检查NaN值的结果证实我的数据中没有NaN值:
print(np.any(np.isnan(data)), np.any(np.isnan(time)))
False False

到目前为止,我已经尝试将data和/或time中的一个或两个从列表转换为numpy ndarrays,删除第0个时间步长(以防出现除以0的错误),明确指定t为独立变量并允许所有变量变化。然而,这些方法都会引发同样的错误。 有人有什么想法是什么原因导致了这个错误吗?谢谢。

1
我不知道为什么会发生这种情况,但如果你使用 time = np.arange(.5,25.,.5),它似乎可以工作。你选择的时间值中必须存在某种非法操作。 - zarak
@zarak 你还改了别的吗?我还是遇到同样的错误。谢谢。 - Jason
1
很奇怪。我完全复制并粘贴了你的代码,直到你分配 time 变量的地方。你尝试在新会话中开始吗?也许一些变量被遮蔽了。 - zarak
@zarak 我开始了一个新的会话,现在它可以工作了,谢谢。 (Jupyter Notebook的重新启动内核似乎没有清除所有内容)我还尝试了 np.arange(5., 25., 5.),以防与整数/浮点数有关,但仍然出现了与之前相同的错误。我想我会继续尝试找到解决方案...如果失败的话,也许我需要在整个数据中更改单位。 - Jason
1
@zarak,你的第一条评论说得很对。似乎我的模型中有错误,导致一些负值被传递给np.sqrt,默认情况下会将它们评估为nan - Jason
我的也是一样,直到我添加了初始猜测...然后就像魔术一样工作了。似乎可以抛出更好的错误? - David Hagan
1个回答

3

我尝试使用scipy.optimize.curve_fit拟合我的模型,但出现以下错误:

/home/bprodz/.virtualenvs/phd_dev/lib/python3.4/site-packages/ipykernel/__main__.py:3: RuntimeWarning: invalid value encountered in sqrt
  app.launch_new_instance()

这表明我的模型会生成一些负数,导致np.sqrt()出现问题。当给 np.sqrt() 一个负数时,默认行为是输出nan,就像这个问题所述的那样。注意,如果给np.sqrt()一个负数,它可以被设置为引发错误,方法是:np.seterr(all='raise') , 可从此处获得更多信息。
提示:我还在lmfit谷歌小组中寻求帮助,并收到以下有用建议
  • 考虑将长公式分成较短的部分,以便更容易进行故障排除
  • 使用Model.eval()测试运行模型函数时某些参数的输出
  • np.ndarray 在这些(数值)情况下通常优于 python列表

非常感谢这些有用的提示,并跟进! - zarak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接