Python 为什么稍微改变函数会导致scipy中的指数曲线拟合出现如此大的差异?
使用scipy中的曲线拟合函数,我得到了一些非常好的结果。我的功能稍有改变就会更好。但我不知道为什么。 这就是代码不起作用的原因:Python 为什么稍微改变函数会导致scipy中的指数曲线拟合出现如此大的差异?,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,使用scipy中的曲线拟合函数,我得到了一些非常好的结果。我的功能稍有改变就会更好。但我不知道为什么。 这就是代码不起作用的原因: def func(x, A1, t1, y0): return A1 * np.exp(x/t1) + y0 x_data = np.array(data['tau']) y_data = np.array(data['magnitude']) p0 = [1000, 4, 0] popt, pcov = curve_fit(func, x_data
def func(x, A1, t1, y0):
return A1 * np.exp(x/t1) + y0
x_data = np.array(data['tau'])
y_data = np.array(data['magnitude'])
p0 = [1000, 4, 0]
popt, pcov = curve_fit(func, x_data, y_data, p0)
print(popt)
y_fited = func(x_data, *popt)
plt.plot(x_data, y_data, 'b-', label='data')
plt.plot(x_data, y_fited, 'r-', label='fited')
输出图如下所示:
在我将func的t1从除法改为乘法后,一切似乎都变好了
def func(x, A1, t1, y0):
return A1 * np.exp(x*t1) + y0
为什么会这样?我不明白为什么我的第一个func不能很好地工作,它不是一个线性函数,我从Origin的指数拟合工具借用它。提前谢谢
这是我的x_数据:
[4.9063e-03 4.5800e-03 4.2538e-03 3.9275e-03 3.6012e-03 3.2750e-03
2.9487e-03 2.6224e-03 2.2961e-03 1.9699e-03 1.6436e-03 1.3173e-03
9.9107e-04 6.6480e-04 3.3853e-04 1.2266e-05]
和y_数据:
[1038.3 921.93 865.19 878.07 1141.9 1043.3 1167.2 1030.5
1174.8
1331.5 1549.7 1379.8 2134.8 1992.5 2218.8 2505.7]
这里有几个问题。显然,这是一种非线性拟合,因此始终存在局部极小值的可能性。显然这里有一个。那么问题是:为什么?我们必须看看底层算法在做什么。只要看看
t1
我们就会发现,如果我们从t1=1开始,两个版本都会给出相同的答案。现在数据清楚地表明这是衰减,所以结果应该是负的。因此,…*t1
的情况需要变小并变为负值。这是由局部误差的梯度控制的。现在很可能../t1
情况也希望朝更小的因子方向发展,但这意味着增加t1
,因此它将朝错误的方向发展。如果在整个装配过程中打印t1
的值,则可以观察到此行为。实际上,在某一点上,它克服了负数的“障碍”。然而,在这一点上,其他参数已经有这样的异常值,它返回到正
具体地说,这取决于启动参数,[5000,1,0]
将起作用
最后,我认为这个例子是关于如何准备fit功能的一个很好的教训:
- 尽量使符号正确,即
exp(-x*t1)
会更好,因为它显然是衰减的
- 如果某个参数可能会改变符号,请注意,如果该参数变为零,则不会出现任何偏差。这就是这里发生的事情
- 如果可能,请重新缩放,以便缩放
1
上的所有参数。这在某种程度上相当于提供良好的起始值。在这里,像1000*a*exp(-1000*t*x)+1000*c
这样的拟合函数将在不提供起始值的情况下快速收敛
这里有几个问题。显然,这是一种非线性拟合,因此始终存在局部极小值的可能性。显然这里有一个。那么问题是:为什么?我们必须看看底层算法在做什么。只要看看
t1
我们就会发现,如果我们从t1=1开始,两个版本都会给出相同的答案。现在数据清楚地表明这是衰减,所以结果应该是负的。因此,…*t1
的情况需要变小并变为负值。这是由局部误差的梯度控制的。现在很可能../t1
情况也希望朝更小的因子方向发展,但这意味着增加t1
,因此它将朝错误的方向发展。如果在整个装配过程中打印t1
的值,则可以观察到此行为。实际上,在某一点上,它克服了负数的“障碍”。然而,在这一点上,其他参数已经有这样的异常值,它返回到正
具体地说,这取决于启动参数,[5000,1,0]
将起作用
最后,我认为这个例子是关于如何准备fit功能的一个很好的教训:
- 尽量使符号正确,即
exp(-x*t1)
会更好,因为它显然是衰减的
- 如果某个参数可能会改变符号,请注意,如果该参数变为零,则不会出现任何偏差。这就是这里发生的事情
- 如果可能,请重新缩放,以便缩放
1
上的所有参数。这在某种程度上相当于提供良好的起始值。在这里,像1000*a*exp(-1000*t*x)+1000*c
这样的拟合函数将在不提供起始值的情况下快速收敛
您使用的拟合方法是一种迭代方法,从参数的“猜测”初始值开始。问题可能来自参数的初始值。如果它们离正确的值太远,迭代过程的收敛可能会失败,或者太慢或不稳定
如果使用不需要“猜测”初始值的非迭代方法,则可以避免这种情况。本文对这种方法进行了解释
非常简单的演算如下所示:
注:
您可以使用上述参数的近似值作为软件中的初始值,并检查它们是否正确计算参数的优化值。您使用的拟合方法是一种迭代方法,从参数的“猜测”初始值开始。问题可能来自参数的初始值。如果它们离正确的值太远,迭代过程的收敛可能会失败,或者太慢或不稳定
如果使用不需要“猜测”初始值的非迭代方法,则可以避免这种情况。本文对这种方法进行了解释
非常简单的演算如下所示:
注:
您可以使用上述参数的近似值,如下所示: