我有两个列表,我试图在它们之间进行 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
最佳答案
我想问题是你没有提供参数的初始猜测,所以 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()
结果:
关于python - 两个列表之间的指数拟合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28414012/