什么叫过拟合和欠拟合?
我们在模型训练的时候,通过把数据划分成训练集和测试集,然后选择Loss函数来评估训练效果怎么样,其loss函数在训练集上的值叫训练误差,在测试集上叫泛化误差,当训练误差比较大的时候,可能说明模型参数量比较小,难以拟合所有数据特征,称为欠拟合。反之当训练误差比较小,但是泛化误差比较大的时候,说明模型虽然在训练集上有不错的表现,但是在未见过的测试集上表现较差的这种现象称过拟合。
那什么是正则化呢,花书上说“凡是能够减少泛化误差的方法”都叫正则化。因此正则化是防止过拟合和提高模型泛化性能的一类方法的统称。
本文记录一下,经典的正则化方法有以下几种:
● Dropout - 在全连接层中随机丢弃部分神经元节点,产生一个简化了的网络结构
● L1/L2正则化 - 在原始的损失函数中增加L1/L2的惩罚项,从而限制产生较大的权重w
● Batch normalization - 控制隐层的输出在一个稳定的范围内
● 数据增强 - 通过增加数据集多样性的方式避免过拟合
● Early stopping - 在达到模型过拟合的阶段前停止训练模型
1 Dropout (随机失效)
Dropout通过随机地将一些神经元的输出置零,迫使模型不依赖于特定的神经元,从而增强了模型的泛化能力。这样,每个神经元都将学习到与其他神经元合作的特征,而不是过度依赖于某些特定的神经元。
在PyTorch中,可以通过在网络层中添加torch.nn.Dropout层来实现Dropout。例如:
import torch
import torch.nn as nn
if __name__ == '__main__':
# 创建一个4行5列的矩阵
matrix = torch.randn(4, 5)
# 定义Dropout层,设置p参数为0.2,表示将20%的元素设置为0
dropout = nn.Dropout(p=0.2)
# 应用Dropout层
matrix_dropout = dropout(matrix)
print("原始矩阵:")
print(matrix)
print()
print("应用Dropout后的矩阵:")
print(matrix_dropout)
输出:
原始矩阵:
tensor([[ 0.1143, -1.0621, 0.7031, -0.7662, -1.1596],
[-0.8340, -0.8210, -0.8747, 1.3130, -2.2559],
[-0.6311, 0.4332, 2.6923, 0.0424, 1.1330],
[ 1.7028, 0.3254, 0.1760, 1.9037, -0.2492]])
应用Dropout后的矩阵:
tensor([[ 0.1429, -1.3276, 0.8788, -0.9577, -1.4495],
[-1.0425, -1.0262, -1.0934, 1.6413, -2.8199],
[-0.0000, 0.5415, 3.3653, 0.0000, 0.0000],
[ 0.0000, 0.4068, 0.2201, 0.0000, -0.3115]])
数一数刚刚好4个0。在举一个例子,在实际网络中应用也比较简单。
import torch
import torch.nn as nn
# 定义一个简单的神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(100, 64)
self.dropout = nn.Dropout(0.5)
self.fc2 = nn.Linear(64, 10)
def forward(self, x):
x = self.fc1(x)
x = self.dropout(x)
x = torch.relu(x)
x = self.fc2(x)
return x
# 创建网络实例
net = Net()
# 在训练过程中使用dropout
net.train()
# 在测试过程中禁用dropout
net.eval()
在训练过程中,通过调用net.train()启用Dropout层,而在测试过程中,通过调用net.eval()禁用Dropout层。这是因为在训练过程中,Dropout层会随机丢弃神经元的输出,而在测试过程中,我们希望保留所有神经元的输出来获得更准确的预测结果。
2 L1/L2正则化
Loss函数:
2.1 为什么L1,L2正则可以解决过拟合问题?
答:模型的复杂度和参数的数量和参数的范围决定,拟合过程中通常都倾向于让权值尽可能小,最后构造一个所有参数都比较小的模型。因为一般认为参数值小的模型比较简单,能适应不同的数据集,也在一定程度上避免了过拟合现象。可以设想一下对于一个线性回归方程,若参数很大,那么只要数据偏移一点点,就会对结果造成很大的影响;但如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,专业一点的说法是抗扰动能力强。
L1正则:
其中,λ是正则化系数,控制正则化的强度;||w||₁表示参数向量w的L1范数。
L2正则:
其中,λ是正则化系数,控制正则化的强度;||w||₂表示参数向量w的L2范数。
给定特征X,训练模型得到的能满足测试集和验证集w值,可能有多个(求导的解不止一组),有的w值比较大,有的w值比较小,为了降低模型的复杂度,我们需要限制一下w的值,即想求解到比较小的w值,因此我们在损失函数后面直接加上了λ(w),由于梯度下降,为了使得总体L值小,那么后面的w也要比较小,从而得到使得模型的复杂度降低,从而解决过拟合问题。
2.2 为啥对参数w进行限制,不对参数B进行限制呢
因为B只能是曲线上下移动,不能降低复杂度
2.3 训练时如何确定λ值
考虑二维的情况,即只有两个权值和 ,此时对于梯度下降法,求解函数的过程可以画出等值线,同时L1正则化的函数也可以在二维平面上画出来。如下图:
图中彩色圆圈线是Loss中前半部分待优化项的等高线,就是说在同一条线上其取值相同,且越靠近中心其值越小。
黑色菱形区域是L1正则项限制。带有正则化的loss函数的最优解要在黑色菱形区域和彩色圆圈线之间折中,也就是说最优解出现在图中优化项等高线与正则化区域相交处。从图中可以看出,当待优化项的等高线逐渐向正则项限制区域扩散时,L1正则化的交点大多在坐标轴上,则很多特征维度上其参数w为0,因此会产生稀疏解;而正则化前面的系数,可以控制图形的大小。越小,约束项的图形越大(上图中的黑色方框);越大,约束项的图形就越小,可以小到黑色方框只超出原点范围一点点,这是最优点的值中的可以取到很小的值。
同时L2正则化的函数也可以在二维平面上画出来。如下图:
图中彩色一圈一圈的线是Loss中前半部分待优化项的等高线,就是说在同一条线上其取值相同,且越靠近中心其值越小。图中黑色圆形区域是L2正则项限制。带有正则化的loss函数的最优解要在loss函数和正则项之间折中,也就是说最优解出现在图中优化项等高线与正则化区域相交处。从图中可以看出,当待优化项的等高线逐渐向正则项限制区域扩散时L2正则化的交点大多在非坐标轴上,二维平面下L2正则化的函数图形是个圆,与方形相比,被磨去了棱角。因此与相交时使得或等于零的机率小了许多,这就是为什么L2正则化不具有稀疏性的原因。
一般来说,λ的确定,从0开始,逐渐增大λ。在训练集上学习到参数,然后在测试集上验证误差。反复进行这个过程,直到测试集上的误差最小。一般的说,随着λ从0开始增大,测试集的误分类率应该是先减小后增大,交叉验证的目的,就是为了找到误分类率最小的那个位置。建议一开始将正则项系数λ设置为0,先确定一个比较好的learning rate。然后固定该learning rate,给λ一个值(比如1.0),然后根据validation accuracy,将λ增大或者减小10倍,增减10倍是粗调节,当你确定了λ的合适的数量级后,比如λ= 0.01,再进一步地细调节,比如调节为0.02,0.03,0.009之类。