2014年5月6日星期二

例子使用Matlab编程实现多项式拟合

1.   原题
编程实现对美国人口普查数据的多项式回归,拟合阶数为15阶。要求:将多项式回归问题转换为高斯消去法解线性代数方程组。
2.  线性回归问题的解法步骤
1)        确定拟合函数,包括拟合函数需要的是多变量还是单变量,多项式的阶数,确保参数是线性的;
2)        线性回归问题         最优化问题
3)        最优化问题         解线性代数方程组的问题,该过程需要系数矩阵的确定,转化,高斯消元法。
3.  分析
设多项式回归方程 (其中m=1,2,…5),目的要找到一组(a0 ,a1,…,am),使  最小,我们可以从另外一种方法来表示,将n个样本数据代入回归方程 ,这样我们就得到n组方程,表示为
=
问题转换为矩阵问题,实际情况,样本数量n>>m,即rank(x) rank(xy),所以原方程组不一定存在解,但我们仍然可以求得它的最小二乘解。
通过变换:  X*a=y        *X*a= *y, 利用高斯消去法就可以解得后者的方程。

4.        Using Gaussian elimination
t=(t-1900)/50 格式编程,这个变换不唯一,目的是为了得到更好的曲线拟合函数。

Matlab函数库提供基本的曲线拟合函数命令,以下先看看Matlabpolyfit 函数怎么用,好处在哪?
调用格式: a=polyfit(xdata,ydata,n)
返回an+1个元素的行向量,该向量是以维数递减形式给出拟合多项式的系数。
Sample
a=polyfit(t,y,4);
a =
      -13.966       57.126      -49.892       84.634       76.393
  该函数其实算法的根本还是利用最小二乘法来求得,若遇到xdata比较大的情况,还是需要转换,否则还是会出现警告,优点就是快捷简单。

   高斯消去法编程实现

clc
clear
m=input('Please input the degrees of the fitting function =') ;  %输入阶数
load data.txt                %装载样本数据
n=length(data) ;
Polynomial_Matrix=zeros(n,m+1) ;  %初始化系数矩阵,该矩阵用来存储样本对应的X


t的变换
由于年份数字比较大,况且当m比较大的话,经过m次方计算就变得非常大这样的话,很容易产生非常大的误差,因此一下对年份作一个变换。

t=(data(:,1)-1900)/50 ;
y=data(:,2) ;          %每年的人口数据

To show the Discrete points of each year

figure
plot(data(:,1),y,'or');
xlabel('years');
ylabel('the US population in Millions')
title('The US Population from 1990 to 2000');
以下利用高斯消元法来解线性方程组,原来的系数矩阵为Polynomial_matrix但是其为超 定矩阵,有最小二乘解,要把它转为正定问题来解,原方程为x*a=y 1
xT*x*a=xT*y 2
方程1的解即为方程2的解,以下的程序是解方程xT*x*a=xT*ya
 
    for i=1:n
for j=1:m+1
Polynomial_Matrix(i,j)=t(i).^(j-1);  %Polynomial_matrix也就是x
end
end
X=Polynomial_Matrix'*Polynomial_Matrix; %X=xT*x
Y=Polynomial_Matrix'*y;                 %Y=xT*y
我们求出来的a的顺序是从a0--am的,使用flipud将顺序倒一下,得到就是另外一个向量即为多项式的系数向量,在Matlab里该向量可以表示函数f=a0+a1x+a2x^2+....amx^m

Augmented_Matrix=guassian([X,Y])      %调用事先编好的高斯消去函数
a= flipud(Augmented_Matrix(:,m+2));

To show the fitting curve (4阶为例)

  plot(1890:10:2020,polyval(a,-0.2:0.2:2.4));  %画出回归曲线
plot(2010,polyval(a,2.2),'o','MarkerFaceColor','g')
legend('实际离散点','拟合曲线','估计值');
text(2010,polyval(a,2.2),sprintf('(%4.4f)',polyval(a,2.2)));%在图像中标出预测值
%在此输出2010的预测人数
fprintf('the predict US population in 2010 is  %f Million',polyval(a,2.2));



>>the predict US population in 2010 is  302.233788 Million