最小二乘法拟合原理及代码实现
1. 最小二乘法定义
已知一组实验数据(xi, yi )(i = 0,1,2,….,m),且观测数据有误差
求自变量 x 与因变量 y 之间的函数关系 y = F(x),不要求 y = F(x)经过
所有点,而只要求在给定点的误差
δi = F(xi) – yi (i = 0,1,2,…,m)
按某种标准最小。
度量的标准不同,将导致不同的结果,常用的准则有如下三
种:
a. 残差的最大绝对值为最小
max
0
i m
|
i
|
max
0
i m
|
y F x
(
i
i
) | min
b. 残差的绝对值之和最小
m
i
0
|
i
|
m
i
0
y F x
|
(
i
i
) | min
c. 残差的平方和最小
m
2
i
m
i
0
i
0
(
y F x
(
i
i
2
)) min
其中 c 被称为最小二乘法原则。
具体定义:已知一组数据(xi, yi )(i = 0,1,2,….,m),在函数类
span
{1,
x
,....,
x
}n
中找到一个函数
y
S x
*( )
,是误差平方和最小,即:
m
m
2
i
i
0
i
0
S x
(
( )
*
y
i
2
)
min
S x
( )
m
i
0
S x
( ( )
y
i
2
)
这里:
S x
( )
a
0
a x
1
......
n
a x
n
(n
求最小二乘解
y
S x
*( )
的方法
现要求一
S x
( )
n
使得:
a x
k
k
n
k
0
I
m
i
0
S x
[
( )
n
y
i
]
2
n
m
[
i
0
k
0
k
a x
k
i
y
i
] min
2
显然
I
n
m
[
i
0
k
0
k
a x
k
i
y
i
]
2
为 0
a a
,
1
(
,....,
a 的多元函数,因此上述问题
)n
即为求
I
I a a
(
,
1
0
,....,
a
)n
的极值问题。
多元函数的求极值的必要条件:设函数 z=f(x,y)在点(x0,y0)具有
偏导数,且在点(x0,y0)有极值,则它在该点的偏导数必然为零。
由上述定理得:
I
a
j
2
n
m
(
i
0
k
0
a x
k
k
i
y x
)
k
i
i
0
(j = 0,1,2,….,n)
即:
n
m
(
k
0
i
0
j
x
k
i
)
a
k
(j = 0,1,2,….,n)
x y
j
i
i
m
i
0
上式是关于 0
a a
,
1
(
,....,
a 的线性方程组,用矩阵表示为:
)n
m
m
m
x
i
x
2
i
0
i
m
i
0
1
x
i
m
m
0
0
i
i
m
x
n
i
m
x
n
i
1
i
0
x
n
i
1
x
n
i
0
i
m
i
0
m
x
2
i
i
0
n
a
0
a
1
a
n
y
i
0
i
m
i
0
x y
i
i
x y
n
i
i
m
i
0
可以证明,方程组的系数矩阵式一个对称正定矩阵,故存在唯一解。
令
X
m
0
i
m
i
0
x
i
x
2
i
1
x
i
m
m
0
0
i
i
m
x
n
i
m
x
n
i
1
i
0
m
0
i
m
i
0
x
n
i
1
x
n
i
m
x
2
i
i
0
n
A
,
a
0
a
1
a
n
Y
,
m
0
i
m
i
0
m
i
0
y
i
x y
i
i
x y
n
i
i
,则
XA Y
1
X XA X Y
1
EA X Y
1
A X Y
1
其中 1X 是 X 的逆矩阵, E 是单位矩阵。
。可以算出 0
a a
,
1
(
,....,
a 。
)n
还可以用消元法算出 0
a a
,
1
(
,....,
a ,程序代码一般是用消元法算出
)n
系数的。
2. 直线拟合
曲线拟合中最基本和最常用的是直线拟合。设 x和 y之间的
函数关系由直线方程
y=a0+a1x
给出。式中有两个待定参数,a0代表截距,a1代表斜率。对于等精
度测量所得到的 m 组数据(xi,yi),i=1,2……,m,xi值被认为
是准确的,所有的误差只联系着 yi。
下面利用最小二乘法把观测数据拟合为直线。要求残差的平方
和最小,即
应有
a
0
a
1
m
0
i
m
i
0
m
i
0
y
i
a
0
a x
i
1
2
y
i
a
0
a x
i
1
2
2
y
i
a
0
a x
i
1
2
2
m
0
i
m
i
0
y
i
a
0
a x
i
1
0
y
i
a
0
a x
i
1
0
整理得
a m a
1
0
a
x
a
i
0
1
x
i
x y
x
2
i
i
i
y
i
解方程,得
a
0
x
2
i
x
y
i
i
m
x
x
2
i
i
x y
x
y
i
i
i
x
x
2
i
i
m
2
m
x y
i
i
a
1
i
2
C#程序代码的实现:
return false;
double fmX = 0.0;
double fmY = 0.0;
double fmXX = 0.0;
double fmXY = 0.0;
double fn = 0.0;
if( 0 == mapFoldList.Count)
{
}
bool fnCalculateLineKB(ref List mapFoldList,ref double
fk,ref double fb)
{
foreach (sAD_PWR iter in mapFoldList)
{
fmX += iter.fAD;
fmY += iter.fPWR;
fmXX += iter.fAD * iter.fAD;
fmXY += iter.fAD * iter.fPWR;
long lCount = mapFoldList.Count;
if(lCount < 2)
{
}
return false;
fn = lCount;
if(Math.Abs(fmX * fmX - fmXX * fn) < 0.000001)
{
}
return false;
}
fk = (fmY * fmX - fmXY * fn)/(fmX * fmX - fmXX * fn);
fb = (fmY - fmX * fk)/fn;
return true;
// Function : fnCurveSimulate(double n[], double T[], int M, int N,int
}
3. 曲线拟合(三阶及以上曲线)代码实现
根据 XA Y 得出,我们需要算出矩阵 X 和矩阵Y ,再对 X 进行矩阵
变换,得到消元后的矩阵,算出 0
a a
1,
,....,
a 。代码的实现:
n
/////////////////////////////////////////////////////////////////
// ParaIn : n[] 自变量数据数组
// T[] 因变量数据数组
// M 拟合公式的最高阶数
// N 数据组数
// xi 所返回系数值的对应参数
// ParaOut : 无
// Return : double
// Description : 用于最小二乘法曲线拟合
/////////////////////////////////////////////////////////////////
/////
xi)
//////
int N,int xi)
{
double [,]b = new double[10,20];
double [,]A = new double[10,10];
double []B = new double[10];
double []x = new double[10];
double []y = new double[10];
public static double fnCurveSimulate(double []n, double []T, int M,
for(j=0; j
//开始进行消元运算
for(i=1; i
}
//得出阶数最高位的系数
x[M-1]=y[M-1]/A[M-1,M-1];
for(i=M-2; i>=0; i--)
{
}
t=0;
for(j=i+1; j