6

我在将曲线拟合到某些数据时遇到了一些麻烦,但无法弄清楚我哪里出错了。

在过去,我使用numpy.linalg.lstsq来完成指数函数,使用scipy.optimize.curve_fit来完成 sigmoid 函数。这一次,我希望创建一个脚本,让我指定各种函数、确定参数并测试它们与数据的匹配度。在执行此操作时,我注意到 Scipyleastsq和 Numpylstsq似乎为相同的数据集和相同的函数提供了不同的答案。该函数很简单y = e^(l*x),并且受到约束,使得y=1x=0

Excel 趋势线与 Numpylstsq结果一致,但由于 Scipyleastsq能够采用任何功能,因此最好找出问题所在。

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,而与 Excel 计算的numpy.linalg.lstsq曲线的 R^2 为 0.41。

4

2 回答 2

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]
于 2013-01-16T04:32:08.327 回答
1

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

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

于 2013-12-19T01:03:25.993 回答