有没有人知道一个scipy/numpy模块,这将允许拟合指数衰减的数据?
Google搜索返回了一些blog文章,例如-http://exnumerus.blogspot.com/2010/04/how-to-fit-exponential-decay-example-in.html,但是该解决方案需要预先指定y偏移,这并不总是可行的
编辑:
curve_fit可以工作,但是如果没有对参数进行初始猜测,它可能会失败得很惨,这有时是需要的。
# !/usr/bin/env python
import numpy as np
import scipy as sp
import pylab as pl
from scipy.optimize.minpack import curve_fit
x = np.array([ 50., 110., 170., 230., 290., 350., 410., 470.,
530., 590.])
y = np.array([ 3173., 2391., 1726., 1388., 1057., 786., 598.,
443., 339., 263.])
smoothx = np.linspace(x[0], x[-1], 20)
guess_a, guess_b, guess_c = 4000, -0.005, 100
guess = [guess_a, guess_b, guess_c]
exp_decay = lambda x, A, t, y0: A * np.exp(x * t) + y0
params, cov = curve_fit(exp_decay, x, y, p0=guess)
A, t, y0 = params
print "A = %s\nt = %s\ny0 = %s\n" % (A, t, y0)
pl.clf()
best_fit = lambda x: A * np.exp(t * x) + y0
pl.plot(x, y, 'b.')
pl.plot(smoothx, best_fit(smoothx), 'r-')
pl.show()
这是可行的,但如果我们删除“p0=guess”,它会失败得很惨。
8条答案
按热度按时间2exbekwf1#
您有两个选择:
1.使系统线性化,并在数据日志上拟合一条线。
1.使用非线性求解程序(例如
scipy.optimize.curve_fit
第一个选项是目前为止最快和最稳健的。但是,它要求您事先知道y偏移,否则不可能线性化方程。(即,
y = A * exp(K * t)
可以通过拟合y = log(A * exp(K * t)) = K * t + log(A)
线性化,但y = A*exp(K*t) + C
只能通过拟合y - C = K*t + log(A)
线性化,并且由于y
是自变量,C
必须事先已知,以使其成为线性系统。如果使用非线性方法,则a)不能保证收敛并得到解,B)速度会慢得多,c)对参数的不确定性的估计会差得多,d)精度通常会低得多。然而,非线性方法与线性反演相比有一个巨大的优势:它可以解一个非线性方程组,在你的例子中,这意味着你不必事先知道
C
。仅给予一个例子,让我们使用线性和非线性方法,用一些噪声数据求解y = A * exp(K * t):
请注意,线性解决方案提供的结果更接近实际值。但是,我们必须提供y偏移值才能使用线性解决方案。非线性解决方案不需要这种先验知识。
nwlls2ji2#
拟合指数的过程,无需初始猜测,无需迭代过程:
这来自论文(pp.16-17):https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales
如果需要,这可以用于初始化非线性回归演算,以便选择特定的优化标准。
示例:
乔·金顿给出的例子很有趣。不幸的是,数据没有显示,只显示了图表。因此,下面的数据(x,y)来自图表的图形扫描,因此,数值可能不完全是乔·金顿使用的那些。然而,考虑到点的广泛分散,“拟合”曲线的相应方程彼此非常接近。
上图是金顿图的副本。
下图显示了用上述程序获得的结果。
UPDATE:一个变体
ckx4rj1h3#
我会使用
scipy.optimize.curve_fit
函数,它的doc字符串甚至有一个拟合指数衰减的例子,我将复制到这里:拟合的参数会因随机噪声的加入而变化,但我得到的a,b和c分别是2.47990495,1.40709306,0.53753635,所以在噪声的情况下,这还不算太糟,如果我拟合到y而不是yn,我得到的是精确的a,b和c值。
hxzsmxv24#
正确的方法是进行Prony估计,并将结果作为最小二乘拟合(或其他更稳健的拟合例程)的初始猜测。Prony估计不需要初始猜测,但它确实需要许多点来产生良好的估计。
以下是概述
http://www.statsci.org/other/prony.html
在Octave中,它被实现为
expfit
,因此您可以基于Octave库函数编写自己的例程。Prony估计确实需要知道偏移量,但如果您深入到衰减中“足够远”,就可以对偏移量进行合理的估计,因此您只需移动数据,将偏移量设置为0。无论如何,Prony估计只是为其他拟合例程获得合理初始猜测的一种方法。
6yt4nkrj5#
我从来没有让curve_fit正常工作过,就像你说的,我不想猜测任何东西。我试图简化Joe Kington的例子,这就是我的工作。我的想法是把“嘈杂”的数据转换成log,然后再转换回来,并使用polyfit和polyval来计算参数:
其中xVals和yVals只是列表。
trnvg8h36#
我不懂python,但我知道一种简单的方法,可以通过非迭代的方式估计带有偏移量的指数衰减系数,给定三个数据点,它们的独立坐标具有固定的差值。您的数据点在它们的独立坐标中具有固定的差值(您的x值间隔为60),因此我的方法可以应用于它们。您当然可以将数学转换为python。
假设
其中
C = exp(-c)
给定y_0,y_1,y_2,对于x = 0,1,2,我们求解
按如下方式求出A、B、C:
对应的指数正好经过三个点(0,y_0)、(1,y_1)和(2,y_2)。如果数据点不在x坐标0、1、2处,而是在k、k + s和k + 2*s处,则
所以可以用上面的公式求出A,B,C,然后计算
产生的系数对y坐标中的误差非常敏感,如果外推超出三个所用数据点定义的范围,则可能导致较大误差,因此最好从尽可能远的三个数据点(同时它们之间仍具有固定距离)计算A、B、C。
您的数据集有10个等距数据点。让我们挑选三个数据点(第110页,第2391页)(第350、786页)(590,263)用于使用― ―这些具有最大可能的固定距离(240),则在独立坐标系中,y_o = 2391,y_l = 786,y_2 = 263,k = 110,s = 240,则A = B = 2380.799,C = 0.3258567,A ′ = 10.20055,B′ = 3980.329,C′ = 0.9953388。指数为
您可以使用此指数作为非线性拟合算法中的初始猜测值。
计算A的公式与Shanks变换(http://en.wikipedia.org/wiki/Shanks_transformation)所使用的公式相同。
gzjq41n47#
@ Jacquelin的解决方案的Python实现。我需要一个近似的基于非解决方案的解决方案,没有初始猜测,所以@ Jacquelin的答案真的很有帮助。最初的问题是作为python numpy/scipy请求提出的。我采用了@johanvdw的漂亮干净的R代码,并将其重构为python/numpy。希望对某些人有用:https://gist.github.com/friendtogeoff/00b89fa8d9acc1b2bdf3bdb675178a29
vi4fp9gy8#
如果衰减不是从0开始,请用途:
其中x0是衰减的起点(拟合的起点)。然后再次使用x0进行绘图:
其中函数为: