Shr*_*saR 57
感谢大家的回复.这是另一种总结它们的尝试.请原谅,如果我说太多"明显"的事情:我之前对最小二乘一无所知,所以一切对我来说都是新的.
多项式插值拟合n给定n+1数据点的多项式,例如找到精确通过四个给定点的立方.正如在问题中所说,这不是我想要的 - 我有很多分数并且想要一个小程度多项式(除非我们很幸运,它们只能大致适合) - 但是因为一些答案坚持谈论关于它,我应该提到它们:拉格朗日多项式,Vandermonde矩阵等.
"最小二乘法"是多项式拟合"有多好"的特定定义/标准/"度量".(还有其他的,但这是最简单的.)假设你试图将多项式p(x,y)= a + bx + cy + dx 2 + ey 2 + fxy拟合到某些给定的数据点(x i,y i),Z i)(其中"Z i "在问题中是"f(x i,y i)").对于最小二乘问题,问题是找到"最佳"系数(a,b,c,d,e,f),使得最小化(保持"最小")的是"残差平方和",即
S =Σ 我(A + BX 我 + CY 我 + DX 我2 + EY 我2 + FX 我 ÿ 我 - z 我)2
重要的想法是,如果将S视为(a,b,c,d,e,f)的函数,则S 在其梯度为0的点处被最小化.这意味着例如∂S/∂f= 0,即
Σ 我图2(a + ... + FX 我 ÿ 我 - z 我)X 我 Ŷ 我 = 0
和a,b,c,d,e的类似方程式.请注意,这些只是... f中的线性方程式.所以我们可以用高斯消元法或任何常用方法来解决它们.
这仍称为"线性最小二乘法",因为虽然我们想要的函数是二次多项式,但它在参数(a,b,c,d,e,f)中仍然是线性的.注意,当我们希望p(x,y)是任意函数f j的任何"线性组合"时,同样的事情是有效的,而不仅仅是多项式(="单项式的线性组合").
对于单变量情况(当只有变量x - f j是单项式x j时),有Numpy的polyfit:
>>> import numpy
>>> xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ys = [1.1, 3.9, 11.2, 21.5, 34.8, 51, 70.2, 92.3, 117.4, 145.5]
>>> p = numpy.poly1d(numpy.polyfit(xs, ys, deg=2))
>>> print p
2
1.517 x + 2.483 x + 0.4927
Run Code Online (Sandbox Code Playgroud)
对于多变量情况,或一般的线性最小二乘,存在SciPy.如其文档中所解释的,它采用值f j(x i)的矩阵A. (理论是它找到了A 的Moore-Penrose伪逆.)在上面的例子中涉及(x i,y i,Z i),拟合多项式意味着f j是单项式x () y ().以下查找最佳二次方(或任何其他度数的最佳多项式,如果更改"degree = 2"行):
from scipy import linalg
import random
n = 20
x = [100*random.random() for i in range(n)]
y = [100*random.random() for i in range(n)]
Z = [(x[i]+y[i])**2 + 0.01*random.random() for i in range(n)]
degree = 2
A = []
for i in range(n):
A.append([])
for xd in range(degree+1):
for yd in range(degree+1-xd):
A[i].append((x[i]**xd)*(y[i]**yd)) #f_j(x_i)
c,_,_,_ = linalg.lstsq(A,Z)
j = 0
for xd in range(0,degree+1):
for yd in range(0,degree+1-xd):
print " + (%.2f)x^%dy^%d" % (c[j], xd, yd),
j += 1
Run Code Online (Sandbox Code Playgroud)
版画
+ (0.01)x^0y^0 + (-0.00)x^0y^1 + (1.00)x^0y^2 + (-0.00)x^1y^0 + (2.00)x^1y^1 + (1.00)x^2y^0
Run Code Online (Sandbox Code Playgroud)
所以它发现多项式是x 2 + 2xy + y 2 +0.01.[最后一个术语有时是-0.01,有时是0,由于我们添加的随机噪声,这是预期的.
Python + Numpy/Scipy的替代品是R和计算机代数系统:Sage,Mathematica,Matlab,Maple.甚至Excel也许能够做到这一点.Numerical Recipes讨论了自己实现它的方法(在C,Fortran中).
x=y=range(20),而不是随机点,它总是产生1.33X 2 + 1.33xy + 1.33y 2,这是令人费解...直到我意识到,因为我总是有x[i]=y[i],多项式都是一样的:X 2 + 2XY + Y 2 = 4x 2 =(4/3)(x 2 + xy + y 2).因此,道德是仔细选择要点以获得"正确的"多项式是很重要的.(如果你可以选择,你应该选择Chebyshev节点进行多项式插值;不确定最小二乘方是否也是如此.)degree为3或4或5,它仍然主要识别相同的二次多项式(对于更高度项,系数为0)但对于更大的度数,它开始拟合更高次多项式.但即使是6度,采用更大的n(更多的数据点而不是20,比如200)仍然适合二次多项式.因此,道德是避免过度拟合,为此可能有助于尽可能多地获取数据点.是的,通常这样做的方法是使用最小二乘法.还有其他方法可以指定多项式的拟合程度,但对于最小二乘法,理论最简单.一般理论称为线性回归.
你最好的选择可能是从Numerical Recipes开始.
R是免费的,可以做你想要的一切,但它有一个很大的学习曲线.
如果您可以访问Mathematica,则可以使用"拟合"功能进行最小二乘拟合.我想Matlab及其开源对应物Octave具有类似的功能.
对于(x,f(x))案例:
import numpy
x = numpy.arange(10)
y = x**2
coeffs = numpy.polyfit(x, y, deg=2)
poly = numpy.poly1d(coeffs)
print poly
yp = numpy.polyval(poly, x)
print (yp-y)
Run Code Online (Sandbox Code Playgroud)