我在 Python 中遇到与
curve_fit
相关的问题。具体来说,我正在尝试对双指数数据进行建模。
我正在尝试对数据进行建模。肉眼看上去拟合效果很好,但当我看到参数和误差时,我感到震惊。误差很大(比参数平均值大几个数量级)。除此之外,我必须提供非常具体的初步猜测,否则毫无用处。你有什么建议吗?
双倍经验拟合如何处理?
Plots: https://ibb.co/mCs39VP
Model:a*e^(-x*b)+c*e^(-x*d)+e
Paramters (for lower fit): [-1622.6092323 -15.038877 1713.45499496 -15.33871455
-1.92259733]
Errors [4.73773551e+06 4.17637511e+02 4.73736168e+06 4.37257698e+02
1.20927662e-02
情节:
您至少面临两个问题:
让我们构建一个 MCVE 来突出您的验配问题的挑战。
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
from sklearn.metrics import r2_score
对于您引用的模型,我们有以下功能:
def model(x, a, b, c, d, e):
return a * np.exp(-b * x) + c * np.exp(-d * x) + e
这对于拟合来说并不简单,因为它是多余的(其中有两个相同的指数效应)。这意味着求解器在从单位点开始执行损失梯度下降时会感到困惑。
我们生成一些与您的数据集类似的数据:
p0 = np.array([1.7, 1.1, -0.4, 4.2, 1.])
请注意,您的参数集没有定义收敛函数,因为两个指数都在增加。这个解决方案肯定无法适合您的数据,因此它们的不确定性很大。
#p0 = np.array([-1622.6092323, -15.038877, 1713.45499496, -15.33871455, -1.92259733])
我们生成一些综合数据集:
np.random.seed(12345)
x = np.linspace(-0.5, 2.0, 35)
y = model(x, *p0)
s = 0.01 * np.ones_like(y)
n = s * np.random.normal(size=y.size)
yexp = y + n
这是优化的关键,我们只将一个初始参数调整为负数,以帮助求解器区分两个指数并相互优化:
popt, pcov = optimize.curve_fit(
model, x, yexp, sigma=s,
p0=[1, 1, -1, 1, 1], # Hint: discriminate both effect
absolute_sigma=True
)
# array([ 1.70657559, 1.04436978, -0.36944364, 4.29809242, 0.96715622])
spopt = np.sqrt(np.diag(pcov))
# array([0.01738214, 0.03964849, 0.02884002, 0.09962603, 0.01952317])
我们可以看到,在这种情况下,收敛是最优的(我们恢复了带有明显误差的参数)。
yhat = model(x, *popt)
score = r2_score(yexp, yhat) # 0.9993365605205807
健身也没错: