PRML系列:1.1 多项式函数拟合

前言

此系列关于Pattern Recognition and Machine Learning的总结,博文记录一些在阅读过程中遇到的难点和自己的感悟。话不多说,直接进入正题吧。

正文

第一章第一节的内容关于多项式函数的拟合,假设我们给出了一系列的坐标点(x,y)们,可能是某个函数生成的,比如:y=sin(2πx)y = \sin(2 \pi x),如下图:

模式识别的目标是,根据给定的坐标点,去预测背后可能的假设(函数),即由蓝色点去预测绿色曲线 y=sin(2πx)y = \sin(2 \pi x)。后续的主题都围绕这个最基本的目标,但如何去预测呢?一个办法是通过假设一个函数f(x,w)f(x, w),其中ww是该函数的参数,然后让它去拟合图中每个蓝色点。

泰勒展开式告诉我们,任何函数都可以由任意M个多项式产生,所以可以用多项式和来进行拟合,于是有:

只要根据给定的点的集合(x, y)求出所有的ww即可。于是我们定义误差函数,直观上可以理解为,当前参数w∗w^*对数据的拟合程度,拟合程度越高(误差越小),那么它就有可能越接近真实的函数y=sin(2πx)y = \sin(2 \pi x).

误差函数如下:

tnt_n表示第n个样例的真实值,而f(xn,w)f(x_n, w)表示第n个样例的预测值。最小二乘法损失函数连续可微,在求导上有很好的性质,为了求得每个参数wiw_i,我们可以对其求导

求偏导的好处在于:对于每个参数wiw_i而言,偏导为0,代表损失函数取得极值。在E(w)E(w)中,我们显然需要极小值,即损失越小,拟合程度越高。

于是对于M个参数,可以求得M个偏导,M个方程,自然能够求得一个解析解,我也很好奇为啥是解析解,自己推导了一波,发现对于第i个参数wiw_i,都有形如:

\lambda_{1i} w_1 + \lambda_{2i} w_2 + \cdots + \lambda_{Mi} w_m = c_i

所以书中的一维多项式能够通过求偏导的方式得到全局唯一的最优解。

那是否意味着M越大越好?直观上来看,泰勒展开式如果M的值越大,那么对真实函数的近似能力越强,但在数据推得假设f(x)f(x)时,并不是如此。如书中所示:

需要指出的是,在这些由

函数生成的点中,还有个别点是噪声,所谓噪声可以理解为随机夹杂在数据集中的搅屎棍。它们的出现或多或少将影响分类器的学习性能。

从图中可以看出:M较小时,如M = 0,1时,函数的拟合程度很弱,当M = 9时,也出现了拟合程度较弱(why?)。这是很有趣的现象,机器学习界叫这现象为过拟合。我给个定义吧:由于函数的表达能力太强(模型复杂),它的表达能力远超真实数据所表现的这种“结构”,甚至把噪声的特性都学进来,从而离真实函数相差甚远。

产生的原因? 我很难从数学的角度去解释为什么M大,就会产生过拟合现象。但从直观上来看,可以这么理解,M的个数就好比一条长度为M的绳子,M越大,绳子越长(代表的是模型描述点的能力)。在一定的长度内,比如M = 3,为了让绳子尽可能符合大多数样本的规律,只能舍弃某些跳脱的很厉害的点(大多数这样的点为噪声)。而当M = 9时,因为绳子对于数据集而言太长了,它有这样的能力使得模型去符合每个点,自然就把噪声点给考虑进来了。

所以书中给出了一个很重要的结论:

We see that, for a given model complexity, the over-fitting problem become less severe as the size of the data set increases.

如果所给的数据集越庞大(噪声比例降低!),同样的M = 9时,则不会出现过拟合现象。如下图所示:

所以本节提出了三种解决方案: 1. 增大数据集的量 2. 采用交叉验证的方法(机器学习中常用来避免过拟合) 3. 采用正则化方法来约束参数

第一种在前面已经提过了,就不再赘述了。交叉验证的思想是把所给数据集分成训练集和测试集,在训练集训练的模型,拿到测试集去测量误差,两者的误差都很小时,则认为假设模型离真实函数越接近。

测试误差函数为RMS: ERMS=2√E(w∗)/NE_{RMS} = \sqrt 2 E(w^*) / N

其中N表示数据集中样例的个数,目的是为了归一化,因为训练集和测试集的个数常常不等,且E(w∗)E(w*) 没做归一化处理,所以在ERMSE_{RMS}中做掉。其余的系数2和开根号是为了得到真实的“线性”的误差,貌似没啥特别作用,不加也可以。测试结果如下图所示:

可以看到M = 9在测试集上表现相当糟糕,在M 在3到8表现都不错,根据奥卡姆剃刀原则,可以选择简单模型M = 3作为最终的模型。

那么为什么采用交叉验证能够有效的解决模型过拟合问题呢?我的思考,仅供参考。

因为噪声的产生,越复杂的模型的学习能力越强,所以函数出现过拟合现象是因为学得了每个点的特性(包括噪声),在图中反映的就是该函数忽上忽下,所以测试集中稍微有一些偏移就能导致极大的偏差。从训练的w∗w^*也可以观察得到:

M = 9时,大多数的wiw_i都特别大,所以xx的稍微扰动都可能产生一个极大极小的值。

这也就产生了第三种解决方案,利用正则化。说白了,正则化是给定M来约束参数ww的学习,即让ww尽量不要出现特别大的值,如上表所示。所以有了新的损失函数定义:

其中

,让损失函数和每个wiw_i相关。对M = 9, 但不同的λ\lambda能够得到如下图所示的结果:

对应的w∗w^*也有了变化:

不过值得思考的并不是这些表面结果,而是为什么让w∗w^*尽可能小,能够有更好的拟合效果?

我的猜测是大多数真实数据都会产生或多或少的左右偏移和上下偏移,以及跟采集器的周遭环境相关,有少量噪声产生。正如前文所说,由于上下偏移,越复杂的模型在小数据集中表达的更精准,那么求局部导数来看,它们更有可能产生一个冲击(无穷大的导数值),而无穷大是由所有w∗w*来表示的,那么自然w∗w^*中都可能存在非常大或者非常小的值。所以w∗w^*越大,假设函数的振幅越明显,所以才会选择更小的w∗w^*来让假设函数更平滑(而非突变)。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏学海无涯

Android开发之奇怪的Fragment

说起Android中的Fragment,在使用的时候稍加注意,就会发现存在以下两种: v4包中的兼容Fragment,android.support.v4.ap...

3215
来自专栏java闲聊

JDK1.8 ArrayList 源码解析

当运行 ArrayList<Integer> list = new ArrayList<>() ; ,因为它没有指定初始容量,所以它调用的是它的无参构造

1232
来自专栏刘君君

JDK8的HashMap源码学习笔记

3288
来自专栏alexqdjay

HashMap 多线程下死循环分析及JDK8修复

1.1K4
来自专栏Hongten

ArrayList VS Vector(ArrayList和Vector的区别)_面试的时候经常出现

2202
来自专栏xingoo, 一个梦想做发明家的程序员

AOE关键路径

这个算法来求关键路径,其实就是利用拓扑排序,首先求出,每个节点最晚开始时间,再倒退求每个最早开始的时间。 从而算出活动最早开始的时间和最晚开始的时间,如果这两个...

2637
来自专栏聊聊技术

原 初学图论-Kahn拓扑排序算法(Kah

2988
来自专栏赵俊的Java专栏

从源码上分析 ArrayList

1211
来自专栏后端之路

LinkedList源码解读

List中除了ArrayList我们最常用的就是LinkedList了。 LInkedList与ArrayList的最大区别在于元素的插入效率和随机访问效率 ...

21010
来自专栏拭心的安卓进阶之路

Java 集合深入理解(12):古老的 Vector

今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这么相...

2537

扫码关注云+社区