我有两个列表,我试图以y = a * e ^(bx)之间的形式进行指数拟合。我正在使用类似于here的第二个答案的方法,但结果与我使用excel测试时所知的结果不符。这是我的代码:
import numpy as np
from scipy.optimize import curve_fit
exp_constants = [62.5, 87.5, 112.5, 137.5, 162.5, 187.5, 212.5, 237.5, 262.5, 287.5]
means = [211.94, 139.30, 80.09, 48.29, 26.94, 12.12, 3.99, 1.02, 0.09, 0.02]
def func(x1, a, b):
return a * np.exp(b * x1)
popt, pcov = curve_fit(func, exp_constants, means)
返回popt[0]
和popt[1]
时,我分别得到3.222e-127和1.0。但是,使用excel检查时,正确的指数方程应为y = 7231.3e ^( - 0.04x)。我对curve_fit方法不是很熟悉,我的代码中是否存在某些内容,或者是否有更好的方法来获得正确的指数拟合?
编辑:这是使用以下代码制作的情节:
plt.figure()
plt.plot(exp_constants, means, 'ko', label="Data")
plt.plot(exp_constants, func(exp_constants, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show
答案 0 :(得分:5)
我想问题是你没有提供参数的初始猜测,所以as per the manual,curve_fit
使用[1,1]作为猜测。然后,优化可能会陷入局部最小值。您应该做的另一件事是将xdata
和ydata
列表更改为numpy数组,如this answer所示:
import numpy as np
from scipy.optimize import curve_fit
exp_constants = np.array([62.5, 87.5, 112.5, 137.5, 162.5, 187.5, 212.5,
237.5, 262.5, 287.5])
means = np.array([211.94, 139.30, 80.09, 48.29, 26.94, 12.12, 3.99,
1.02, 0.09, 0.02])
def func(x1, a, b):
return a * np.exp(b * x1)
guess = [100, -0.1]
popt, pcov = curve_fit(func, exp_constants, means, p0 = guess)
猜测的确切值并不重要,但您应该至少具有数量级和符号,以便优化可以收敛到最佳值。我只是使用了一些接近正确答案的随机数字'你提到过。当您不知道猜测什么时,您可以执行polyfit(xdata, log(ydata), 1)
和一些基本数学运算来获得初始值,如this answer所示,您所关联的问题就会显示。
快速情节:
x = np.linspace(exp_constants[0], exp_constants[-1], 1000)
plt.plot(exp_constants, means, 'ko', x, popt[0]*np.exp(popt[1]*x), 'r')
plt.show()
结果: