多项式最小二乘法拟合

和自甴很熟 提交于 2021-02-10 10:28:11

实用计算方法实验二——多项式最小二乘法拟合

实用计算方法实验二——多项式最小二乘法拟合

采用mlx,即matlab的实时脚本,便于观察结果和发布过程。

  • 二次多项式
  • 三次多项式
  • 指数函数
  • 评价拟合效果
  • 附录:Doolittle函数解矛盾方程组
  • 二次多项式

%二次多项式 最小二乘法 解矛盾方程组 拟合

%形如a0*1+a1*x+a2*x^2的拟合

clear

clc

x=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];

y=[352 211 197 160 142 106 104 60 56 38 36 32 21 19 15];

 

m=size(x,2); %获得数据点个数

%n=input('请输入phi(x)的个数:');

n=3;%n即为phi(x)的个数

syms symsx

f = symfun([1,symsx,symsx^2],symsx);%在这里可以修改phi(x)的表达式的形式与个数,如symsx^2,在建立法方程时的值为x^2,cos(symsx)则建立法方程时为cos(x)

expr = formula(f);

表达式分别为

expr(1)

ans =

expr(2)

ans =

expr(3)

ans =

构建的法方程的A与Y

 

A=zeros(m,n); %构造法方程所需的A和Y

for j=1:n

temp =subs(expr(j),symsx,x);

temp2 = double(temp);

for i=1:m

A(i,j)=temp2(i);

end

end

A

A =
     1     1     1
     1     2     4
     1     3     9
     1     4    16
     1     5    25
     1     6    36
     1     7    49
     1     8    64
     1     9    81
     1    10   100
     1    11   121
     1    12   144
     1    13   169
     1    14   196
     1    15   225

 

Y=zeros(m,1);

for k=1:m

Y(k,1)=y(k);

end

%a=(A'*A)\(A'*Y);%左除注意

%左除即可解出a了,这里使用一下Doolittle分解法

Doolittle分解法解矛盾方程组

a=Doolittle(A'*A,A'*Y)

l =
   1.000000000000000                   0                   0
   8.000000000000000   1.000000000000000                   0
  82.666666666666671  16.000000000000000   1.000000000000000

u =
   1.0e+03 *

   0.015000000000000   0.120000000000000   1.240000000000000
                   0   0.280000000000000   4.480000000000000
                   0                   0   4.125333333333314

a =
   1.0e+02 *

   3.478967032967037  -0.511393826761475   0.019897382029735

 

%误差的平方和

a1=zeros(n,1);

for i=1:n

a1(i,1)=a(i);

end

c=(A*a1-Y);

Q=0;

for i=1:m

Q=Q+c(i)^2;

end

误差的平方和Q为

Q;

Q1=Q

Q1 =
     5.948695345830643e+03

 

fprintf( 'a0: %f \t a1: %f a2: %f\n' , a(1), a(2), a(3)) ;

a0: 347.896703 a1: -51.139383  a2: 1.989738

得到的二次函数关系

fprintf( '%f+(%f)*x+(%f)*x^2 \n' , a(1), a(2), a(3)) ;

347.896703+(-51.139383)*x+(1.989738)*x^2

for k=1:m

yi(k)=a(1)+a(2)*x(k)+a(3)*x(k)^2;

end

绘制散点图

plot(x,y,'o',x,yi,'*');

legend('真值','二次多项式')

hold on;

  • 三次多项式

%三次多项式 最小二乘法 解矛盾方程组 拟合

%形如a0*1+a1*x+a2*x^2+a3*x^3的拟合

x=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];

 

y=[352 211 197 160 142 106 104 60 56 38 36 32 21 19 15];

 

m=size(x,2); %获得数据点个数

n=4;%n即为phi(x)的个数

syms symsx

f = symfun([1,symsx,symsx^2,symsx^3],symsx);%在这里可以修改phi(x)的表达式的形式与个数,如symsx^2,在建立法方程时的值为x^2,cos(symsx)则建立法方程时为cos(x)

expr = formula(f);

表达式分别为

expr(1)

ans =

expr(2)

ans =

expr(3)

ans =

expr(4)

ans =

构建法方程的A与Y

 

A=zeros(m,n); %构造法方程所需的A和Y

for j=1:n

temp =subs(expr(j),symsx,x);

temp2 = double(temp);

for i=1:m

A(i,j)=temp2(i);

end

end

A

A =
           1           1           1           1
           1           2           4           8
           1           3           9          27
           1           4          16          64
           1           5          25         125
           1           6          36         216
           1           7          49         343
           1           8          64         512
           1           9          81         729
           1          10         100        1000
           1          11         121        1331
           1          12         144        1728
           1          13         169        2197
           1          14         196        2744
           1          15         225        3375

 

Y=zeros(m,1);

for k=1:m

Y(k,1)=y(k);

end

Doolittle分解法解矛盾方程

%a=(A'*A)\(A'*Y);

a=Doolittle(A'*A,A'*Y);

l =
   1.0e+02 *

   0.010000000000000                   0                   0                   0
   0.080000000000000   0.010000000000000                   0                   0
   0.826666666666667   0.160000000000000   0.010000000000000                   0
   9.600000000000000   2.254000000000000   0.240000000000001   0.010000000000000

u =
   1.0e+04 *

   0.001500000000000   0.012000000000000   0.124000000000000   1.440000000000000
                   0   0.028000000000000   0.448000000000000   6.311200000000000
                   0                   0   0.412533333333331   9.900800000000000
                   0                   0                   0   5.728319999998808

a

a =
   1.0e+02 *

   3.914095238095376  -0.793302868155895   0.062557009983493  -0.001777484498073

 

%误差的平方和

a1=zeros(n,1);

for i=1:n

a1(i,1)=a(i);

end

c=(A*a1-Y);

Q=0;

for i=1:m

Q=Q+c(i)^2;

end

误差的平方和Q为

Q;

Q2=Q

Q2 =
     4.138860629892981e+03

 

fprintf( 'a0: %f \t a1: %f \t a2: %f \t a3: %f \n' , a(1), a(2), a(3) ,a(4)) ;

a0: 391.409524 a1: -79.330287 a2: 6.255701 a3: -0.177748

得到的三次函数关系

 

fprintf( '%f+(%f)*x+(%f)*x^2+(%f)*x^3 \n' , a(1), a(2), a(3), a(4)) ;

391.409524+(-79.330287)*x+(6.255701)*x^2+(-0.177748)*x^3

for k=1:m

yi2(k)=a(1)+a(2)*x(k)+a(3)*x(k)^2+a(4)*x(k)^3;

end

绘制散点图

plot( x,yi2,'p');

legend('真值','二次多项式','三次多项式')

 

  • 建立拟合效果评价标准

即误差平方和的大小Q,二次函数误差平方和为Q1,三次函数误差平方和为Q2,Q值越小,拟合效果越好

Q1=5948.69534583064

Q2=4138.86062989298

 

Q1

Q1 =
     5.948695345830643e+03

Q2

Q2 =
     4.138860629892981e+03

 

%尝试采用y=a*exp(b*x)形式的函数拟合

x=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];

n=size(x,2);

xsum=sum(x);

xva=xsum/n

xva =
     8

y=[352 211 197 160 142 106 104 60 56 38 36 32 21 19 15];

u=log(y)

u =
   5.863631175598097   5.351858133476067   5.283203728737989   5.075173815233827   4.955827057601261   4.663439094112067   4.644390899141373   4.094344562222100   4.025351690735150   3.637586159726386   3.583518938456110   3.465735902799727   3.044522437723423   2.944438979166440   2.708050201102210

usum=sum(u);

uva=usum/n

uva =
   4.222738185055482

mulxu=xsum*usum

mulxu =
     7.600928733099867e+03

xsum2=xsum^2

xsum2 =
       14400

xu=x.*u;

xusum=sum(xu);

x2=x.*x;

x2sum=sum(x2);

b=(n*xusum-mulxu)/(n*x2sum-xsum2)

b =
  -0.217687176024111

a1=uva-b*xva

a1 =
   5.964235593248374

%scatter(x,u,x,b*x+a1)

a=exp(a1)

a =
     3.892553648884338e+02

得到

x=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];

y=[352 211 197 160 142 106 104 60 56 38 36 32 21 19 15];

m=size(x,2); %获得数据点个数

n=1;

syms symsx

f = symfun([a*exp(b*symsx),],symsx);%在这里可以修改phi(x)的表达式,如symsx^2,在建立法方程时的值为x^2,cos(symsx)则建立法方程时为cos(x)

expr = formula(f);

A=zeros(m,n); %构造法方程所需的A和Y

for j=1:n

temp =subs(expr(j),symsx,x);

temp2 = double(temp);

for i=1:m

A(i,j)=temp2(i);

end

end

Y=zeros(m,1);

for k=1:m

Y(k,1)=y(k);

end

%a=(A'*A)\(A'*Y);%左除注意

%左除即可解出a了,这里使用一下Doolittle分解法

d=Doolittle(A'*A,A'*Y);

l =
     1

u =
     2.773369199466112e+05

%误差的平方和

d1=zeros(n,1);

for i=1:n

d1(i,1)=d(i);

end

c=(A*d1-Y);

Q=0;

for i=1:m

Q=Q+c(i)^2;

end

Q3=Q

Q3 =
     3.806082127183518e+03

plot(a*exp(b*x),'+');

legend('真值','二次多项式','三次多项式','指数函数')

Q3=3806.08212718352

即误差平方和的大小Q,Q值越小,拟合效果越好

Q1=5948.69534583064

Q2=4138.86062989298

则由Q1>Q2>Q3

得到使用指数函数拟合效果是最好的。

  • 附录:Doolittle函数

function[x,y,l,u] = Doolittle(A,d)

脚本中的所有函数都必须以 'end' 结束。
 

n=size(A,1);%获得矩阵A的行数

n1=size(A,2);

m=size(d,1);

for i=1:m

b(i)=d(i,1);

end

%这里b是一个数组

u=zeros(n);%生成n*n的全零矩阵

a=zeros(n);

for i=1:n

for j=1:n1

a(i,j)=A(i,j);

end

end

l=zeros(n);

for i=1:n

l(i,i)=1;

end

for k=1:n

for j=k:n

sum1=0;

for r=1:k-1

sum1=sum1+l(k,r)*u(r,j);

end

u(k,j)=a(k,j)-sum1;

end

for i=k+1:n

sum2=0;

for r=1:k-1

sum2=sum2+l(i,r)*u(r,k);

end

l(i,k)=(a(i,k)-sum2)/u(k,k);

end

end

l

u

for i=1:n

sum3=0;

for j=1:(i-1)

sum3=sum3+l(i,j)*y(j);

end

y(i)=b(i)-sum3;

end

for i=n:-1:1%注意matlab循环变量的步进是要注明正负的

sum4=0;

for j=(i+1):n

sum4=sum4+u(i,j)*x(j);

end

x(i)=(y(i)-sum4)/u(i,i);

end

end

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!