两个列表之间的指数拟合
Exponential Fit Between 2 Lists
我有两个列表,我试图在它们之间进行 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
uses [1, 1] as a guess. The optimization might then get stuck at some local minimum. One other thing you should do is to change your xdata
and ydata
lists to numpy arrays, as shown by 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)
猜测的确切值并不重要,但你可能至少应该有正确的数量级和符号,这样优化才能收敛到最优值。我只是使用了一些接近您提到的 'correct answer' 的随机数。当您不知道该猜什么时,您可以做一个 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()
结果:
我有两个列表,我试图在它们之间进行 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
uses [1, 1] as a guess. The optimization might then get stuck at some local minimum. One other thing you should do is to change your xdata
and ydata
lists to numpy arrays, as shown by 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)
猜测的确切值并不重要,但你可能至少应该有正确的数量级和符号,这样优化才能收敛到最优值。我只是使用了一些接近您提到的 'correct answer' 的随机数。当您不知道该猜什么时,您可以做一个 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()
结果: