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