最小二乘法的正交多项拟合算法
数学表达式
参考清华大学 李庆杨《数值分析》第五版 P69
构造正交多项式
p
k
(
x
)
k
=
0
n
{p_k(x)}^n_{k=0}
pk(x)k=0n
p
0
(
x
)
=
1
p
1
(
x
)
=
(
x
−
A
1
)
p
0
(
x
)
.
.
.
p
k
+
1
(
x
)
=
(
x
−
A
k
+
1
)
p
k
(
x
)
−
B
k
p
k
−
1
(
x
)
k
=
1
,
2
,
3
,
.
.
.
,
n
−
1
p_0(x) = 1 \\ p_1(x) = (x-A_1)p_0(x) \\ ...\\ p_{k+1}(x) = (x-A_{k+1})p_k(x) - B_k p_{k-1}(x) \\ k =1,2,3,...,n-1
p0(x)=1p1(x)=(x−A1)p0(x)...pk+1(x)=(x−Ak+1)pk(x)−Bkpk−1(x)k=1,2,3,...,n−1
其中
A
k
+
1
=
(
x
p
k
,
p
k
)
(
p
k
,
p
k
)
=
∑
i
=
0
m
x
i
p
k
2
(
x
i
)
∑
i
=
0
m
p
k
2
(
x
i
)
,
k
=
0
,
1
,
2
,
.
.
.
,
n
−
1
B
k
=
(
p
k
,
p
k
)
(
p
k
−
1
,
p
k
−
1
)
=
∑
i
=
0
m
p
k
2
(
x
i
)
∑
i
=
0
m
p
k
−
1
2
(
x
i
)
,
k
=
1
,
2
,
.
.
.
,
n
−
1
A_{k+1} = \frac{(xp_k,p_k)}{(p_{k},p_{k})} = \frac{\sum_{i=0}^m x_ip^2_k(x_i)}{\sum_{i=0}^mp_k^2(x_i)},k=0,1,2,...,n-1 \\ B_k = \frac{(p_k,p_k)}{(p_{k-1},p_{k-1})}= \frac{\sum_{i=0}^m p^2_k(x_i)}{\sum_{i=0}^mp_{k-1}^2(x_i)},k=1,2,...,n-1 \\
Ak+1=(pk,pk)(xpk,pk)=∑i=0mpk2(xi)∑i=0mxipk2(xi),k=0,1,2,...,n−1Bk=(pk−1,pk−1)(pk,pk)=∑i=0mpk−12(xi)∑i=0mpk2(xi),k=1,2,...,n−1
利用正交多项式构建
a
∗
a^*
a∗
a
k
∗
=
(
f
,
p
k
)
(
p
k
,
p
k
)
=
∑
i
=
0
m
f
(
x
i
)
p
k
(
x
i
)
∑
i
=
0
m
p
k
2
(
x
i
)
a^*_k = \frac{(f,p_k)}{(p_k,p_k)}=\frac{\sum^m_{i=0}f(x_i)p_k(x_i)}{\sum^m_{i=0}p^2_k(x_i)}
ak∗=(pk,pk)(f,pk)=∑i=0mpk2(xi)∑i=0mf(xi)pk(xi)
则待拟合曲线的正交多项式为
S
∗
=
a
0
∗
p
0
(
x
)
+
a
1
∗
p
1
(
x
)
+
.
.
.
+
a
n
∗
p
n
(
x
)
S^* = a^*_0p_0(x) + a^*_1p_1(x) + ... + a^*_np_n(x)
S∗=a0∗p0(x)+a1∗p1(x)+...+an∗pn(x)
计算示例
给定数据表,求二次最小二乘拟合多项式
x i x_i xi | 0 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0 |
---|---|---|---|---|---|---|---|
y i y_i yi | 1.0 | 1.75 | 1.96 | 2.19 | 2.44 | 2.71 | 3.0 |
- 求第一项
a
0
∗
a^*_0
a0∗
a 0 ∗ = ( f , p 0 ) ( p 0 , p 0 ) = ∑ i = 0 6 f ( x i ) p 0 ( x i ) ∑ i = 0 6 p 0 2 ( x i ) a^*_0 = \frac{(f,p_0)}{(p_0,p_0)}=\frac{\sum^6_{i=0}f(x_i)p_0(x_i)}{\sum^6_{i=0}p^2_0(x_i)} a0∗=(p0,p0)(f,p0)=∑i=06p02(xi)∑i=06f(xi)p0(xi)
p 0 ( x i ) = 1 ; p_0(x_i)=1; p0(xi)=1;
∑ 0 6 f ( x i ) = 15.05 ; \sum^6_0{f(x_i)}=15.05; ∑06f(xi)=15.05;
求得 a 0 ∗ = 15.05 / 7 = 2.15 a^*_0 = 15.05/7=2.15 a0∗=15.05/7=2.15
- 求第二项
a
1
∗
a^*_1
a1∗
a 1 ∗ = ( f , p 1 ) ( p 1 , p 1 ) = ∑ i = 0 6 f ( x i ) p 1 ( x i ) ∑ i = 0 6 p 1 2 ( x i ) a^*_1 = \frac{(f,p_1)}{(p_1,p_1)}=\frac{\sum^6_{i=0}f(x_i)p_1(x_i)}{\sum^6_{i=0}p^2_1(x_i)} a1∗=(p1,p1)(f,p1)=∑i=06p12(xi)∑i=06f(xi)p1(xi)
先确定
p
1
(
x
i
)
=
x
−
A
1
p_1(x_i)=x-A_1
p1(xi)=x−A1, 求
A
1
A_1
A1
A
1
=
(
x
p
0
,
p
0
)
(
p
0
,
p
0
)
=
∑
i
=
0
6
x
i
∑
i
=
0
6
p
0
∗
p
0
=
4.5
7
=
0.64
A_1 = \frac{(xp_0,p_0)}{(p_{0},p_{0})} =\frac{\sum^6_{i=0}x_i}{\sum^6_{i=0}p_0*p_0} = \frac{4.5}{7} = 0.64
A1=(p0,p0)(xp0,p0)=∑i=06p0∗p0∑i=06xi=74.5=0.64
则
p
1
(
x
i
)
=
x
−
0.64
p_1(x_i)= x- 0.64
p1(xi)=x−0.64,求得
a
1
∗
=
1.30
0.657
≈
1.98
a_1^*= \frac{1.30}{0.657} \approx 1.98
a1∗=0.6571.30≈1.98
- 求第三项
a
2
∗
a^*_2
a2∗
a 2 ∗ = ( f , p 2 ) ( p 2 , p 2 ) = ∑ i = 0 6 f ( x i ) p 2 ( x i ) ∑ i = 0 6 p 2 2 ( x i ) a^*_2 = \frac{(f,p_2)}{(p_2,p_2)}=\frac{\sum^6_{i=0}f(x_i)p_2(x_i)}{\sum^6_{i=0}p^2_2(x_i)} a2∗=(p2,p2)(f,p2)=∑i=06p22(xi)∑i=06f(xi)p2(xi)
p 2 ( x ) = ( x − A 2 ) p 1 ( x ) − B 1 p 0 ( x ) = ( x − A 2 ) ( x − A 1 ) − B 1 p_2(x) = (x-A_2)p_1(x)-B_1p_0(x) = (x-A_2)(x-A_1)-B_1 p2(x)=(x−A2)p1(x)−B1p0(x)=(x−A2)(x−A1)−B1
A 2 = ( x p 1 , p 1 ) ( p 1 , p 1 ) = ∑ i = 0 6 x i ∗ ( x i − 0.64 ) 2 ∑ i = 0 6 ( x i − 0.64 ) 2 = 0.2242 0.6572 = 0.34 A_2 = \frac{(xp_1,p_1)}{(p_{1},p_{1})} =\frac{\sum^6_{i=0}x_i*(x_i-0.64)^2}{\sum^6_{i=0}(x_i-0.64)^2} = \frac{0.2242}{0.6572} = 0.34 A2=(p1,p1)(xp1,p1)=∑i=06(xi−0.64)2∑i=06xi∗(xi−0.64)2=0.65720.2242=0.34
B 1 = ( p 1 , p 1 ) ( p 0 , p 0 ) = 0.6572 7 = 0.094 B_1 = \frac{(p_1,p_1)}{(p_0,p_0)}= \frac{0.6572}{7}=0.094 B1=(p0,p0)(p1,p1)=70.6572=0.094
p 2 ( x ) = x 2 − 0.98 x + 0.12 p_2(x) = x^2 - 0.98x +0.12 p2(x)=x2−0.98x+0.12
求得【此处需要高精度计算】
a
2
∗
≈
0.0686
0.0686
≈
1
a^*_2 \approx \frac{0.0686}{0.0686} \approx 1
a2∗≈0.06860.0686≈1
最终
S
∗
=
a
0
∗
p
0
(
x
)
+
a
1
∗
p
1
(
x
)
+
a
2
∗
p
2
(
x
)
=
x
2
+
x
+
1
S^* = a^*_0p_0(x) + a^*_1p_1(x) +a^*_2p_2(x) =x^2+x+1
S∗=a0∗p0(x)+a1∗p1(x)+a2∗p2(x)=x2+x+1
正交多项式是目前为止多项式拟合最好的方法,不用解线性方程组,根据次数 n,只用递推公式方便地计算正交多项式;MATLAB 正交多项式最小二乘拟合函数 p = polyfit (x,y,n)
,输入参数
x
=
[
x
0
,
x
1
,
.
.
.
x
m
]
;
y
=
[
y
0
,
y
1
,
.
.
.
,
y
m
]
x=[x_0,x_1,...x_m]; y=[y_0,y_1,...,y_m]
x=[x0,x1,...xm];y=[y0,y1,...,ym],返回次数为 n 的多项式 p(x) 的系数,p 中的系数按降幂排列,p 的长度为 n + 1。
Python 代码
以拟合线性或二次曲线为例,由于1-2次曲线,最多只有 a 0 ∗ . . a 2 ∗ , p 0 . . p 2 a_0^*..a_2^*,p_0..p_2 a0∗..a2∗,p0..p2 需要计算,代码量比较小
def linearfit(xl: list, yl: list)->list:
if len(xl) != len(yl) or len(xl) < 2:
return []
# 生成必要数据
A = 0.0
asl = [0, 0]
# 定义p函数
p = [lambda n:1, lambda n: n-A]
# 定义x,y映射函数
def f(i): return yl[xl.index(i)]
# 计算第一项
asl[0] = sum(map(f, xl))/sum(map(p[0], xl))
# 计算第二项
A = sum(map(lambda n: n, xl)) / sum(map(p[0], xl)) #确定p1函数的项
asl[1] = sum(map(lambda n: f(n)*p[1](n), xl)) / sum(map(lambda n:p[1](n)**2, xl))
# 计算返回系数
cof = [asl[0]-A*asl[1],asl[1]]
return cof
def QuadFit(xl: list, yl: list) -> list:
if len(xl) != len(yl) or len(xl) < 3:
return []
# 定义x,y映射函数
def f(i): return yl[xl.index(i)]
# 生成必要数据
A = [0.0, 0.0, 0.0]
B = [0.0, 0.0, 0.0]
asl = [0, 0, 0]
# 定义p函数
p = [lambda n:1, lambda n: n-A[1], lambda n:((n-A[2])*(n-A[1])-B[1])]
# 计算第一项
asl[0] = sum(map(f, xl))/sum(map(p[0], xl))
# 计算第二项
A[1] = sum(map(lambda n: n, xl)) / sum(map(p[0], xl))
asl[1] = sum(map(lambda n: f(n)*p[1](n), xl)) / \
sum(map(lambda n: p[1](n)**2, xl))
# 计算第三项
A[2] = sum(map(lambda n: n*p[1](n)**2, xl)) / \
sum(map(lambda n: p[1](n)**2, xl))
B[1] = sum(map(lambda n: p[1](n)**2, xl)) / \
sum(map(lambda n: p[0](n)**2, xl))
asl[2] = sum(map(lambda n: f(n)*p[2](n), xl)) / \
sum(map(lambda n: p[2](n)**2, xl))
def rst(n): return asl[0] + asl[1] * (n-A[1]) + \
asl[2]*((n-A[2])*(n-A[1])-B[1])
# 计算返回系数
cof = [rst(0), asl[1]-asl[2]*(A[1]+A[2]), asl[2]]
return cof