numpy.polyfit与scipy.odr的比较
我有一个数据集,理论上它可以用一个二次多项式来描述。我想对这个数据进行拟合,所以我使用了 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]
在上面的图片中,numpy.polyfit
得到的结果(红色虚线)看起来还不错。而 scipy.odr
的结果(绿色虚线)则完全不对。我需要指出的是,在我想要拟合的实际数据集中,numpy.polyfit
和 scipy.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)