Python中的指数回归

vwhgwdsa  于 2022-12-02  发布在  Python
关注(0)|答案(2)|浏览(400)

我有一组xy数据,我想使用指数回归来找到最适合这组点的直线,即:

y = P1 + P2 exp(-P0 x)

我想计算P0P1P2的值。
我使用了一个软件“Igor Pro”,它可以为我计算值,但我需要一个Python实现。我使用了curve_fit函数,但我得到的值与Igor软件计算的值相差甚远。以下是我得到的数据集:
第一组:

x = [ 1.06, 1.06, 1.06, 1.06, 1.06, 1.06, 0.91, 0.91, 0.91 ]
y = [ 476, 475, 476.5, 475.25, 480, 469.5, 549.25, 548.5, 553.5 ]

Igor计算值:

P1=376.91, P2=5393.9, P0=3.7776

curve_fit计算值:

P1=702.45, P2=-13.33. P0=-2.6744

第二组:

x = [ 1.36, 1.44, 1.41, 1.745, 2.25, 1.42, 1.45, 1.5, 1.58]
y = [ 648, 618, 636, 485, 384, 639, 630, 583, 529]

Igor计算值:

P1=321, P2=4848, P0=-1.94

通过曲线拟合计算的值:

No optimal values found

我按如下方式使用curve_fit

from scipy.optimize import curve_fit
popt, pcov = curve_fit(lambda t, a, b, c: a * np.exp(-b * t) + c, x, y)

其中:

P1=c, P2=a and P0=b
tjrkku2a

tjrkku2a1#

看起来curve_fit函数不是解决此问题的正确工具,因为您尝试拟合数据的函数(y = P1 + P2 * exp(-P0 * x))具有三个参数,而curve_fit需要仅具有一个参数的函数(自变量,在本例中为t)。您可以使用curve_fit将单参数函数拟合到数据,方法是用t和单个参数表示y,但这不会给予您要查找的P1、P2和P0的值。
若要使此特定函数适合您的数据,您需要使用不同的方法。一种可能的方法是定义一个函数,该函数将x、P1、P2和P0作为参数,并根据上面的等式返回相应的y值。然后,您可以使用非线性优化算法来查找P1、P2和P0的值。和P0的函数,它们可以最小化数据中y的预测值与y的观测值之间的差异。有几个Python库提供了可以用于此目的的非线性优化算法,如scipy.optimize和lmfit。
下面是一个如何使用scipy.optimize将数据拟合到函数y = P1 + P2 * exp(-P0 * x)的示例:

import numpy as np
from scipy.optimize import minimize

# Define the function that we want to fit to the data
def func(x, P1, P2, P0):
    return P1 + P2 * np.exp(-P0 * x)

# Define a function that takes the parameters of the function as arguments
# and returns the sum of the squared differences between the predicted
# and observed values of y
def objective(params):
    P1, P2, P0 = params
    y_pred = func(x, P1, P2, P0)
    return np.sum((y - y_pred) ** 2)

# Define the initial values for the parameters
params_init = [376.91, 5393.9, 3.7776]

# Use the minimize function to find the values of the parameters that
# minimize the objective function
result = minimize(objective, params_init)

# Print the optimized values of the parameters
print(result.x)

此代码应给予与Igor软件计算的值相同的P1、P2和P0值。然后,您可以使用参数的优化值,通过上面定义的函数预测任意给定x值的y值。
我希望这对你有帮助!如果你有任何其他问题,请告诉我。

gojuced7

gojuced72#

当比较拟合结果时,在拟合参数中包含不确定性总是很重要的。(P1=376.91,P2=5393.9,P0=3.7776),并根据曲线拟合(P1=702.45,P2= -13.33,P0=-2.6744)不同,是什么导致得出这些值实际上不同的结论?
当然,在日常对话中,376.91和702.45是非常不同的,主要是因为简单地将一个值表述到小数点后两位就意味着近似于该标度的准确度(纽约和东京之间的距离是10,850公里,但实际上不是10,847,024公里,31厘米--这可能是两个城市公交站之间的距离)。但是在比较拟合结果时,不能假设日常知识,我不知道Igor是否会给予你这些,scipy curve_fit可以,但是它需要一些工作来提取它们--很遗憾。
请允许我建议您尝试lmfit(免责声明:我是一个作者)。使用该方法,您可以像这样设置和执行fit:

import numpy as np
from lmfit import Model
    
x = [ 1.06, 1.06, 1.06, 1.06, 1.06, 1.06, 0.91, 0.91, 0.91 ]
y = [ 476, 475, 476.5, 475.25, 480, 469.5, 549.25, 548.5, 553.5 ]
# x = [ 1.36, 1.44, 1.41, 1.745, 2.25, 1.42, 1.45, 1.5, 1.58]
# y = [ 648, 618, 636, 485, 384, 639, 630, 583, 529]    

# Define the function that we want to fit to the data
def func(x, offset, scale, decay):
    return offset + scale * np.exp(-decay* x)
    
model = Model(func)
params = model.make_params(offset=375, scale=5000, decay=4)
    
result = model.fit(y, params, x=x)
    
print(result.fit_report())

这将打印出

[[Model]]
    Model(func)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 49
    # data points      = 9
    # variables        = 3
    chi-square         = 72.2604167
    reduced chi-square = 12.0434028
    Akaike info crit   = 24.7474672
    Bayesian info crit = 25.3391410
    R-squared          = 0.99362489
[[Variables]]
    offset:  413.168769 +/- 17348030.9 (4198775.95%) (init = 375)
    scale:   16689.6793 +/- 1.3337e+10 (79909638.11%) (init = 5000)
    decay:   5.27555726 +/- 1016721.11 (19272297.84%) (init = 4)
[[Correlations]] (unreported correlations are < 0.100)
    C(scale, decay)  = 1.000
    C(offset, decay) = 1.000
    C(offset, scale) = 1.000

这表明参数值的不确定性非常大,所有参数之间的相关系数均为1。这是因为您只有2个x值,因此无法准确确定3个独立变量。
请注意,在不确定度为1700万的情况下,P1(偏移量)的值413和762实际上是一致的。问题不在于Igor和curve_fit在最佳值上存在分歧,而在于两者都无法以任何精度确定该值。
对于您的其他数据集,情况稍微好一点,结果是:

[[Model]]
    Model(func)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 82
    # data points      = 9
    # variables        = 3
    chi-square         = 1118.19957
    reduced chi-square = 186.366596
    Akaike info crit   = 49.4002551
    Bayesian info crit = 49.9919289
    R-squared          = 0.98272310
[[Variables]]
    offset:  320.876843 +/- 42.0154403 (13.09%) (init = 375)
    scale:   4797.14487 +/- 2667.40083 (55.60%) (init = 5000)
    decay:   1.93560164 +/- 0.47764470 (24.68%) (init = 4)
[[Correlations]] (unreported correlations are < 0.100)
    C(scale, decay)  = 0.995
    C(offset, decay) = 0.940
    C(offset, scale) = 0.904

相关性仍然很高,但是参数已经被合理地确定了。2同时,注意这里的最佳拟合值更接近于你从Igor那里得到的值,并且可能“在不确定性范围内”。
这就是为什么***总是***需要将不确定性与拟合报告的最佳拟合值包括在内。

相关问题