Math 数据拟合多项式
给定一组值Math 数据拟合多项式,math,statistics,Math,Statistics,给定一组值(x,f(x)),有没有办法找到最适合数据的给定次数的多项式 我知道,这是为了找到一个给定数据点的n次多项式,但这里有大量的值,我们想找到一个低次多项式(找到最佳线性拟合、最佳二次、最佳三次等)。这可能与 更一般地说,我想知道当我们有一个多元函数时的答案——比如说像(x,y,f(x,y)),并且想在变量中找到给定次数的最佳多项式(p(x,y))。(特别是多项式,而不是样条曲线或傅里叶级数。) 理论和代码/库(最好是Python语言,但任何语言都可以)都很有用。是的,这通常是通过使用最小
(x,f(x))
,有没有办法找到最适合数据的给定次数的多项式
我知道,这是为了找到一个给定数据点的n
次多项式,但这里有大量的值,我们想找到一个低次多项式(找到最佳线性拟合、最佳二次、最佳三次等)。这可能与
更一般地说,我想知道当我们有一个多元函数时的答案——比如说像(x,y,f(x,y))
,并且想在变量中找到给定次数的最佳多项式(p(x,y)
)。(特别是多项式,而不是样条曲线或傅里叶级数。)
理论和代码/库(最好是Python语言,但任何语言都可以)都很有用。是的,这通常是通过使用最小二乘法来实现的。还有其他方法可以说明多项式的拟合程度,但最小二乘法的理论最简单。一般的理论称为线性回归 你最好的选择可能是从一开始 它是免费的,可以做任何你想做的事情,甚至更多,但它有一个很大的学习曲线 如果您可以访问Mathematica,则可以使用拟合函数进行最小二乘拟合。我想象Matlab和它的开源对应物Octave有一个类似的函数。对于(x,f(x))情况: <席>席席(p)>如果你想将(席,f(席))拟合为n次多项式,则你可以建立一个线性最小二乘问题,其中数据(1,Xi,Xi,X^ 2,…,X^ n,F(XI))。这将返回一组系数(c0,c1,…,cn),因此最佳拟合多项式为*y=c0+c1*x+c2*x^2+…+cn*x^n* 通过在问题中包括y的幂和x与y的组合,可以推广这两个以上的因变量。在某种意义上,是适合给定数据点集的“最简单”插值多项式 有时这是有问题的,因为它在不同的数据点之间变化很大。拉格朗日多项式(如@j w发布的)在指定的点上为您提供精确的拟合,但是对于次数超过5或6的多项式,您可能会遇到数值不稳定 最小二乘法为您提供了“最佳拟合”多项式,误差定义为各个误差的平方和。(沿y轴测量点与生成结果的函数之间的距离,将它们平方,然后求和)MATLAB
polyfit
函数可执行此操作,并且使用多个返回参数,可以让它自动处理缩放/偏移问题(例如,如果你有100个点都在x=312.1和312.3之间,并且你想要一个6次多项式,你需要计算u=(x-312.2)/0.1,因此u值分布在-1和+=)之间
注意最小二乘拟合的结果受到x轴值分布的影响。如果x轴值间隔相等,则两端的误差会更大。如果您可以选择x值,并且您关心与已知函数和i轴的最大偏差插值多项式,然后使用将给你一些接近完美极小极大多项式的东西(很难计算)。这在数值公式中有详细讨论
编辑:从我收集的资料来看,这些都适用于一个变量的函数。对于多元函数来说,如果阶数超过,比如说,2,可能会困难得多。我确实找到了一个。感谢大家的回答。这里是另一个总结它们的尝试。如果我说的“明显”太多,请原谅事情:我以前对最小二乘法一无所知,所以对我来说一切都是新的 非多项式插值 正在拟合一个给定数据点的次多项式,例如,找到一个正好经过四个给定点的立方体。如问题中所述,这不是我想要的——我有很多点,想要一个小次多项式(除非我们运气好,否则只能近似拟合)-但是,由于一些答案坚持要谈论它,我应该提到它们:),等等 什么是最小二乘法? “最小二乘法”是多项式拟合程度的特定定义/标准/度量。(还有其他的,但这是最简单的。)假设您正在尝试拟合多项式 p(x,y)=a+bx+cy+dx2+ey2+fxy 到一些给定的数据点(xi,yi,Zi)(其中“Zi”是问题中的“f(xi,yi)”。使用最小二乘法,问题是找到“最佳”系数(a、b、c、d、e、f),从而最小化(保持“最小”)的是“残差平方和”,即 S=∑i(a+bxi+cyi+dxi2+eyi2+fxiyi-Zi)2 理论 重要的想法是,如果你把S看作(a,b,c,d,e,f)的函数,那么S就在它的。这意味着,例如∂/∂f=0,即 ∑i2(a+…+fxiyi-Zi)xiyi=0 和a,b,c,d,e的类似方程。 注意,这些只是a…f中的线性方程。所以我们可以用或任何一种方法来解决它们 这仍然被称为“线性最小二乘法”,因为尽管我们想要的函数是一个二次多项式,但它在参数(a、b、c、d、e、f)上仍然是线性的。请注意,当我们希望p(x,y)是任意函数fj的任何“线性组合”,而不仅仅是一个多项式(=“单项式的线性组合”)时,同样的情况也适用 代码 对于单变量情况(当只有变量x-fj是单项式xj时),有Numpy: 对于多元情况,或一般的线性最小二乘,存在SciPy,它采用值fj(xi)的矩阵a。(理论是它找到了A的形式。)在我们上面涉及(xi,yi,Zi)的例子中,拟合多项式意味着fj是单项式x()y()。下面找到最佳二次型(或最佳多项式
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)
>>> 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
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
+ (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
def Tn(n, x):
if n==0:
return 1.0
elif n==1:
return float(x)
else:
return (2.0 * x * Tn(n - 1, x)) - Tn(n - 2, x)
class ChebyshevFit:
def __init__(self):
self.Tn = Memoize(Tn)
def fit(self, data, degree=None):
"""fit the data by a 'minimal squares' linear combination of chebyshev polinomials.
cfr: Conte, de Boor; elementary numerical analysis; Mc Grow Hill (6.2: Data Fitting)
"""
if degree is None:
degree = 5
data = sorted(data)
self.range = start, end = (min(data)[0], max(data)[0])
self.halfwidth = (end - start) / 2.0
vec_x = [(x - start - self.halfwidth)/self.halfwidth for (x, y) in data]
vec_f = [y for (x, y) in data]
mat_phi = [numpy.array([self.Tn(i, x) for x in vec_x]) for i in range(degree+1)]
mat_A = numpy.inner(mat_phi, mat_phi)
vec_b = numpy.inner(vec_f, mat_phi)
self.coefficients = numpy.linalg.solve(mat_A, vec_b)
self.degree = degree
def evaluate(self, x):
"""use Clenshaw algorithm
http://en.wikipedia.org/wiki/Clenshaw_algorithm
"""
x = (x-self.range[0]-self.halfwidth) / self.halfwidth
b_2 = float(self.coefficients[self.degree])
b_1 = 2 * x * b_2 + float(self.coefficients[self.degree - 1])
for i in range(2, self.degree):
b_1, b_2 = 2.0 * x * b_1 + self.coefficients[self.degree - i] - b_2, b_1
else:
b_0 = x*b_1 + self.coefficients[0] - b_2
return b_0