2013-01-16 86 views
6

我在拟合某些数据的曲线时遇到了一些麻烦,但无法计算出我要出错的地方。指数衰减曲线拟合在numpy和scipy中

在过去我曾与numpy.linalg.lstsq的指数函数和乙状结肠功能scipy.optimize.curve_fit做到了这一点。这次我想创建一个脚本,让我指定各种功能,确定参数并测试它们对数据的适合性。在做这件事时,我注意到Scipy leastsq和Numpy lstsq似乎为同一组数据和相同的功能提供了不同的答案。该功能简单地为y = e^(l*x),受限于y=1x=0

Excel趋势线与Numpy lstsq结果一致,但由于Scipy leastsq能够采取任何功能,因此找出问题所在是一件好事。

import scipy.optimize as optimize 
import numpy as np 
import matplotlib.pyplot as plt 

## Sampled data 
x = np.array([0, 14, 37, 975, 2013, 2095, 2147]) 
y = np.array([1.0, 0.764317544, 0.647136491, 0.070803763, 0.003630962,  0.001485394,  0.000495131]) 

# function 
fp = lambda p, x: np.exp(p*x) 

# error function 
e = lambda p, x, y: (fp(p, x) - y) 

# using scipy least squares 
l1, s = optimize.leastsq(e, -0.004, args=(x,y)) 
print l1 
# [-0.0132281] 


# using numpy least squares 
l2 = np.linalg.lstsq(np.vstack([x, np.zeros(len(x))]).T,np.log(y))[0][0] 
print l2 
# -0.00313461628963 (same answer as Excel trend line) 

# smooth x for plotting 
x_ = np.arange(0, x[-1], 0.2) 

plt.figure() 
plt.plot(x, y, 'rx', x_, fp(l1, x_), 'b-', x_, fp(l2, x_), 'g-') 
plt.show() 

编辑 - 附加信息

上面的MWE包括数据集的一小部分。当拟合实际数据时,曲线呈现0.82的R^2,而与Excel计算的曲线相同的曲线具有0.41的R^2曲线,其曲线的R^2为0.41 。

回答

4

您正在最小化不同的错误功能。

当使用numpy.linalg.lstsq,被最小化的误差函数是

np.sum((np.log(y) - p * x)**2) 

scipy.optimize.leastsq最小化函数

np.sum((y - np.exp(p * x))**2) 

第一种情况,需要因变量和自变量之间的线性相关性,但解决方案是已知的,而第二个可以处理任何依赖关系,但依赖于迭代方法。

在一个单独的说明, 我现在不能使用 numpy.linalg.lstsq时测试,但 ,我你并不需要vstack零一排,下面的作品,以及:

l2 = np.linalg.lstsq(x[:, None], np.log(y))[0][0] 
+0

谢谢@Jaime - 伟大的答案!不幸的是,我的数学知识不是很好,是一个写还是错的[也见上面的编辑],还是只是根本上不同......?例如,如果我想测试Sigmoid或Gompertz曲线对相同数据的拟合程度,对其他函数有什么影响? – StacyR

+0

@StacyR我没有足够的知识来正确回答你的问题,但我相当确定,像'np.linalg.lstsq'那样拟合指数是一种快速的'不'计算技巧错误正确。这里有一些讨论(很难让我跟随):http://mathworld.wolfram.com/LeastSquaresFittingExponential.html如果你不想深入研究这些东西,我会用scipy的方法来处理所有事情:应该给予更好的配合,并且您的结果将对所有功能保持一致。 – Jaime

+0

再次感谢!我已经做了一些更多的研究,正如你所提到的那样,发现'np.linalg.lstsq'方法在低x值时过度地加权y-错误。你分享的链接以及我发现的其他一些资源,使我得到了另外一种分析方法(使问题变得棘手的是约束 - 所有书籍都描述了y = a * e^b * x的方法)比y = e^b * x),但是,这也会产生比迭代式的'scipy.optimize.leastsq'更糟的拟合曲线。 – StacyR

1

要在Jaime的观点上阐述了一点,数据的任何非线性变换都会导致不同的误差函数,从而导致不同的解决方案。这将导致拟合参数的不同置信区间。因此,您有三个可能的标准用于做出决定:您想要最小化哪个错误,哪个参数要更有信心,最后,如果您使用拟合来预测某个值,哪种方法在有趣的方面产生的误差更小预测值。在解析和Excel中进行一些分析表明,数据中的不同种类的噪声(例如,如果噪声函数缩放振幅,影响时间常数或是相加的)会导致不同的解决方案选择。

我还会补充一点,虽然这个技巧对于指数衰减为“有效”,但它不能用于阻尼指数(上升或下降)的更一般(普通)情况下,假设为0.