web-dev-qa-db-ja.com

データへの多項式のあてはめ

値のセット_(x,f(x))_が与えられた場合、データに最適な次数の多項式を見つける方法はありますか?

多項式補間 を知っています。これは_n+1_データポイントが与えられた次数nの多項式を見つけるためのものですが、ここには多数の値があり、低次多項式(最適な線形近似、最適な2次、最適な3次などを見つけます)。 最小二乗 ...に関連している可能性があります.

より一般的には、多変量関数(たとえば_(x,y,f(x,y))_など)があるときに答えを知り、特定の次数の最適な多項式(p(x,y))を見つけたい変数。 (具体的には、スプラインやフーリエ級数ではなく、多項式です。)

理論とコード/ライブラリ(Pythonが望ましいが、どの言語でもかまいません)の両方が有用です。

48
ShreevatsaR

みんなの返信をありがとう。これらを要約する別の試みを次に示します。あまりにも多くの「明白な」ことを言った場合はご容赦ください。以前は最小二乗については何も知らなかったので、すべてが新しいものでした。

NOT多項式補間

多項式補間 は、与えられた_n+1_データポイントの次数nの多項式に適合しています。与えられた4つの点を正確に通過する立方体を見つける。質問で述べたように、これは私が望んでいたことではありませんでした-私は多くの点を持っていて、次数が小さい多項式を望んでいました(幸運でなければ、およそ適合します)-答えのいくつかはそれについて話すことを主張しました、私はそれらに言及する必要があります:) ラグランジュ多項式バンデルモンド行列 など.

最小二乗とは何ですか?

「最小二乗」は、多項式が「どれだけうまく適合するか」の特定の定義/基準/「メトリック」です。 (他にもありますが、これは最も簡単です。)多項式p(x、y)= a + bx + cy + dxを近似しようとしているとしましょう2 + ey2 +特定のデータポイント(x、y、Z)(ここで、「Z"は" f(x、y)」の質問)。最小二乗法の問題は、最小化(「最小」のまま)が「合計」になるように、「最良」係数(a、b、c、d、e、f)を見つけることです。平方の残差」、すなわち

S = ∑ (a + bx + cy + dx2 + ey2 + fxy -Z2

理論

重要な考え方は、(a、b、c、d、e、f)の関数としてSを見ると、Sは 最小化 で、その 勾配 。これは、たとえば∂S/∂f= 0、つまり

2(a +…+ fxy -Z)バツy = 0

およびa、b、c、d、eの同様の方程式これらはa…fの単なる線形方程式であることに注意してください。 ガウス消去法 または 通常の方法 のいずれかで解決できます。

これは、「線形最小二乗」と呼ばれます。これは、必要な関数が2次多項式であるにもかかわらず、まだ線形パラメータ内(a、b、c、d、e、f)であるためです。 p(x、y)をarbitrary関数fの「線形結合」にしたい場合にも同じことが機能することに注意してください。j、単に多項式(=「単項式の線形結合」)の代わりに。

コード

単変量の場合(変数xのみがある場合— fj 単項式ですxj)、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
_

多変量の場合、または一般的な線形最小二乗の場合、SciPyがあります。 ドキュメントで説明されているように 、値fの行列Aを取りますjバツ)。 (理論は、Aの Moore-Penrose pseudoinverse を見つけるということです。)上記の例では(x、y、Z)、多項式のフィッティングはfj 単項式はx()y()。以下は、最高の2次(または、「次数= 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
_

プリント

_ + (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
_

多項式がxであることを発見しました2+ 2xy + y2+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.33y2、それは不可解でした...私が常に_x[i]=y[i]_を持っているので、多項式が同じであることに気づくまで:x2+ 2xy + y2 = 4x2 =(4/3)(x2+ xy + y2)。そのため、「正しい」多項式を得るためにポイントを慎重に選択することが重要であるというのが教訓です。 (選択できる場合は、多項式補間に Chebyshevノード を選択する必要があります。最小二乗にも同じことが当てはまるかどうかはわかりません。)
  • オーバーフィッティング:高次の多項式は常にデータにより良く適合することができます。 degreeを3または4または5に変更しても、ほとんど同じ2次多項式(高次の項の係数は0)を認識しますが、次数が大きくなると、高次の多項式の適合を開始します。しかし、次数6でも、より大きいn(20の代わりに200などのより多くのデータポイント)を取得しても、2次多項式に適合します。したがって、モラルは、過剰適合を避けることです。
  • 数値安定性 の問題があるかもしれません。私は完全には理解していません。
  • 多項式が必要ない場合は、他の種類の関数でより良い近似を取得できます。 スプライン (区分的多項式)。
57
ShreevatsaR

はい、これは通常、最小二乗法を使用して行われます。多項式の適合度を指定する方法は他にもありますが、理論は最小二乗に対して最も簡単です。一般理論は線形回帰と呼ばれます。

あなたの最善の策は、おそらく 数値レシピ で始めることです。

[〜#〜] r [〜#〜] は無料で、必要なことはすべて実行できますが、大きな学習曲線があります。

Mathematicaにアクセスできる場合は、Fit関数を使用して最小二乗近似を行うことができます。 MatlabとそのオープンソースのOctaveにも同様の機能があると思います。

7
John D. Cook

より高い次数の多項式は常にデータにより良く適合することを忘れないでください。より高次の多項式は、通常、非常にありそうもない関数( Occam's Razor を参照)につながりますが、(過剰適合)。単純性(多項式の次数)と適合(最小二乗誤差など)のバランスを見つけたい場合。定量的には、 赤池情報量基準 または ベイズ情報量基準 のテストがあります。これらのテストは、どのモデルを優先するかをスコア化します。

4
Fredriku73

(xi、f(xi))を次数の多項式に当てはめたい場合nを使用して、データの線形最小二乗問題を設定します(1、xi、xi、xi ^ 2、...、xi ^ n、f(xi))。これは係数のセットを返します( c0、c1、...、cn)したがって、最適な多項式は* y = c0 + c1 * x + c2 * x ^ 2 + ... + cn * x ^ n。*

yのべき乗とxyの組み合わせを問題に含めることにより、この2つ以上の従属変数を一般化できます。

2
David Norman

大学でこの本を持っていましたが、それでも私は非常に便利だと感じています。Conte、de Boor;基本的な数値解析; Mc Grow Hill。関連する段落は6.2:データフィッティングです。
サンプルコードはFORTRANに含まれており、リストも読みにくいですが、説明は同時に深く明確です。あなたは何をしているのかを理解するだけでなく、それを行うだけではありません(数値レシピの私の経験)。
私は通常、数値レシピから始めますが、このようなことのために、私はすぐにConte-de Boorをつかまなければなりません。

コードを投稿した方がいいかもしれません...少し削られていますが、最も関連性の高い部分があります。明らかにnumpyに依存しています!

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
2
mariotomo

ラグランジュ多項式(@j wに投稿)は、指定した点に正確に適合しますが、5または6以上の次数の多項式では、数値の不安定性が発生する可能性があります。

最小二乗法は、個々の誤差の二乗和として定義された誤差を持つ「最適な」多項式を提供します。 (あなたが持っている点と結果の関数の間のy軸に沿った距離を取り、それらを平方し、それらを合計します)MATLAB polyfit関数はこれを行い、複数の戻り引数で、あなたはそれを持つことができますスケーリング/オフセットの問題を自動的に処理します(たとえば、x = 312.1と312.3の間に100ポイントがあり、6次の多項式が必要な場合、u =(x-312.2)/0.1を計算します。 u値は-1と+ =の間で分布します。

[〜#〜] note [〜#〜]最小二乗近似の結果はstrongly x軸値の分布の影響を受けます。 x値が等間隔の場合、両端でより大きなエラーが発生します。 x値をchooseすることができ、既知の関数と補間多項式からの最大偏差に注意する場合は、 Chebyshev多項式の使用 は、完璧なミニマックス多項式に近いものを提供します(計算が非常に困難です)。これについては、「数値のレシピ」で詳しく説明しています。

編集:私が収集したものから、これはすべて1つの変数の関数に対してうまく機能します。多変量関数の場合、次数がたとえば2を超えると、さらに困難になる可能性があります。 Googleブックスのリファレンス が見つかりました。

2
Jason S

最小二乗問題を線形代数問題として表現する方法を知っていれば、Excelの行列関数を使用してクイックフィットを計算するのはかなり簡単です。 (これは、Excelが線形代数ソルバーとしてどの程度信頼できるかによって異なります。)

0
duffymo

近似多項式とexact oneを見つけることとの間には大きな違いがあることを覚えておいてください。

たとえば、4ポイントを与えると、

  1. 最小二乗などの方法で線を近似する
  2. 最小二乗などの方法で放物線を近似する
  3. これらの4つの点でexact 3次関数を見つけます。

最適な方法を選択してください!

0
stalepretzel