Python - curve_fitting 自动化初始猜测

问题描述 投票:0回答:1

我昨天问了以下问题,这是这个问题的延伸: 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()

此建议不适用于此处使用的组合之一:

python scipy curve-fitting
1个回答
0
投票

你的假设是好的,但是你遗漏了一些东西,你试图拟合的方程是:

y(x)= a+b\exp{-\frac{c}{x-d}}

这类似于指数衰减(与 x 的倒数相关)。如果我们遵循你的第一个假设,忽略 a 和 d 作为初始值,我们得到:

y(x)=b\exp{-\frac{c}{x}}

这里我们可以看到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)) 的方法会更有意义。这些值仍然会有点偏差,但只需几次迭代即可获得最佳拟合值。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.