为什么稍微改变函数会导致 scipy 中的指数曲线拟合出现如此大的差异?
Why slightly changing the function caused so much difference in exponential curve fitting in scipy?
使用 scipy 中的 curve_fit 函数,我得到了一些非常奇怪的结果。对我的功能稍作改动会使它变得更好。但我不知道为什么。
这是代码不起作用:
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_data:
[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_data:
[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]
会起作用。
最后我认为这个例子是关于如何准备拟合函数的很好的一课:
- 尝试让符号正确,即
exp( -x * t1 )
会更好,因为它显然是衰减的
- 如果参数可能改变符号,请注意如果参数变为零,则不会出现任何分歧。这有点像这里发生的事情。
- 如果可能,重新调整比例,使所有参数都在
1
的比例上。这在某种程度上等同于提供良好的起始值。这里像 1000 * a * exp( -1000 * t * x ) + 1000 * c
这样的拟合函数会在不提供起始值的情况下快速收敛。
您使用的拟合方法是一种迭代方法,从参数的“猜测”初始值开始。问题可能来自参数的初始值。如果它们离正确值太远,迭代过程的收敛可能会失败或者太慢或不稳定。
如果使用不需要“猜测”初始值的非迭代方法,则可以避免这种情况。 https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales
中解释了这种方法
下面是非常简单的微积分:
注意:
您可以使用上面找到的参数的近似值作为软件中的初始值,并检查它们是否会正确计算参数的优化值。
使用 scipy 中的 curve_fit 函数,我得到了一些非常奇怪的结果。对我的功能稍作改动会使它变得更好。但我不知道为什么。 这是代码不起作用:
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_data:
[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_data:
[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]
会起作用。
最后我认为这个例子是关于如何准备拟合函数的很好的一课:
- 尝试让符号正确,即
exp( -x * t1 )
会更好,因为它显然是衰减的 - 如果参数可能改变符号,请注意如果参数变为零,则不会出现任何分歧。这有点像这里发生的事情。
- 如果可能,重新调整比例,使所有参数都在
1
的比例上。这在某种程度上等同于提供良好的起始值。这里像1000 * a * exp( -1000 * t * x ) + 1000 * c
这样的拟合函数会在不提供起始值的情况下快速收敛。
您使用的拟合方法是一种迭代方法,从参数的“猜测”初始值开始。问题可能来自参数的初始值。如果它们离正确值太远,迭代过程的收敛可能会失败或者太慢或不稳定。
如果使用不需要“猜测”初始值的非迭代方法,则可以避免这种情况。 https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales
中解释了这种方法下面是非常简单的微积分:
注意:
您可以使用上面找到的参数的近似值作为软件中的初始值,并检查它们是否会正确计算参数的优化值。