一、線性最小二乘擬合
使用一個簡單函數在整體上逼近已知函數,使其在整體上儘可能與原始數據曲線近似。記爲:
稱之爲擬合曲線,若該函數爲插值多項式,則所有偏差爲零。
但實際情況中,我們不可能要求近似曲線
y =
嚴格通過這麼多數據點。但爲了使其儘可能反映所給數據的變化趨勢,我們可以要求偏差的絕對值儘可能小,甚至是所有偏差中的最大值儘可能小。我們可以通過使選取的近似曲線在節點xi 處的偏差的平方和達到最小來實現這一目標,這一原則就是 最小二乘原則。
按最小原則選擇的擬合曲線就稱爲最小二乘擬合曲線,此方法稱爲最小二乘法。
實用公式推導:
假設我們此處有這樣一組數據點,這些點的分佈接近於在一條直線上,因此選一條直線(一條曲線則加入對應方程推導)來擬合這組數據,令:
根據最小二乘原則,有:
令a0,a1爲未知數,則此處轉換爲求二元函數S(a0,a1)的極小點問題:
由此可得:
聯立解得:
即得到了待求的擬合直線段。
C++實現:
bool gFittingLine(double *xArray, double *yArray, int firstIndex, int lastIndex,
double &a, double &b)
{
int count = lastIndex-firstIndex+1;
if(count < 2) return false;
double s0 = (double)count, s1 = 0, s2 = 0, t0 = 0, t1 = 0;
for(int i=firstIndex;i<=lastIndex;i++)
{
s1 += xArray[i];
s2 += (xArray[i]*xArray[i]);
t0 += yArray[i];
t1 += (xArray[i]*yArray[i]);
}
double d = s0*s2-s1*s1;
b = (s2*t0-s1*t1)/d;
a = (s0*t1-s1*t0)/d;
return true;
}
實現對二維平面離散點的曲線擬合
二、最小二乘面擬合
對空間中的一系列散點,尋求一個近似平面,與線性最小二乘一樣,只是變換了擬合方程:
使用平面的一般方程:
Ax + By + CZ + D = 0
可以令平面方程爲:
由最小二乘法知:
同樣分別取 a0,a1,a2的偏導數:
即是:
換算爲矩陣形式有:
可以直接通過克拉默法則求出a0,a1,a2的行列式表達式,有:
c++實現(gDaterm3() 爲自定義的三階行列式計算函數):
bool gFittingPlane(double *x, double *y, double *z, int n, double &a, double &b, double &c)
{
int i;
double x1, x2, y1, y2, z1, xz, yz, xy, r;
x1 = x2 = y1 = y2 = z1 = xz = yz = xy = 0;
for(i=0; i<n; i++)
{
x1 += x[i];
x2 += x[i]*x[i];
xz += x[i]*z[i];
y1 += y[i];
y2 += y[i]*y[i];
yz += y[i]*z[i];
z1 += z[i];
xy += x[i]*y[i];
}
r = gDeterm3(x2, xy, x1, xy, y2, y1, x1, y1, n);
if(IS_ZERO(r)) return false;
a = gDeterm3(xz, xy, x1, yz, y2, y1, z1, y1, n) / r;
b = gDeterm3(x2, xz, x1, xy, yz, y1, x1, z1, n) / r;
c = gDeterm3(x2, xy, xz, xy, y2, yz, x1, y1, z1) / r;
return true;
}