需要一个Python多项式拟合函数,该函数返回协方差。

4
我希望在数据集 (X,Y,Yerr) 上执行最小二乘多项式拟合并获得拟合参数的协方差矩阵。由于我有许多数据集,所以 CPU 时间是一个问题,因此我正在寻求解析(=快速)解决方案。我找到了以下(非理想)选项: numpy.polyfit 进行拟合,但不考虑误差 Yerr,也不返回协方差; numpy.polynomial.polynomial.polyfit接受 Yerr 作为输入(以权重形式),但也不返回协方差; scipy.optimize.curve_fitscipy.optimize.leastsq可以定制拟合多项式并返回协方差矩阵,但由于它们是迭代方法,因此比 polyfit例程慢得多(这会产生解析解);
Python 提供了一个返回拟合参数协方差的解析多项式拟合程序吗(或者我必须自己编写)?
更新: 似乎在 Numpy 1.7.0 中,numpy.polyfit 现在不仅接受权重,而且还返回系数的协方差矩阵... 因此,问题已解决! :-)

请查看mpfit或kmpfit。http://www.astro.rug.nl/software/kapteyn/kmpfit.html - reptilicus
根据链接,这是另一个(通用的)迭代求解器。由于速度的原因,我正在寻找分析(=非迭代)解决方案 - 这对于多项式来说是完全可能的。 - Rolf Bartstra
4
Statsmodels是什么?https://groups.google.com/forum/?fromgroups=#!topic/pystatsmodels/paCNa5sXbOo http://statsmodels.sourceforge.net/devel/generated/statsmodels.regression.linear_model.OLS.html - joris
@joris 这个链接可能确实有用,我会去看一下的。谢谢 - Rolf Bartstra
进行多项式拟合的代码非常简单…为什么不只是改编现有的numpy程序以同时返回协方差矩阵呢? - Brian B
2个回答

0
你想要一个快速的加权最小二乘模型,可以返回协方差矩阵而不需要额外的开销吗?一般来说,正确的协方差矩阵取决于数据生成过程(DGP),因为不同的DGP(比如误差异方差)意味着参数估计的不同分布(想想白噪声和OLS标准误之间的区别)。但是如果你可以假设WLS是正确的方法,我相信你会使用WLS的渐近方差估计值beta,(1/n X'V^-1X)^-1,其中V是从Yerrs创建的加权矩阵。如果numpy.polynomial.polynomial.polyfit对你有用,那么这是一个非常简单的公式。
我找了一个在线参考资料,但没有找到。但是请参见Fumio Hayashi的《经济计量学》,2000年,普林斯顿大学出版社,第133-137页的推导和讨论。
更新12/4/12: 还有另一个与之相似的stackoverflow问题:numpy.polyfit has no keyword 'cov',其中有一个很好的解释(带有代码),说明如何使用scikits.statsmodels来实现你想要的功能。我相信你会想要替换这行代码:
result = sm.OLS(Y,reg_x_data).fit()

result = sm.WLS(Y,reg_x_data, weights).fit()

在使用numpy.polynomial.polynomial.polyfit时,您可以像以前一样将权重定义为Yerr的函数。有关使用WLS和statsmodels的更多详细信息,请访问statsmodels网站


谢谢,我知道如何计算公式,只是希望相应的代码已经在Python/Numpy中实现了 - 但似乎并不是这种情况 :-( - Rolf Bartstra

0

这里使用scipy.linalg.lstsq

import numpy as np,numpy.random, scipy.linalg
#generate the test data
N = 100
xs = np.random.uniform(size=N)
errs = np.random.uniform(0, 0.1, size=N) # errors
ys = 1 + 2 * xs + 3 * xs ** 2 + errs * np.random.normal(size=N)

# do the fit
polydeg = 2
A = np.vstack([1 / errs] + [xs ** _ / errs for _ in range(1, polydeg + 1)]).T
result = scipy.linalg.lstsq(A, (ys / errs))[0]
covar = np.matrix(np.dot(A.T, A)).I
print result, '\n', covar

>> [ 0.99991811  2.00009834  3.00195187]
[[  4.82718910e-07  -2.82097554e-06   3.80331414e-06]
 [ -2.82097554e-06   1.77361434e-05  -2.60150367e-05]
 [  3.80331414e-06  -2.60150367e-05   4.22541049e-05]]

谢谢,这对于单一数据集或者多个数据集都可以,只要每组数据集中的误差相同就可以。然而,通常不同的数据集可能会有不同的误差,导致每种情况下矩阵A都不同。在这种情况下,“linalg.lstsq”算法需要被放置在一个循环中——而这正是我不想要的(因为计算速度慢)。同时,在这种一般情况下,解可以通过一次大规模的数组操作来计算,这将极大地加快速度。据我所知,目前不存在这样的函数(也就是说:还不存在,因为我自己要构建它)。 - Rolf Bartstra
如果您有不同的数据集,您必须重新构建矩阵(这是非常轻量级的操作),并再次解决系统。没有其他方法。我认为将不同的卡方问题合并成一个大问题没有任何好处,因为矩阵计算的性能将是~ N^2,所以您最好解决多个小问题而不是一个具有许多参数的大问题。 - sega_sai
你说得没错,但是将不同的卡方问题合并成一个大问题并不是我的意思。我旨在通过在单个三维数组操作中并行解决各个问题,其中不同的数据集沿第三维度排列。我已经尝试过这种“快速而简单”的方法,在我的情况下(200万个数据集),它比循环遍历各个数据集快500倍! - Rolf Bartstra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接