numpy.polyfit与scipy.odr的比较

5 投票
2 回答
4716 浏览
提问于 2025-04-18 13:42

我有一个数据集,理论上它可以用一个二次多项式来描述。我想对这个数据进行拟合,所以我使用了 numpy.polyfit。不过,这个方法的一个缺点是,它没有提供返回系数的误差。因此,我决定用 scipy.odr 也来拟合一下数据。奇怪的是,这两种方法得到的多项式系数竟然不一样。

我不太明白这个情况,所以我决定用我自己生成的一组数据来测试这两种拟合方法:

import numpy
import scipy.odr
import matplotlib.pyplot as plt

x = numpy.arange(-20, 20, 0.1)
y = 1.8 * x**2 -2.1 * x + 0.6 + numpy.random.normal(scale = 100, size = len(x))

#Define function for scipy.odr
def fit_func(p, t):
  return p[0] * t**2 + p[1] * t + p[2]

#Fit the data using numpy.polyfit
fit_np = numpy.polyfit(x, y, 2)

#Fit the data using scipy.odr
Model = scipy.odr.Model(fit_func)
Data = scipy.odr.RealData(x, y)
Odr = scipy.odr.ODR(Data, Model, [1.5, -2, 1], maxit = 10000)
output = Odr.run()
#output.pprint()
beta = output.beta
betastd = output.sd_beta

print "poly", fit_np
print "ODR", beta

plt.plot(x, y, "bo")
plt.plot(x, numpy.polyval(fit_np, x), "r--", lw = 2)
plt.plot(x, fit_func(beta, x), "g--", lw = 2)

plt.tight_layout()

plt.show()

一个结果的例子如下:

poly [ 1.77992643 -2.42753714  3.86331152]
ODR [   3.8161735   -23.08952492 -146.76214989]

enter image description here

在上面的图片中,numpy.polyfit 得到的结果(红色虚线)看起来还不错。而 scipy.odr 的结果(绿色虚线)则完全不对。我需要指出的是,在我想要拟合的实际数据集中,numpy.polyfitscipy.odr 之间的差异要小得多。不过,我还是不明白这两者之间的差异是怎么来的,为什么在我自己的测试例子中差异这么大,以及哪种拟合方法更好?

我希望你们能提供一些答案,帮助我更好地理解这两种拟合方法,并解答我心中的疑问。

2 个回答

0

实际的问题是,odr 输出的 beta 系数顺序和 numpy.polyfit 的顺序是相反的。所以绿色曲线没有正确计算出来。要绘制它,可以使用下面的代码:

plt.plot(x, fit_func(beta[::-1], x), "g--", lw = 2)
8

你现在使用的ODR方法是进行完整的正交距离回归。如果你想让它进行正常的非线性最小二乘拟合,可以在开始优化之前加上

Odr.set_job(fit_type=2)

这样你就能得到你想要的结果了。

拟合结果

完整的ODR之所以效果不好,是因为没有指定权重或标准差。很明显,这样会让点云的解释变得困难,因为它假设x和y的权重是一样的。如果你提供估计的标准差,ODR也会给出一个不错的结果(当然会有所不同)。

Data = scipy.odr.RealData(x, y, sx=0.1, sy=10)

撰写回答