我昨天问了以下问题,这是这个问题的延伸: Python - curve_fitting 在高 x 值时无法正常工作
为了完整起见,我将再次解释一下情况。 我有四个 XY 点需要获取曲线,因此我使用
scipy.optimize.curve_fit
。看看这些点,我想使用指数函数。我遇到了一些问题,但是有人能够修复它,并且我有下面的代码示例:
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
## X
# list_x1: [3.139, 2.53, 0.821, 0.27]
# list_x2: [859.8791936328762, 805.5080517453312, 639.2578427310567, 496.3622821767497]
## Y
# list_y1: [0.21, 0.49, 1.56, 23.97]
# list_y2: [0.01, 0.01, 0.04, 2.46]
list_x = [859.8791936328762, 805.5080517453312, 639.2578427310567, 496.3622821767497]
list_y = [0.01, 0.01, 0.04, 2.46]
def func_exp(x, a, b, c, d):
return a + b*np.exp(-c*(x-d))
p0 = (0, max(list_x), 0, max(list_y))
list_line_info, pcov = curve_fit(func_exp, list_x, list_y, maxfev=100000, p0=p0)
plot_x = np.linspace(min(list_x), max(list_x), 1000)
plot_y = func_exp(plot_x, *list_line_info)
plt.plot(plot_x, plot_y, linestyle="-", color="orangered")
plt.plot(list_x, list_y, linestyle="--", color="dodgerblue")
plt.scatter(list_x, list_y, color="black", zorder=2)
plt.grid()
该代码在我的程序中适用于我输入的所有列表,除了一种组合。问题在于初始猜测值。在另一个问题中提出的使用这些的建议是有效的。然后我尝试使用
p0 = (0, max(list_x), 0, max(list_y))
来自动化此操作。这适用于所有图形(list_x1
、list_x2
和 list_y1
的所有组合),但不适用于 list_x2
和 list_y2
的组合。
组合
list_x1
和list_y2
:
组合
list_x2
和list_y2
:
最初的猜测
p0 = (0, max(list_x), 0.01, max(list_y))
在 list_x2
和 list_y2
的组合中确实有效,但后来我对 list_x1
和 list_y2
的组合也有同样的问题
我在这里遗漏了什么吗?
编辑
我根据评论中的建议更新了代码:
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
## X
# list_x1: [3.139, 2.53, 0.821, 0.27]
# list_x2: [859.8791936328762, 805.5080517453312, 639.2578427310567, 496.3622821767497]
## Y
# list_y1: [0.21, 0.49, 1.56, 23.97]
# list_y2: [0.01, 0.01, 0.04, 2.46]
list_x = [859.8791936328762, 805.5080517453312, 639.2578427310567, 496.3622821767497]
list_y = [0.21, 0.49, 1.56, 23.97]
def func_exp(x, a, b, c, d):
return a + b*np.exp(-c*(x-d))
p0 = (0, max(list_y), 0, max(list_x))
list_line_info, pcov = curve_fit(func_exp, list_x, list_y, maxfev=100000, p0=p0)
plot_x = np.linspace(min(list_x), max(list_x), 1000)
plot_y = func_exp(plot_x, *list_line_info)
plt.plot(plot_x, plot_y, linestyle="-", color="orangered")
plt.plot(list_x, list_y, linestyle="--", color="dodgerblue")
plt.scatter(list_x, list_y, color="black", zorder=2)
plt.grid()
此建议不适用于此处使用的组合之一:
你的假设是好的,但是你遗漏了一些东西,你试图拟合的方程是:
这类似于指数衰减(与 x 的倒数相关)。如果我们遵循你的第一个假设,忽略 a 和 d 作为初始值,我们得到:
这里我们可以看到b与振幅类似。这样,如果 c 等于 x_0(在本例中为 500),则 b=e*y_0 将完美适合第一个点。因此,我们可以看到 b 和 c 分别与 y 和 x 相关。
在您的情况下,您可以使用 p0 = (0, max(list_x), 0, max(list_y)) 进行初始估计。因此,将 b 与 x 关联,将 d 与 y 关联,对于相同数量级的值来说并没有太大区别。您迭代了大约 100,000 次。然而,当 x 和 y 的数量级不同时,很好地拟合这些点的保证非常低。如果我们看看你的函数无法拟合结果的情况,那么与 y 和 x 相比,你会从非常高的 b 和非常低的 c 开始。这样第一次估计 y 就会太大,与 x 的顺序相同。
因此,初始值为 p0 = (0, max(list_y), 0, max(list_x)) 的方法会更有意义。这些值仍然会有点偏差,但只需几次迭代即可获得最佳拟合值。