原文:http://blog.csdn.net/vivihe0/article/details/33317041
在说到模型过拟合问题的时候,我们经常听说到模型的方差和偏差,本系列就通过多项式拟合为例来说明什么是模型的方差和偏差,进而说明模型复杂度与模型预测效果之间的关系。
我们通过计算机产生样本数据点来进行多项式拟合。为了能在2维平面上方便显示拟合的函数,我们的输入向量和输出向量都是1维的。我们产生数据的函数是:
y = sin(2*pi*x)
根据这个函数,我们以(0,0.1,....,0.9,1)这11个点作为输入样本x,产生y值,然后再将一个均值为0,标准差为0.3的正态分布 噪声项叠加在y上,产生了目标输出样本t。我们用这11个样本点来拟合4种不同阶数的多项式,将其对应的曲线再分别与真实的函数关系y = sin(2*pi*x)的曲线做对比。这样可以看出我们拟合的曲线有没有提取出11个样本点背后隐含的函数关系。
注意,如果是在实际应用中,我们并不知道产生数据的真实函数关系。在那种情况下,我们的目标是在不知道真实函数关系的情况下,仅仅通过10个样本点,拟合一条曲线,然后对未知的x值预测其t值。而在本文中,我们是知道产生数据的真实函数关系的。
下面是相应的MATLAB代码,在这里我们直接使用MATLAB的多项式拟合函数polyfit和polyval。polyfit函数可以计算指定阶数多项式拟合的系数,polyfit函数根据系数来计算给定输入变量的输出值。其具体的使用细节见下面的代码。
- %产生10个数据点用于多项式拟合
- xTrain = 0:0.1:1;
- tTrain = sin(2*pi*xTrain) + normrnd(0, 0.3, 1, 11);
- %拟合4种不同阶数的多项式
- poly = cell(1, 4);
- p = [1, 2, 3, 10];
- for i = 1 : 4
- poly{i} = polyfit(xTrain, tTrain, p(i));
- end
- % 设置绘制曲线的采样点
- xGrid = 0: 0.01: 1;
- %新建图形
- figure
- % 多项式拟合
- for i = 1 : 4
- subplot(2,2,i);
- plot(xGrid, sin(2*pi*xGrid), 'b');
- hold on
- plot(xTrain, tTrain, 'o');
- plot(xGrid, polyval(poly{i}, xGrid), 'r');
- set(gca, 'YLim', [-2, 2]);
- title(sprintf('阶数: %d ', p(i)), 'fontsize', 20);
- end
注意,图中的蓝线是产生数据点真实的函数关系,圈是数据点,而红线是拟合的多项式曲线。
从图中可以看出,阶数为1和2时,拟合的效果不好,拟合的曲线与正弦曲线y = sin(2*pi*x)差距甚远。在阶数为3的时候,拟合的效果较好。当我们把阶数增加到9的时候,多项式对10个数据点有着完美的拟合,实际上拟合曲线 准确地穿过了10个样本点,但是拟合曲线与y = sin(2*pi*x)却差距很大。
我们把前2个子图的情况叫做欠拟合,在这种情况下,由于模型的阶数较低,用于拟合的模型不够灵活,所以没有有效提取出数据包含的信息。最后一个子图 的情况叫做过拟合,在这种情况下,模型过分灵活,以至于能够适应数据的任何随机的波动,这样拟合的曲线就把数据包含的噪声也作为了有价值的信息而加以利用 了。所以说这两种情况都是需要避免的,我们需要的是在这两种情况之间做一个折中,也就是拟合的模型既不能太复杂也不能太简单。
当然你会说,在实际应用的情况下,我们不知道数据是由什么函数产生的(也就是我们无法画出图中的蓝线),那么如何判断有没有过拟合呢?且听下回。
好了,本文的结论:过犹不及。