numpy SciPy中的指数曲线拟合

owfi6suc  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(116)

我有两个NumPy数组xy。当我尝试使用指数函数和curve_fit(SciPy)来拟合我的数据时,

#!/usr/bin/env python
from pylab import *
from scipy.optimize import curve_fit

x = np.array([399.75, 989.25, 1578.75, 2168.25, 2757.75, 3347.25, 3936.75, 4526.25, 5115.75, 5705.25])
y = np.array([109,62,39,13,10,4,2,0,1,2])

def func(x, a, b, c, d):
    return a*np.exp(b-c*x)+d

popt, pcov = curve_fit(func, x, y)

我得到错误的系数popt

[a,b,c,d] = [1., 1., 1., 24.19999988]

有什么问题吗?

8ehkhllq

8ehkhllq1#

第一条评论:因为a*exp(b - c*x) = (a*exp(b))*exp(-c*x) = A*exp(-c*x)ab是冗余。我将删除b和用途:

import matplotlib.pyplot as plt

def func(x, a, c, d):
    return a*np.exp(-c*x)+d

这不是主要问题。问题很简单,当你使用默认的初始猜测(全是1)时,curve_fit无法收敛到这个问题的解。检查pcov;你会看到它是inf。这并不奇怪,因为如果c为1,则exp(-c*x)的大部分值下溢为0:

In [32]: np.exp(-x)
Out[32]: 
array([  2.45912644e-174,   0.00000000e+000,   0.00000000e+000,
         0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
         0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
         0.00000000e+000])

这表明c应该很小。一个更好的初始猜测是,比如说,p0 = (1, 1e-6, 1)。然后我得到:

In [36]: popt, pcov = curve_fit(func, x, y, p0=(1, 1e-6, 1))

In [37]: popt
Out[37]: array([  1.63561656e+02,   9.71142196e-04,  -1.16854450e+00])

这看起来很合理:

In [42]: xx = np.linspace(300, 6000, 1000)

In [43]: yy = func(xx, *popt)

In [44]: plt.plot(x, y, 'ko')
Out[44]: [<matplotlib.lines.Line2D at 0x41c5ad0>]

In [45]: plt.plot(xx, yy)
Out[45]: [<matplotlib.lines.Line2D at 0x41c5c10>]

z9gpfhce

z9gpfhce2#

首先,我建议将你的方程修改为a*np.exp(-c*(x-b))+d,否则指数将始终以x=0为中心,这可能并不总是如此。您还需要指定合理的初始条件(curve_fit的第4个参数指定[a,b,c,d]的初始条件)。
这段代码非常适合:

from pylab import *
from scipy.optimize import curve_fit

x = np.array([399.75, 989.25, 1578.75, 2168.25, 2757.75, 3347.25, 3936.75, 4526.25, 5115.75, 5705.25])
y = np.array([109,62,39,13,10,4,2,0,1,2])

def func(x, a, b, c, d):
    return a*np.exp(-c*(x-b))+d

popt, pcov = curve_fit(func, x, y, [100,400,0.001,0])
print popt

plot(x,y)
x=linspace(400,6000,10000)
plot(x,func(x,*popt))
show()

相关问题