最近在看Bishop的Pattern Recognition and Machine Learning,里面讲的多项式拟合非常透彻,所以根据该书中的例子再对这个方面进行扩充。
首先我们随机取上的20个点,并加高斯白噪声(至于噪声强度可以自己规定,这里取10),我们用上文提到的方法进行拟合,得到入下图所示的结果。
由图可知,当k=1时,拟合的效果是非常差的,而当k=3时,拟合得到的曲线就比较接近了,而当k=12,19尤其是ke=19时,拟合出来的曲线几乎完全和原始的数据重合了(按理论来说k=19应该拟合的曲线应该完全经过所有点,但这里有三个点例外,具体原因还不清楚,但并不影响分析),那么这样得到的曲线函数是否是最完美的呢?当然不是,恰恰相反,这种情况是我们应该避免的,我们称这种情况为过拟合(over-fitting)。
在实际情况中,我们获得的信号往往是带有噪声的,所以如果我们对得到的数据完全拟合,那么就会引入噪声,这是不能接受的。我们可以从root-mean-square(RMS)error来判断拟合的结果的好坏。
随机取计算得到的曲线100个点,计算其E(RMS)(为了计算方便,tn直接取sin上面的点),得到当k=3时,E(RMS)=0.2844,而当k=12时,E(RMS)=9.9938。更直观的,当k=3时,W=[0.1664,8.4490,-26.5924,17,9262],当k=12时,W=[-269.6461, 13129.8357, -244471.6788 . . .],可以看出当k过大时,其对应的系数会变得非常大,在图像的体现为剧烈波动。因此为了避免这种情况的发生,学者们加入了一个正则项来约束W中值得大小
具体求解也是对w求导,其中lambda决定了这个正则项在公式中的重要程度,具体选择方法可以参见上文提到的PRML,这里就不做仿真实验了。
最后附上代码,代码没有经过仔细的检查,里面的变量也不是很规范,如果里面有何错误,请大家指出来。
clc;
clear;
num=20;
x=rand(1,num);
y=[];
for i=1:size(x,2)
y=[y, sin(2*3.14*x(i))];
end
yn = awgn(y,10,'measured');
I=ones(1,num);
X=[I; x; x.^2; x.^3];
Y=yn;
A=Y/X;
y2=A(1)+A(2)*x+A(3)*x.^2+A(4)*x.^3;
x_test=rand(1,100);
y_test=[];
y_test_ori=[];
for i=1:size(x_test,2)
y_test_ori=[y_test_ori, sin(2*3.14*x_test(i))];
y_test=[y_test, (A(1)+A(2)*x_test(i)+A(3)*x_test(i)^2+A(4)*x_test(i)^3)];
end
% y_test_ori_n = awgn(y_test_ori,10,'measured');
y_test=y_test-y_test_ori;
y_train=y-y2;
E_test=sqrt(sum(y_test.^2)/100);
E_train=sqrt(sum(y_train.^2)/10);
figure;
set(0,'defaultfigurecolor','w')
[a,b]=sort(x);
plot(a,y2(b),'b');
hold on;
scatter(x,yn,'r');
hold on;
x_ori=0:0.01:1;
y1=sin(2*3.14*x_ori);
plot(x_ori,y1,'g');