如何为我猜测双指数衰减选择正确的初始拟合参数?
How to choose the right initial fitting parameters for I'm guessing a double exponential decay?
为了拟合我的数据(具有对数 y 轴),我尝试猜测要提供给 scipy.optimize.curve_fit 的初始拟合参数时遇到了失败。由于双重衰减,我猜它是双指数拟合(虽然我可能是错的)。代码和生成的图表如下。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def double_exponential(x, a, b, c, d):
return a*np.exp(-c*(x-b))+d
fig, ax = plt.subplots()
x = np.array([7.13793103, 21.4137931, 35.68965517, 49.96551724, 64.24137931, 78.51724138, 92.79310345, 107.06896552, 121.34482759, 135.62068966, 149.89655172, 164.17241379, 178.44827586, 192.72413793, 207.00000000, 221.27586207, 235.55172414, 249.82758621, 264.10344828, 278.37931034, 292.65517241, 306.93103448, 321.20689655, 335.48275862, 349.75862069, 364.03448276, 378.31034483, 392.5862069, 406.86206897, 421.13793103])
y = np.array([169954, 20599, 7309, 3989, 2263, 1569, 1134, 1017, 788, 806, 693, 528, 502, 431, 445, 367, 277, 267, 255, 189, 171, 109, 76, 36, 18, 9, 4, 3, 2, 1])
y_pruned = np.where(y < 1, 1, y)
p0 = (1.0, 1.0, 1.0, 1.0) # only an example (I've tried other values without success)
popt, pcov = curve_fit(double_exponential, x, np.log(y_pruned), p0=p0)
ax.plot(x, double_exponential(x, *popt), 'g--')
ax.plot(x, np.log(y_pruned), 'ro')
ax.set_yscale('log') # I need to have the y-axis logarithmic
plt.show()
我可能是错的,但在我看来它不是双指数。在 log-plot 中,它似乎是一个 fourth-order 多项式,如果您尝试,它非常适合:
我刚刚使用以下函数安装了 x and np.log(y)
:
def f(x, a, b, c, d):
return a*x**3 +b*x**2 + c*x + d
拟合结果为:
a: -4.933e-07 +/- 4.82e-08 (-9.8%) initial:1
b: 0.0003011 +/- 3.14e-05 (10.4%) initial:1
c: -0.06804 +/- 0.00579 (-8.5%) initial:1
d: 11.406 +/- 0.286 (2.5%) initial:1
如果你真的想要拟合 x
和 y
而不是 log(y)
这有点棘手,因为来自前几个点的残差更大并且拟合函数忽略右边的小点:
def f(x, a=-4.933e-07, b=0.0003011, c=-0.06804, d=11.406):
return np.exp(a*x**3 +b*x**2 + c*x + d)
当然,您可以在拟合函数中调整这种权衡点的行为,并且它有效,但在我看来,就仅拟合数据日志而言,它有点过于复杂:
为了拟合我的数据(具有对数 y 轴),我尝试猜测要提供给 scipy.optimize.curve_fit 的初始拟合参数时遇到了失败。由于双重衰减,我猜它是双指数拟合(虽然我可能是错的)。代码和生成的图表如下。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def double_exponential(x, a, b, c, d):
return a*np.exp(-c*(x-b))+d
fig, ax = plt.subplots()
x = np.array([7.13793103, 21.4137931, 35.68965517, 49.96551724, 64.24137931, 78.51724138, 92.79310345, 107.06896552, 121.34482759, 135.62068966, 149.89655172, 164.17241379, 178.44827586, 192.72413793, 207.00000000, 221.27586207, 235.55172414, 249.82758621, 264.10344828, 278.37931034, 292.65517241, 306.93103448, 321.20689655, 335.48275862, 349.75862069, 364.03448276, 378.31034483, 392.5862069, 406.86206897, 421.13793103])
y = np.array([169954, 20599, 7309, 3989, 2263, 1569, 1134, 1017, 788, 806, 693, 528, 502, 431, 445, 367, 277, 267, 255, 189, 171, 109, 76, 36, 18, 9, 4, 3, 2, 1])
y_pruned = np.where(y < 1, 1, y)
p0 = (1.0, 1.0, 1.0, 1.0) # only an example (I've tried other values without success)
popt, pcov = curve_fit(double_exponential, x, np.log(y_pruned), p0=p0)
ax.plot(x, double_exponential(x, *popt), 'g--')
ax.plot(x, np.log(y_pruned), 'ro')
ax.set_yscale('log') # I need to have the y-axis logarithmic
plt.show()
我可能是错的,但在我看来它不是双指数。在 log-plot 中,它似乎是一个 fourth-order 多项式,如果您尝试,它非常适合:
我刚刚使用以下函数安装了 x and np.log(y)
:
def f(x, a, b, c, d):
return a*x**3 +b*x**2 + c*x + d
拟合结果为:
a: -4.933e-07 +/- 4.82e-08 (-9.8%) initial:1
b: 0.0003011 +/- 3.14e-05 (10.4%) initial:1
c: -0.06804 +/- 0.00579 (-8.5%) initial:1
d: 11.406 +/- 0.286 (2.5%) initial:1
如果你真的想要拟合 x
和 y
而不是 log(y)
这有点棘手,因为来自前几个点的残差更大并且拟合函数忽略右边的小点:
def f(x, a=-4.933e-07, b=0.0003011, c=-0.06804, d=11.406):
return np.exp(a*x**3 +b*x**2 + c*x + d)
当然,您可以在拟合函数中调整这种权衡点的行为,并且它有效,但在我看来,就仅拟合数据日志而言,它有点过于复杂: