过拟合和欠拟合现象及解决方案

过拟合和欠拟合

欠拟合:(under-fitting)也称为欠学习,它的直观表现是算法训练得到的模型在训练集上表现差,没有学到数据的规律。引起欠拟合的原因有:模型本身过于简单,例如数据本身是非线性的但使用了线性模型;特征数太少无法正确的建立统计关系。

过拟合:(over-fitting)随着训练过程的进行,模型复杂度,在training data上的error渐渐减小。可是在验证集上的error却反而渐渐增大——由于训练出来的网络过拟合了训练集,对训练集以外的数据却不work。过拟合即在训练误差很小,而泛化误差很大,因为模型可能过于的复杂,使其”记住”了训练样本,然而其泛化误差却很高。

解决过拟合的方法:

1. 加入正则化项,参数范数惩罚,可在优化原来目标函数的同时,避免权值过大带来的过拟合风险

最常用的范数惩罚为L1,L2正则化,L1又被成为Lasso,

Lasso回归的损失函数:

Ridge回归损失函数:

L1正则可以产生稀疏模型(L1是怎么让系数等于零的)。

假设有如下带L1正则化的损失函数:

其中J0是原始的损失函数,加号后面的一项是L1正则化项,α是正则化系数。注意到L1正则化是权值的绝对值之和,J是带有绝对值符号的函数,因此J是不完全可微的。机器学习的任务就是要通过一些方法(比如梯度下降)求出损失函数的最小值。当我们在原始损失函数J0后添加L1正则化项时,相当于对J0做了一个约束。令L=α∑w∣w∣,则J=J0+L,此时我们的任务变成在L约束下求出J0取最小值的解。考虑二维的情况,即只有两个权值w1和w2,此时L=∣w1∣+∣w2∣对于梯度下降法,求解J0的过程可以画出等值线,同时L1正则化的函数L。

L也可以在w1w2的二维平面上画出来。如下图:

图中等值线是J0的等值线,黑色方形是L函数的图形。在图中,当J0等值线与L图形首次相交的地方就是最优解。上图中J0与L在L的一个顶点处相交,这个顶点就是最优解。注意到这个顶点的值是(w1,w2)=(0,w)。可以直观想象,因为L函数有很多『突出的角』(二维情况下四个,多维情况下更多),J0与这些角接触的机率会远大于与L其它部位接触的机率,而在这些角上,会有很多权值等于0,这就是为什么L1正则化可以产生稀疏模型,进而可以用于特征选择。

而正则化前面的系数α,可以控制L图形的大小。α越小,L的图形越大(上图中的黑色方框);α越大,L的图形就越小,可以小到黑色方框只超出原点范围一点点,这是最优点的值(w1,w2)=(0,w)中的w可以取到很小的值。

L2正则:

二维平面下L2正则化的函数图形是个圆,与方形相比,被磨去了棱角。因此J0与L相交时使得w1或w2等于零的机率小了许多,这就是为什么L2正则化不具有稀疏性的原因。

(2)数据增强,增加样本数据量

pytorch常用的数据增强:

    #随机比例缩放
		new_im = transforms.Resize((100, 200))(im)
	#随机位置裁剪
		new_im = transforms.RandomCrop(100)(im)		#裁剪出100x100的区域
		new_im = transforms.CenterCrop(100)(im)
	#随机水平/垂直翻转
		new_im = transforms.RandomHorizontalFlip(p=1)(im) 
		new_im = transforms.RandomVerticalFlip(p=1)(im)
	#随机角度旋转
		new_im = transforms.RandomRotation(45)(im)  
	#色度、亮度、饱和度、对比度的变化
		new_im = transforms.ColorJitter(brightness=1)(im)
		new_im = transforms.ColorJitter(contrast=1)(im)
		new_im = transforms.ColorJitter(saturation=0.5)(im)
		new_im = transforms.ColorJitter(hue=0.5)(im)
	#进行随机的灰度化
		new_im = transforms.RandomGrayscale(p=0.5)(im)    # 以0.5的概率进行灰度化
	#Padding (将原始图padding成正方形)
		new_im = transforms.Pad((0, (im.size[0]-im.size[1])//2))(im)  # 原图为(500,313)
	#使用Compose函数生成一个PiPeLine
		data_transform={‘train':transforms.Compose([
					transforms.RandomHorizontalFlip(),
					transforms.Resize(image_size),
					transforms.CenterCrop(image_size),
					transforms.ToTensor(),
					transforms.Normalize([0.485, 0.456, 0.406],
								 [0.229, 0.224, 0.225]																
					])

(3)提前终止(early stopping)

模型在验证集上的误差在一开始是随着训练集的误差的下降而下降的。当超过一定训练步数后,模型在训练集上的误差虽然还在下降,但是在验证集上的误差却不在下降了。此时我们的模型就过拟合了。因此我们可以观察我们训练模型在验证集上的误差,一旦当验证集的误差不再下降时,我们就可以提前终止我们训练的模型。

(4)参数绑定与参数共享

在卷积神经网络CNN中,卷积层就是其中权值共享的方式,一个卷积核通过在图像上滑动从而实现共享参数,大幅度减少参数的个数,用卷积的形式是合理的。

(5)bagging 和其他集成方法

(6)Dropout

当一个复杂的前馈神经网络被训练在小的数据集时,容易造成过拟合。为了防止过拟合,可以通过阻止特征检测器的共同作用来提高神经网络的性能。

Dropout说的简单一点就是:我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征。

没有Dropout的网络计算公式:

采用Dropout的网络计算公式:

代码层面实现让某个神经元以概率p停止工作,其实就是让它的激活函数值以概率p变为0。比如我们某一层网络神经元的个数为1000个,其激活函数输出值为y1、y2、y3、……、y1000,我们dropout比率选择0.4,那么这一层神经元经过dropout后,1000个神经元中会有大约400个的值被置为0。

训练的时候会随机的丢弃一些神经元,但是预测的时候就没办法随机丢弃了。如果丢弃一些神经元,这会带来结果不稳定的问题,也就是给定一个测试数据,有时候输出a有时候输出b,结果不稳定,这是实际系统不能接受的,用户可能认为模型预测不准。那么一种”补偿“的方案就是每个神经元的权重都乘以一个p,这样在“总体上”使得测试数据和训练数据是大致一样的。比如一个神经元的输出是x,那么在训练的时候它有p的概率参与训练,(1-p)的概率丢弃,那么它输出的期望是px+(1-p)0=px。因此测试的时候把这个神经元的权重乘以p可以得到同样的期望。

为什么说Dropout可以解决过拟合?

a. 取平均的作用

b. 减少神经元之间复杂的共适应关系

c. Dropout类似于性别在生物进化中的角色

(7) 辅助分类节点(auxiliary classifiers)

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

(8) Batch Normalization

BN在训练某层时,会对每一个mini-batch数据进行标准化(normalization)处理,使输出规范到N(0,1)的正太分布,减少了Internal convariate shift(内部神经元分布的改变),传统的深度神经网络在训练是,每一层的输入的分布都在改变,因此训练困难,只能选择用一个很小的学习速率,但是每一层用了BN后,可以有效的解决这个问题,学习速率可以增大很多倍.

(9)降低模型复杂度

在数据量较少时,模型过于复杂是产生过拟合的主要因素,适当降低模型复杂度可以避免模型拟合过多的采样噪声。例如,在神经网络中减少网络层数、神经元个数;在决策树模型中降低树的深度,进行剪枝。

解决欠拟合的方法:

1. 添加新特征。

当特征不足或现有特征与样本标签的相关性不强时,模型容易出现欠拟合。通过挖掘“上下文特征”“ID类特征”“组合特征”等新的特征,往往能取得更好的效果。在深度学习潮流中,有很多模型可以帮助完成特征工程,如因子分解机、梯度提升决策树、Deep-crossing等都可以成为丰富特征的方法。

2. 增加模型复杂度

简单的模型学习能力较差,通过增加模型的复杂度可以使模型拥有更强的拟合能力。例如,在线性模型中添加高次项, 在神经网络中增加网络层数或神经元个数等。

3. 减少正则化系数

正则化是用来防止过拟合的,但当模型出现欠拟合时,需要有针对性地减少正则化系数。

代码交流 2020