怎么解决过拟合与欠拟合?

一、过拟合

在训练数据不够多时,或者over-training时,经常会导致over-fitting(过拟合)。其直观的表现如下图所所示。


随着训练过程的进行,模型复杂度,在training data上的error渐渐减小。可是在验证集上的error却反而渐渐增大——由于训练出来的网络过拟合了训练集,对训练集以外的数据却不work。

在机器学习算法中,我们经常将原始数据集分为三部分:训练集(training data)、验证集(validation data)、测试集(testing data)。

1. validation data是什么?

它事实上就是用来避免过拟合的。在训练过程中,我们通经常使用它来确定一些超參数(比方,依据validation data上的accuracy来确定early stopping的epoch大小、依据validation data确定learning rate等等)。那为啥不直接在testing data上做这些呢?由于假设在testing data做这些,那么随着训练的进行,我们的网络实际上就是在一点一点地overfitting我们的testing data,导致最后得到的testing accuracy没有什么參考意义。因此,training data的作用是计算梯度更新权重,testing data则给出一个accuracy以推断网络的好坏。

2. 防止过拟合方法主要有:

① 正则化(Regularization)(L1和L2)
② 数据增强(Data augmentation),也就是增加训练数据样本
③ Dropout
④ early stopping

二、正则化

正则化(Regularization)包含L1、L2(L2 regularization也叫权重衰减,weight decay)

1. L1 regularization

在原始的代价函数后面加上一个L1正则化项,即全部权重w的绝对值的和,再乘以λ/n(这里不像L2正则化项那样,须要再乘以1/2)。


先计算导数:


上式中sgn(w)表示 w 的符号,那么权重w的更新规则为:


比原始的更新规则多出了这一项。

当w为正时,sgn(w)> 0, 则更新后的w变小。

当w为负时,sgn(w)> 0, 则更新后的w变大——因此它的效果就是让w往0靠,使网络中的权重尽可能为0,也就相当于减小了网络复杂度,防止过拟合。

另外,上面没有提到一个问题,当w为0时怎么办?当w等于0时,|W|是不可导的。所以我们仅仅能依照原始的未经正则化的方法去更新w,这就相当于去掉 η*λ*sgn(w)/n 这一项,所以我们能够规定sgn(0)=0,这样就把 w=0 的情况也统一进来了。

(在编程的时候,令sgn(0)=0,sgn(w> 0)=1,sgn(w<0)=-1)

2. L2 regularization(权重衰减)

L2正则化就是在代价函数后面再加上一个正则化项:


C0代表原始的代价函数,后面那一项就是L2正则化项。它是这样来的:全部參数 w 的平方和,除以训练集的样本大小n。

λ 就是正则项系数,权衡正则项与C0项的比重。另外另一个系数1/2,1/2经常会看到,主要是为了后面求导的结果方便,后面那一项求导会产生一个2,与1/2相乘刚好凑整。L2正则化项是怎么避免overfitting的呢?我们推导一下看看,先求导:


能够发现L2正则化项对 b 的更新没有影响,可是对于w的更新有影响:


在不使用L2正则化时。求导结果中 w 前系数为 1,经变化后w前面系数为 1−ηλ/n ,由于η、λ、n都是正的。所以 1−ηλ/n小于1,它的效果是减小w,这也就是权重衰减(weight decay)的由来。

当然考虑到后面的导数项,w 终于的值可能增大也可能减小。

另外,必须提一下,对于基于mini-batch的随机梯度下降,w 和 b 更新的公式跟上面给出的有点不同:


对照上面 w 的更新公式。能够发现后面那一项变了,变成全部导数加和,乘以η再除以m,m是一个mini-batch中样本的个数。

在此我们仅仅是解释了L2正则化项有让w“变小”的效果,可是还没解释为什么w“变小”能够防overfitting?

一个所谓“显而易见”的解释就是:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合刚刚好(这个法则也叫做奥卡姆剃刀),而在实际应用中,也验证了这一点,L2正则化的效果往往好于未经正则化的效果。当然,对于非常多人(包含我)来说,这个解释似乎不那么显而易见,所以这里加入一个略微数学一点的解释(引自知乎):

过拟合的时候,拟合函数的系数往往非常大,为什么?例如以下图所看到的,过拟合。就是拟合函数须要顾忌每个点。终于形成的拟合函数波动非常大。在某些非常小的区间里,函数值的变化非常剧烈。

这就意味着函数在某些小区间里的导数值(绝对值)非常大,由于自变量值可大可小,所以仅仅有系数足够大,才干保证导数值非常大。而L2正则化是通过约束參数的范数使其不要太大,所以能够在一定程度上降低过拟合情况。


3. 在什么情况下使用L1,什么情况下使用L2?

L1和L2的差别,为什么一个让绝对值最小,一个让平方最小,会有那么大的差别呢?我看到的有两种几何上直观的解析:

(1)下降速度:

我们知道,L1和L2都是规则化的方式,我们将权值参数以L1或者L2的方式放到代价函数里面去。然后模型就会尝试去最小化这些权值参数。而这个最小化就像一个下坡的过程,L1和L2的差别就在于这个“坡”不同,如下图:L1就是按绝对值函数的“坡”下降的,而L2是按二次函数的“坡”下降。所以实际上在0附近,L1的下降速度比L2的下降速度要快,所以会非常快得降到0。不过我觉得这里解释的不太中肯,当然了也不知道是不是自己理解的问题。


L1称Lasso,L2称Ridge。

总结就是:L1会趋向于产生少量的特征,而其他的特征都是0,而L2会选择更多的特征,这些特征都会接近于0。Lasso在特征选择时候非常有用,而Ridge就只是一种规则化而已。

三. 数据集扩增(data augmentation)

训练模型有时候不是由于算法好赢了,而是由于拥有海量的数据才赢了。”

不记得原话是哪位大牛说的了,hinton?从中可见训练数据有多么重要,特别是在深度学习方法中,海量的训练数据,意味着能够用更深的网络,训练出更好的模型。

既然这样,收集大量数据不就OK啦?假设能够收集很多其它能够用的数据,当然好。可是非常多时候,收集很多其它的数据意味着须要耗费很多其它的人力物力。尤其在对数据集进行人工标注的同学就知道,效率特别低,简直是粗活。

所以。能够在原始数据上做些改动,得到很多其它的数据,以图片数据集举例,能够做各种变换,如:

  • 将原始图片旋转一个小角度
  • 加入随机噪声
  • 一些有弹性的畸变(elastic distortions),论文《Best practices for convolutional neural networks applied to visual document analysis》对MNIST做了各种变种扩增。
  • 截取(crop)原始图片的一部分,比方DeepID中,从一副人脸图中,截取出了100个小patch作为训练数据,极大地添加了数据集。

感兴趣的能够看《Deep learning face representation from predicting 10,000 classes》.

大量训练数据意味着什么?

用50000个MNIST的样本训练SVM得出的accuracy94.48%,用5000个MNIST的样本训练KNN得出accuracy为93.24%,所以很多其它的数据能够使算法表现得更好。

在机器学习中,算法本身并不能决出胜负,不能武断地说这些算法谁优谁劣,由于数据对算法性能的影响非常大。

四、Dropout

L1、L2正则化是通过改动代价函数来实现的,而Dropout则是通过改动神经网络本身来实现的,它是在训练网络时用的一种技巧(trike),它的流程例如以下:


假设我们要训练上图这个网络,在训练开始时,我们随机地“删除”一部分的隐层单元,视它们为不存在,得到例如以下的网络:


保持输入输出层不变,依照BP算法更新上图神经网络中的权值(虚线连接的单元不更新,由于它们被“暂时删除”了)。

以上就是一次迭代的过程,在第二次迭代中,也用相同的方法,仅仅只是这次删除的那一部分隐层单元,跟上一次删除掉的肯定是不一样的。由于我们每一次迭代都是“随机”地去删掉一部分。

第三次、第四次……都是这样,直至训练结束。

以上就是Dropout,它为什么有助于防止过拟合呢?能够简单地这样解释,运用了dropout的训练过程,相当于训练了非常多个仅仅有部分隐层单元的神经网络,每个这种半数网络,都能够给出一个分类结果,这些结果有的是正确的,有的是错误的。

随着训练的进行,大部分半数网络都能够给出正确的分类结果。那么少数的错误分类结果就不会对终于结果造成大的影响。

删除神经单元,不工作,通常keep_prob取0.5

在编程时可以利用TensorFlow中 DropoutWrappera函数

在训练过程引入Dropout 策略,其Dropout层保留节点比例(keep_prob),每批数据输入时神经网络中的每个单元会以1-keep_prob的概率不工作,防止过拟合。

lstmCell = tf.contrib.rnn.DropoutWrapper(cell=lstmCell, output_keep_prob=0.5)
更加深入地理解。能够看看Hinton和Alex两牛2012的论文《ImageNet Classification with Deep Convolutional Neural Networks》

五、提前终止(Early stopping)

对模型进行训练的过程即是对模型的参数进行学习更新的过程,这个参数学习的过程往往会用到一些迭代方法,如梯度下降(Gradient descent)学习算法。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……

六、从数据预处理角度

1. 对原始数据通过PCA, t-SNE等降维技术进行降维处理

2. 平衡不同类数据的权重等

参考:

1.《Neural networks and deep learning》概览 中第三章的一部分
http://blog.csdn.net/u012162613/article/details/44220115

版权声明:本文为CSDN博主「Charles_yy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010899985/article/details/79471909

推荐阅读