scipy curve_fit错误:遇到零除零

时间:2013-11-23 11:46:35

标签: python scipy runtime-error curve-fitting

我一直在尝试使用scipy.optimize.curve_fit将函数拟合到某些数据:

from __future__ import (print_function,
                    division,
                    unicode_literals,
                    absolute_import)
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as mpl
x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,     20, 21, 22, 23, 24, 25, 26, 27, 28, 29])
y = np.array([20.8, 20.9, 22.9, 25.2, 26.9, 28.3, 29.5, 30.7, 31.8, 32.9, 34.0, 35.3, 36.4, 37.5, 38.6, 39.6, 40.6, 41.6, 42.5, 43.2, 44.2, 45.0, 45.8, 46.5, 47.3, 48.0, 48.6, 49.2, 49.8, 50.4])
def f(x, a, b, c):
    return a/(1+b*x**c)
popt, pcov = curve_fit(f, x, y)
print(popt, np.sqrt(np.diag(pcov)), sep='\n')

但总会出现错误:

RuntimeWarning: divide by zero encountered in power
return a/(1+b*x**c)

也许有人可以帮我避免它? 任何帮助将非常感激。干杯!

2 个答案:

答案 0 :(得分:5)

好吧,两个有用的技巧。

1,将0中的x替换为一些非常小的数字,例如1e-8(不要笑,R中的核心包实际上是这是由his name shall not be spoken撰写的,人们一直都在使用它。) 实际上我根本没有得到你的RuntimeWarning。我正在运行scipy 0.12.0numpy 1.7.1。也许这取决于版本。

但我们会非常不合适:

In [41]: popt, pcov
Out[41]: (array([  3.90107143e+01,  -3.08698757e+07,  -1.52971609e+02]), inf)

因此,技巧2,我们定义f函数,而不是优化g函数:

In [38]: def g(x, a, b, c):
   ....:     return b/a*x**c+1/a
   ....:

In [39]: curve_fit(g, x, 1/y) #Better fit
Out[39]:
(array([ 19.76748582,  -0.14499508,   0.44206688]),
 array([[ 0.29043958,  0.00899521,  0.01650935],
        [ 0.00899521,  0.00036082,  0.00070345],
        [ 0.01650935,  0.00070345,  0.00140253]]))

我们现在可以使用生成的参数向量作为起始向量来优化f()。由于curve_fit是非线性最小二乘法,参数优化g()不一定是参数优化f(),但希望它会接近。协方差矩阵当然是非常不同的。

In [78]: curve_fit(f, x, y, p0=curve_fit(g, x, 1/y)[0]) #Alternative Fit
Out[78]:
(array([ 18.0480446 ,  -0.22881647,   0.31200106]),
 array([[ 1.14928169,  0.03741604,  0.03897652],
        [ 0.03741604,  0.00128511,  0.00136315],
        [ 0.03897652,  0.00136315,  0.00145614]]))

结果的比较:

enter image description here

现在结果非常好。

答案 1 :(得分:4)

您的x值从0开始。如果由于某种原因,参数c在计算过程中为负,那么您将评估0上升为负指数,即除以零:对于{{1}我们有

p>0