机器学习中防止过拟合的处理方法

原文地址:一只鸟的天空,http://blog.csdn.net/heyongluoyao8/article/details/49429629

防止过拟合的处理方法
过拟合
  我们都知道,在进行数据挖掘或者机器学习模型建立的时候,因为在统计学习中,假设数据满足独立同分布(i.i.d,independently and identically distributed),即当前已产生的数据可以对未来的数据进行推测与模拟,因此都是使用历史数据建立模型,即使用已经产生的数据去训练,然后使用该模型去拟合未来的数据。但是一般独立同分布的假设往往不成立,即数据的分布可能会发生变化(distribution drift),并且可能当前的数据量过少,不足以对整个数据集进行分布估计,因此往往需要防止模型过拟合,提高模型泛化能力。而为了达到该目的的最常见方法便是:正则化,即在对模型的目标函数(objective function)或代价函数(cost function)加上正则项。 
  在对模型进行训练时,有可能遇到训练数据不够,即训练数据无法对整个数据的分布进行估计的时候,或者在对模型进行过度训练(overtraining)时,常常会导致模型的过拟合(overfitting)。如下图所示: 
 
  通过上图可以看出,随着模型训练的进行,模型的复杂度会增加,此时模型在训练数据集上的训练误差会逐渐减小,但是在模型的复杂度达到一定程度时,模型在验证集上的误差反而随着模型的复杂度增加而增大。此时便发生了过拟合,即模型的复杂度升高,但是该模型在除训练集之外的数据集上却不work。 
  为了防止过拟合,我们需要用到一些方法,如:early stopping、数据集扩增(Data augmentation)、正则化(Regularization)、Dropout等。

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……

数据集扩增
  在数据挖掘领域流行着这样的一句话,“有时候往往拥有更多的数据胜过一个好的模型”。因为我们在使用训练数据训练模型,通过这个模型对将来的数据进行拟合,而在这之间又一个假设便是,训练数据与将来的数据是独立同分布的。即使用当前的训练数据来对将来的数据进行估计与模拟,而更多的数据往往估计与模拟地更准确。因此,更多的数据有时候更优秀。但是往往条件有限,如人力物力财力的不足,而不能收集到更多的数据,如在进行分类的任务中,需要对数据进行打标,并且很多情况下都是人工得进行打标,因此一旦需要打标的数据量过多,就会导致效率低下以及可能出错的情况。所以,往往在这时候,需要采取一些计算的方式与策略在已有的数据集上进行手脚,以得到更多的数据。 
  通俗得讲,数据机扩增即需要得到更多的符合要求的数据,即和已有的数据是独立同分布的,或者近似独立同分布的。一般有以下方法:

从数据源头采集更多数据
复制原有数据并加上随机噪声
重采样
根据当前数据集估计数据分布参数,使用该分布产生更多数据等
正则化方法
  正则化方法是指在进行目标函数或代价函数优化时,在目标函数或代价函数后面加上一个正则项,一般有L1正则与L2正则等。

L1正则 
  L1正则是基于L1范数,即在目标函数后面加上参数的L1范数和项,即参数绝对值和与参数的积项,即: 

其中C0C0代表原始的代价函数,nn是样本的个数,λλ就是正则项系数,权衡正则项与C0C0项的比重。后面那一项即为L1正则项。 
  在计算梯度时,ww的梯度变为: 

其中,sgnsgn是符号函数,那么便使用下式对参数进行更新:

 

对于有些模型,如线性回归中(L1正则线性回归即为Lasso回归),常数项bb的更新方程不包括正则项,即: 

其中,梯度下降算法中,α<0,β<0α<0,β<0,而在梯度上升算法中则相反。 
  从上式可以看出,当ww为正时,更新后ww会变小;当ww为负时,更新后ww会变大;因此L1正则项是为了使得那些原先处于零(即|w|≈0|w|≈0)附近的参数ww往零移动,使得部分参数为零,从而降低模型的复杂度(模型的复杂度由参数决定),从而防止过拟合,提高模型的泛化能力。 
  其中,L1正则中有个问题,便是L1范数在0处不可导,即|w||w|在0处不可导,因此在ww为0时,使用原来的未经正则化的更新方程来对ww进行更新,即令sgn(0)=0sgn(0)=0,这样即: 

L2正则 
  L2正则是基于L2范数,即在目标函数后面加上参数的L2范数和项,即参数的平方和与参数的积项,即: 

其中C0C0代表原始的代价函数,nn是样本的个数,与L1正则化项前面的参数不同的是,L2项的参数乘了1212,是为了便于计算以及公式的美感性,因为平方项求导有个2,λλ就是正则项系数,权衡正则项与C0C0项的比重。后面那一项即为L2正则项。 
  L2正则化中则使用下式对模型参数进行更新: 

对于有些模型,如线性回归中(L2正则线性回归即为Ridge回归,岭回归),常数项bb的更新方程不包括正则项,即: 

其中,梯度下降算法中,α<0,β<0α<0,β<0,而在梯度上升算法中则相反。 
  从上式可以看出,L2正则项起到使得参数ww变小加剧的效果,但是为什么可以防止过拟合呢?一个通俗的理解便是:更小的参数值ww意味着模型的复杂度更低,对训练数据的拟合刚刚好(奥卡姆剃刀),不会过分拟合训练数据,从而使得不会过拟合,以提高模型的泛化能力。 
  在这里需要提到的是,在对模型参数进行更新学习的时候,有两种更新方式,mini-batch (部分增量更新)与 full-batch(全增量更新),即在每一次更新学习的过程中(一次迭代,即一次epoch),在mini-batch中进行分批处理,先使用一部分样本进行更新,然后再使用一部分样本进行更新。直到所有样本都使用了,这次epoch的损失函数值则为所有mini batch的平均损失值。设每次mini batch中样本个数为mm,那么参数的更新方程中的正则项要改成:

 

而full-batch即每一次epoch中,使用全部的训练样本进行更新,那么每次的损失函数值即为全部样本的误差之和。更新方程不变。
总结 
  正则项是为了降低模型的复杂度,从而避免模型区过分拟合训练数据,包括噪声与异常点(outliers)。从另一个角度上来讲,正则化即是假设模型参数服从先验概率,即为模型参数添加先验,只是不同的正则化方式的先验分布是不一样的。这样就规定了参数的分布,使得模型的复杂度降低(试想一下,限定条件多了,是不是模型的复杂度降低了呢),这样模型对于噪声与异常点的抗干扰性的能力增强,从而提高模型的泛化能力。还有个解释便是,从贝叶斯学派来看:加了先验,在数据少的时候,先验知识可以防止过拟合;从频率学派来看:正则项限定了参数的取值,从而提高了模型的稳定性,而稳定性强的模型不会过拟合,即控制模型空间。 
  另外一个角度,过拟合从直观上理解便是,在对训练数据进行拟合时,需要照顾到每个点,从而使得拟合函数波动性非常大,即方差大。在某些小区间里,函数值的变化性很剧烈,意味着函数在某些小区间里的导数值的绝对值非常大,由于自变量的值在给定的训练数据集中的一定的,因此只有系数足够大,才能保证导数的绝对值足够大。如下图(引用知乎): 
 
  另外一个解释,规则化项的引入,在训练(最小化cost)的过程中,当某一维的特征所对应的权重过大时,而此时模型的预测和真实数据之间距离很小,通过规则化项就可以使整体的cost取较大的值,从而,在训练的过程中避免了去选择那些某一维(或几维)特征的权重过大的情况,即过分依赖某一维(或几维)的特征(引用知乎)。 
  L2与L1的区别在于,L1正则是拉普拉斯先验,而L2正则则是高斯先验。它们都是服从均值为0,协方差为1λ1λ。当λ=0λ=0时,即没有先验)没有正则项,则相当于先验分布具有无穷大的协方差,那么这个先验约束则会非常弱,模型为了拟合所有的训练集数据, 参数ww可以变得任意大从而使得模型不稳定,即方差大而偏差小。λλ越大,标明先验分布协方差越小,偏差越大,模型越稳定。即,加入正则项是在偏差bias与方差variance之间做平衡tradeoff(来自知乎)。下图即为L2与L1正则的区别: 
 
上图中的模型是线性回归,有两个特征,要优化的参数分别是w1和w2,左图的正则化是L2,右图是L1。蓝色线就是优化过程中遇到的等高线,一圈代表一个目标函数值,圆心就是样本观测值(假设一个样本),半径就是误差值,受限条件就是红色边界(就是正则化那部分),二者相交处,才是最优参数。可见右边的最优参数只可能在坐标轴上,所以就会出现0权重参数,使得模型稀疏。 
  其实拉普拉斯分布与高斯分布是数学家从实验中误差服从什么分布研究中得来的。一般直观上的认识是服从应该服从均值为0的对称分布,并且误差大的频率低,误差小的频率高,因此拉普拉斯使用拉普拉斯分布对误差的分布进行拟合,如下图: 
 
而拉普拉斯在最高点,即自变量为0处不可导,因为不便于计算,于是高斯在这基础上使用高斯分布对其进行拟合,如下图: 
 
具体参见:正态分布的前世今生
Dropout
  正则是通过在代价函数后面加上正则项来防止模型过拟合的。而在神经网络中,有一种方法是通过修改神经网络本身结构来实现的,其名为Dropout。该方法是在对网络进行训练时用一种技巧(trick),对于如下所示的三层人工神经网络: 
 
对于上图所示的网络,在训练开始时,随机得删除一些(可以设定为一半,也可以为1/3,1/4等)隐藏层神经元,即认为这些神经元不存在,同时保持输入层与输出层神经元的个数不变,这样便得到如下的ANN: 
 
然后按照BP学习算法对ANN中的参数进行学习更新(虚线连接的单元不更新,因为认为这些神经元被临时删除了)。这样一次迭代更新便完成了。下一次迭代中,同样随机删除一些神经元,与上次不一样,做随机选择。这样一直进行瑕疵,直至训练结束。 
  Dropout方法是通过修改ANN中隐藏层的神经元个数来防止ANN的过拟合。具体可参见这里。
--------------------- 
作者:一只鸟的天空 
来源:CSDN 
原文:https://blog.csdn.net/heyongluoyao8/article/details/49429629 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

问题背景
最近做深度学习实验的时候遇到了一个很棘手的问题,那就是大名鼎鼎的“过拟合”,直观地表现在图中是长这个样子的,分析来讲就是说深度网络在拟合训练集的时候是可以很好地实现,Loss很小,Accuracy很大(我这儿能达到99.99%),但是呢,测试集的Loss很大,Accuracy在一个比较低的范围内波动(我这儿是70%-80%),并没有像论文中说的那样,测试集的Loss随着迭代的增加而减小,Accuracy随着迭代的增加而增大。



如果你没有看出来上图有什么毛病的话,我就放一张理想状态的结果图做对比(如下图粗粗的线),画的比较挫,但是大概的意思在那儿,随着迭代的增加,训练集和测试集的精确度应该上升,我们可以容忍测试集的精确度没有训练集那么高,毕竟有拟合的误差,但是像上图我做出来的结果那样,一定是“过拟合”啦。 

用白话来说“过拟合”就是:老师给你的题你都会做了,考试给你换个花样你就懵逼了。好,老师给你的题就相当于我们的训练数据,考试的题相当于测试数据,“过拟合”就是深度网络把训练的数据拟合的特别好,但是有点好过头了,对训练数据当然是100%好用,但是一来测试数据就疯了,那这样的网络训练出来其实是没有用的,训练集已经是监督学习了,拟合的再好也没用。

体现在函数上就是下图

正常是测试数据是一个线性或者二次多项式的分布,如果过拟合了,深度网络很有可以弄出一个特别复杂的拟合曲线函数,把上面所有的黑点点都穿过,当然训练数据的误差超级小,但是测试数据一来整个的误差就比较高了。

网络结构介绍
我实验中用到的深度网络结构原型是Fully Convolutional Networks,参考的论文中也叫它U-Net,总之就是一个用来做图像分割的深度网络。示意图如下:  

 用Keras的实现代码是:

大概的问题背景和网络结构介绍完毕,更多实验Details请参考PET/CT images segmentation via U-Net, using keras.

问题分析
当年LeNet-5在手写字的识别上出尽了风头,但是当LeNet-5应用到其他数据集中的时候却出现了很多问题,从此,学者们开始了疯狂的理论、实践探索。“过拟合”问题算是深度学习中一个特别重要的问题,老生常谈了,也有不少解决的方法供我选择。

举例来讲(感谢“知乎深度学习Keras”——QQ群中大神们的帮助):

1. 加入Dropout层

2. 检查数据集是否过小(Data Augmentation)

3. 用一用迁移学习的思想

4. 调参小tricks.

调小学习速率(Learning Rate)
调小每次反向传播的训练样本数(batch_size)
5. 试一试别的优化器(optimizer)

6. Keras的回调函数EarlyStopping()

评价:我认为第一个是比较可行,因为“教科书”上的确有说dropout是专门用来对付“过拟合”问题的。

关于数据集的大小,这也是导致过拟合的原因,如果太小,很容易过拟合。那么多大的数据集够了呢?反正我的肯定够了,我的深度网络输入图像是369,468幅,68*80像素的,二通道输入,总共的大小是19.5GB。这个数据量可以说是十分可观了,所以对我来说,第二条可能不适用。那么如果想要扩充数据集,需要用到Data Augmentation,这个是在医学影像中十分常用的手段,包括平移,旋转,拉伸,扭曲等等变换造出新的数据,来增加数据量。

第三条是深度学习中比较有效的方法了,英文名叫fine-tuning,就是用已有的训练完的网络参数作为初始化,在这个基础上继续训练。原来的网络参数往往会在很多论文和github里头能找到,这是在很大的图像数据集中训练完的网络,根据图形图像的“语义”相似性(我也不知道该怎么描述,就是认为世界上的图片都有某种相似性,就像人类,每个人都长得不一样,但是你不会把人和其他动物混在一起,这就是一个宏观的,抽象的相似性),把这个网络“迁移”到一个新的图像数据集中是有一定的道理的。由于时间原因,我暂时还没有采用这个。

第四条就是比较说不清道不明的调参了,这几乎是机器学习的主要话题,人说“有多少人工,就有多少智能”,这个调参真的需要“经验”啊哈哈哈。

不好意思,第五条又是试凑法。。。可供选择的Optimizers有很多,都试一下,看看用哪儿效果好,听上去有点丧心病狂了。

第六条方法是一个小函数,叫做EarlyStopping,代码如下 


early_stopping = EarlyStopping(monitor = 'val_loss', patience = 5)
作用是监视每次迭代的指标,比如说这儿监视的是val_loss(测试集的Loss),随着迭代的增加,当val_loss不再发生大的变化的时候可以终止训练,在过拟合之前阻断。这种策略也称为“No-improvement-in-n”,n就是Epoch的次数。
不幸的是,以上六个方案,我测试了以后都没有很好地解决“过拟合”问题。

 

 正则化方法
正则化方法是指在进行目标函数或代价函数优化时,在目标函数或代价函数后面加上一个正则项,一般有L1正则与L2正则等。这个很理论了,会涉及到一些公式。



这部分内容我在学习的时候就当它纯理论来记,当时根本没有想过会去真正用它,看来现在是必须要try一下了。

要在Keras中修改这部分代价函数(Objectives)的代码,可以参考这部分内容,里面包括了若干个代价函数,如果想要自己编写代价函数也可以的。根据这个博客:基于Theano的深度学习(Deep Learning)框架Keras学习随笔-08-规则化(规格化),有效解决过拟合的方法就是加入规则项。具体的规则化可以参见深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-04-基于Python的LeNet之MLP中对于规则化的介绍。博主Tig_Free是真神啊,膜拜一下!


问题解决
最终,过拟合的现象基本上被控制住了,总的来说,L1/L2规范化的确是很牛逼,在学术论文中也有所体现:

网络调整如下:


model = Sequential()
    
    model.add(Convolution2D(64, 4, 4, border_mode='valid', input_shape=data.shape[-3:]))
    model.add(Convolution2D(64, 3, 3, border_mode='valid'))
    model.add(Activation('relu'))
    model.add(Dropout(0.3))    
    #model.add(BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    
    model.add(Convolution2D(64, 4, 4, border_mode='valid'))
    model.add(Convolution2D(64, 3, 3, border_mode='valid'))    
    model.add(Activation('relu'))
    model.add(Dropout(0.3))    
    #model.add(BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
        
    model.add(Convolution2D(128, 4, 4, border_mode='valid'))
    model.add(Activation('relu'))
    model.add(Dropout(0.3))    
    #model.add(BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one'))
        
    model.add(Convolution2D(128, 3, 3, border_mode='valid')) 
    model.add(Activation('relu'))    
    model.add(Dropout(0.3))    
    #model.add(BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one'))    
    
    model.add(Convolution2D(128, 3, 3, border_mode='valid'))
    model.add(Activation('relu'))
    model.add(Dropout(0.3))
    #model.add(BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one'))
    model.add(MaxPooling2D(pool_size=(2, 2)))        
    
    model.add(Flatten())
    model.add(Dense(512, init='normal',W_regularizer=l2(0.02), activity_regularizer=activity_l2(0.01)))
    model.add(Activation('relu'))
    model.add(Dropout(0.3))
            
    model.add(Dense(512, init='normal',W_regularizer=l2(0.02), activity_regularizer=activity_l2(0.01)))
    model.add(Activation('relu'))
    model.add(Dropout(0.3))
            
    model.add(Dense(LABELTYPE, init='normal'))
    model.add(Activation('softmax')) 

配置:)
dropout层(0.3)
全连接层的L2规范化
优化器(adadelta)
学习速率(1e-9)
达到的效果比较令人满意,不仅训练集的Loss在降低,Acc在上升,测试集的Loss也同样降低,测试集的Acc在上升,整体的网络学习性能也变得比以前好了。

至此,深度网络的过拟合问题暂时告一段落。

关于过拟合的参考材料
机器学习中使用「正则化来防止过拟合」到底是一个什么原理?为什么正则化项就可以防止过拟合?

机器学习中防止过拟合的处理方法

用简单易懂的语言描述「过拟合 overfitting」?

Reducing Overfitting in Deep Networks by Decorrelating Representations. Michael Cogswell, Faruk Ahmed, Ross Girshick, Larry Zitnick, Dhruv Batra (2015)

Dropout: A Simple Way to Prevent Neural Networks from Overfitting. N Srivastava, G Hinton, A Krizhevsky, I Sutskever, R Salakhutdinov (2014)

Overfitting & Regularization (墙)

Regularization in Statistics. PJ Bickel, B Li (2006) 

Overfitting, Regularization, and Hyperparameters (墙)

Overfitting. by Hal Daume III (墙)

Data Science 101: Preventing Overfitting in Neural Networks. by Nikhil Buduma (墙)
--------------------- 
作者:MrGiovanni 
来源:CSDN 
原文:https://blog.csdn.net/mrgiovanni/article/details/52167016 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值