皆様からの返信ありがとうございます。それらを要約する別の試みがあります。あまりにも多くの「明白な」ことを言った場合はご容赦ください。以前は最小二乗法について何も知らなかったので、すべてが私にとって新しいものでした。
多項式補間ではありません
多項式補間nは、与えられたデータポイントの次数の多項式を近似しn+1ます。たとえば、与えられた4つのポイントを正確に通過する3次を見つけます。質問で述べたように、これは私が望んでいたことではありませんでした—私は多くのポイントを持ち、小さな次数の多項式を望んでいました(運が良ければ、ほぼ適合します)—しかし、いくつかの答えは話すことを主張したのでそれについて、私はそれらに言及する必要があります:)ラグランジュ多項式、ファンデルモンド行列など。
最小二乗とは何ですか?
「最小二乗」は、多項式が「どれだけうまく」適合するかについての特定の定義/基準/「メトリック」です。(他にもありますが、これが最も簡単です。)多項式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 = ∑ i(a + bx i + cy i + dx i 2 + ey i 2 + fx i y i --Z i)2
仮説
重要な考え方は、Sを(a、b、c、d、e、f)の関数として見ると、勾配が0になる点でSが最小化されるということです。これは、たとえば∂S/∂f= 0、つまり
∑ i 2(a+…+fx i y i --Z i)x i y i = 0
およびa、b、c、d、eの同様の方程式。これらはa…fの単なる線形方程式であることに注意してください。したがって、ガウスの消去法または通常の方法のいずれかを使用してそれらを解決できます。
これは、「線形最小二乗」と呼ばれます。これは、必要な関数が2次多項式であったにもかかわらず、パラメーター(a、b、c、d、e、f)では線形であるためです。p(x、y)を単なる多項式(=「単項式の線形結合」)ではなく、任意の関数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 j(x i )の行列Aを取ります。(理論は、Aのムーア-ペンローズ疑似逆行列を見つけるというものです。)(x i、y i、Z i)を含む上記の例では、多項式を当てはめると、f jが単項式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.33y 2を生成しましたが、これは不可解でした...私が常に持っていたx[i]=y[i]ので、多項式が同じであることに気付くまで:x 2 + 2xy + y 2 = 4x 2 =(4/3)(x 2 + xy + y 2)。したがって、道徳は、「正しい」多項式を取得するためにポイントを慎重に選択することが重要であるということです。(選択できる場合は、多項式補間にチェビシェフノードを選択する必要があります。最小二乗法についても同じことが当てはまるかどうかはわかりません。)
- 過剰適合:高次の多項式は常にデータをより適切に適合させることができます。を3、4、または5に変更し
degreeても、ほとんど同じ2次多項式(高次の項の係数は0)を認識しますが、次数が大きいほど、高次の多項式の近似を開始します。ただし、次数が6の場合でも、nを大きくすると(20ではなくより多くのデータポイント、たとえば200)、2次多項式に適合します。したがって、モラルは過剰適合を回避することです。そのため、可能な限り多くのデータポイントを取得することが役立つ場合があります。
- 私が完全には理解していない数値安定性の問題があるかもしれません。
- 多項式が必要ない場合は、スプライン(区分的多項式)などの他の種類の関数との適合性を高めることができます。