Fork me on GitHub

深度学习中防止过拟合的方法

“什么是过拟合?以及如何预防过拟合?”

上述是机器学习常见面试题之一,本文将对其稍作解答,仅供参考。

0. 什么是过拟合

过拟合即在训练误差很小,而泛化误差很大,因为模型可能过于的复杂,使其”记住”了训练样本,然而其泛化误差却很大。

在传统的机器学习方法中有很大防止过拟合的方法,同样这些方法很多也适合用于深度学习中,同时深度学习中又有一些独特的防止过拟合的方法,下面对其进行简单的梳理。

1. 获取更多数据

让模型泛化的能力更好的最好办法就是使用更多的训练数据进行训练,但是在实践中,我们拥有的数据是有限的,解决这一问题可以人为的创造一些假数据添加到训练集中。

一个具体的例子:
在AlexNet中,将$256\times 256$图像随机的截取$224\times 224$大小,增加了许多的训练样本,同时可以对图像进行左右翻转,增加样本的个数,实验的结果可以可降低1%的误差。

在神经网络中输入噪声也可以看做是数据增强的一种方式。

通俗得讲,数据集扩增即需要得到更多的符合要求的数据,即和已有的数据是独立同分布的,或者近似独立同分布的。一般有以下方法:

  • 从数据源头采集更多数据
  • 复制原有数据并加上随机噪声
  • 重采样
  • 根据当前数据集估计数据分布参数,使用该分布产生更多数据等

2.选用合适的模型

2.1 网络结构 Architecture

这个很好理解,减少网络的层数、神经元个数等均可以限制网络的拟合能力。

2.2 参数范数惩罚 regularization

范数正则化是一种非常普遍的方法,也是最常用的方法,假如优化:

$$minObj(\theta)=L(y,f(x))+\alpha G(\theta)$$

其中L为经验风险,其为在训练样本上的误差,而G为对参数的惩罚,也叫结构风险。α是平衡两者,如果太大则对应的惩罚越大,如过太小,甚至接近与0,则没有惩罚。

最常用的范数惩罚为L1,L2正则化。

L1正则

L1又被成为Lasso:
$$||w||1=|w1|+|w2|+…$$

即绝对值相加,其趋向于是一些参数为0。可以起到特征选择的作用。

L2正则

L2正则化为:

$$||w||_2=w12+w22+…$$

L2范数是指向量各元素的平方和然后求平方根。它有两个美称,在回归里面,有人把有它的回归叫“岭回归”(Ridge Regression),有人也叫它“权值衰减weight decay”。它的强大功效是改善机器学习里面一个非常重要的问题:过拟合。

其趋向与,使权重很小。其又成为ridge。

拟合过程中通常都倾向于让权值尽可能小,最后构造一个所有参数都比较小的模型。因为一般认为参数值小的模型比较简单,能适应不同的数据集,也在一定程度上避免了过拟合现象。可以设想一下对于一个线性回归方程,若参数很大,那么只要数据偏移一点点,就会对结果造成很大的影响;但如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是『抗扰动能力强』。

这里也一句话总结下:通过L2范数,我们可以实现了对模型空间的限制,从而在一定程度上避免了过拟合。

关于更多正则化的内容可以参考《deep learning》第七章:深度学习中的正则化。

2.3 训练时间 Early stopping

当随着模型的能力提升,训练集的误差会先减小再增大,这样可以提前终止算法减缓过拟合现象。

Early stopping方法的具体做法是,在每一个Epoch结束时(一个Epoch集为对所有的训练数据的一轮遍历)计算validation data的accuracy,当accuracy不再提高时,就停止训练。这种做法很符合直观感受,因为accurary都不再提高了,在继续训练也是无益的,只会提高训练的时间。那么该做法的一个重点便是怎样才认为validation accurary不再提高了呢?并不是说validation accuracy一降下来便认为不再提高了,因为可能经过这个Epoch后,accuracy降低了,但是随后的Epoch又让accuracy又上去了,所以不能根据一两次的连续降低就判断不再提高。一般的做法是,在训练的过程中,记录到目前为止最好的validation accuracy,当连续10次Epoch(或者更多次)没达到最佳accuracy时,则可以认为accuracy不再提高了。此时便可以停止迭代了(Early Stopping)。这种策略也称为“No-improvement-in-n”,n即Epoch的次数,可以根据实际情况取,如10、20、30……

提前终止是一种很常用的缓解过拟合的方法,如在决策树的先剪枝的算法,提前终止算法,使得树的深度降低,防止其过拟合。

添加噪声

给网络加噪声也有很多方法:

在输入中加噪声

在权值上加噪声

对网络的响应加噪声

3. 结合多种模型

集成学习是一种比较奇特的方法,如果我们训练多个不同的模型,然后将它们的输出汇总,例如平均起来或者投票汇总,那么汇总的结果可以在一定程度上自动克服过拟合,哪怕每个模型都过拟合了。

3.1 bagging boosting

BaggingBootstrap Aggregating 的简称。简单理解:就是分段函数的概念:用不同的模型拟合不同部分的训练集。

其实bagging的方法是可以起到正则化的作用,因为正则化就是要减少泛化误差,而bagging的方法可以组合多个模型起到减少泛化误差的作用。
在深度学习中同样可以使用此方法,但是其会增加计算和存储的成本

由于训练网络本身就要耗费较多资源,所以一般不单独使用神经网络做bagging

类似的还有boosting

bagging中的模型是强模型,偏差低,方差高。目标是降低方差。在bagging中,每个模型的bias和variance近似相同,但是互相相关性不太高,因此一般不能降低Bias,而一定程度上能降低variance。典型的bagging是random forest。

boosting中每个模型是弱模型,偏差高,方差低。目标是通过平均降低偏差。boosting的基本思想就是用贪心法最小化损失函数,显然能降低偏差,但是通常模型的相关性很强,因此不能显著降低variance。典型的Boosting是adaboost,另外一个常用的并行Boosting算法是GBDT(gradient boosting decision tree)。这一类算法通常不容易出现过拟合。

3.2 Dropout

正则是通过在代价函数后面加上正则项来防止模型过拟合的。而在神经网络中,有一种方法是通过修改神经网络本身结构来实现的,其名为Dropout。该方法是在对网络进行训练时用一种技巧(trick),对于如下所示的三层人工神经网络:

对于上图所示的网络,在训练开始时,随机得删除一些(可以设定为一半,也可以为1/3,1/4等)隐藏层神经元,即认为这些神经元不存在,同时保持输入层与输出层神经元的个数不变,这样便得到如下的ANN:

然后按照BP学习算法对ANN中的参数进行学习更新(虚线连接的单元不更新,因为认为这些神经元被临时删除了)。这样一次迭代更新便完成了。下一次迭代中,同样随机删除一些神经元,与上次不一样,做随机选择。这样一直进行下去,直至训练结束。

Dropout提供了一种廉价的Bagging集成近似,能够训练和评估指数级数量的神经网络。dropout可以随机的让一部分神经元失活,这样仿佛是bagging的采样过程,因此可以看做是bagging的廉价的实现。
但是它们训练不太一样,因为bagging,所有的模型都是独立的,而dropout下所有模型的参数是共享的。

通常可以这样理解dropout:假设我们要判别一只猫,有一个神经元说看到有毛就是猫,但是如果我让这个神经元失活,它还能判断出来是猫的话,这样就比较具有泛化的能力,减轻了过拟合的风险。

4. Batch Normalization

在Google Inception V2中所采用,是一种非常有用的正则化方法,可以让大型的卷积网络训练速度加快很多倍,同事收敛后分类的准确率也可以大幅度的提高。
BN在训练某层时,会对每一个mini-batch数据进行标准化(normalization)处理,使输出规范到N(0,1)的正太分布,减少了Internal convariate shift(内部神经元分布的改变),传统的深度神经网络在训练是,每一层的输入的分布都在改变,因此训练困难,只能选择用一个很小的学习速率,但是每一层用了BN后,可以有效的解决这个问题,学习速率可以增大很多倍。

5. 参数绑定与参数共享

在卷积神经网络CNN中(计算机视觉与卷积神经网络 ),卷积层就是其中权值共享的方式,一个卷积核通过在图像上滑动从而实现共享参数,大幅度减少参数的个数,用卷积的形式是合理的,因为对于一副猫的图片来说,右移一个像素同样还是猫,其具有局部的特征。这是一种很好的缓解过拟合现象的方法。

同样在RNN中用到的参数共享,在其整条时间链上可以进行参数的共享,这样才使得其能够被训练。

6. 辅助分类节点(auxiliary classifiers)

在Google Inception V1中,采用了辅助分类节点的策略,即将中间某一层的输出用作分类,并按一个较小的权重加到最终的分类结果中,这样相当于做了模型的融合,同时给网络增加了反向传播的梯度信号,提供了额外的正则化的思想。

参考资料

------ 本文结束感谢您的阅读 ------
坚持原创技术分享,您的支持将鼓励我继续创作!