指数衰减曲线拟合numpy和scipy

时间:2013-01-16 00:57:31

标签: numpy scipy curve-fitting least-squares exponential

我在为一些数据拟合曲线方面遇到了一些麻烦,但在我出错的地方无法解决。

过去我用 numpy.linalg.lstsq 表示指数函数, scipy.optimize.curve_fit 表示sigmoid函数。这次我希望创建一个脚本,让我指定各种函数,确定参数并测试它们与数据的拟合。在这样做时,我注意到Scipy leastsq和Numpy lstsq似乎为同一组数据和相同的函数提供了不同的答案。该函数只是y = e^(l*x),受约束,y=1位于x=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包括一小部分数据集。在拟合实际数据时, scipy.optimize.curve_fit 曲线显示R ^ 2为0.82,而 numpy.linalg.lstsq 曲线与计算的曲线相同通过Excel,R ^ 2为0.41。

2 个答案:

答案 0 :(得分: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]

答案 1 :(得分:1)

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

我还要补充一点,虽然这个技巧“适用于”指数衰减为0,但它不能用于阻尼指数(上升或下降)的更一般(和常见)情况下,不能假设的值为0。