正则化之weight decay

  • 正则化与偏差-方差分解
  • pytorch中的L2正则化——weight decay

在机器学习、深度学习当中我们经常会听到regularization正则化这个概念,正则化这三个字到底是什么意思呢?如果直接从字面的意思来理解正则化是非常抽象的,但正则化的概念非常简单,就是减少方差的策略。那么什么是方差,什么是偏差呢?
误差可分解为:偏差、方差与噪声之和。即误差=偏差+方差+噪声之和,偏差度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力;
方差度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响;(验证集和训练集之间的差异)
噪声则表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界。
我们说一个模型过拟合就是说它在训练集上表现非常好,但是在测试集上表现就非常差,对应地,它就是一个高方差,而正则化策略就是用来降低高方差,所以也经常会听到用正则化来解决过拟合问题。其实本质上正则化就是用来降低高方差从而解决过拟合问题的。在前面介绍损失函数时,提到了目标函数的公式定义:
obj=Cost+Regularizationobj = Cost + Regularization
其中Regularization这项就是正则项,通常包括L1正则项和L2正则项:
L1 Regularization Term:iNwi\sum_{i}^{N} |w_{i}|
L2 Regularization Term:iNwi2\sum_{i}^{N} w_{i} ^ {2}
其中L2正则项又称为weight decay(权值衰减),下面通过公式的推到解释为什么L2正则项被称为权值衰减:

1.obj=Cost+Regularizationobj = Cost + Regularization
2.obj=Loss+λ2iNwi2obj = Loss + \frac{\lambda}{2}*\sum_{i}^{N} w_{i} ^ {2}
其中Cost可以用Loss来表示,而λ\lambda是pytorch中设置的超参数,用来调和Loss和正则项之间的比例;1/2是为了求导时计算方便。
在未添加正则项之前的权值更新公式为:
wi+1=wiobjwi=wiLosswiw_{i+1} = w_{i} - \frac{\partial obj}{\partial w_{i}} = w_{i} - \frac{\partial Loss}{\partial w_{i}}
加入正则项后,权值的更新公式为:
wi+1=wiobjwi=wi(Losswi+λwi)=wi(1λ)Losswiw_{i+1} = w_{i} - \frac{\partial obj}{\partial w_{i}} = w_{i} - (\frac{\partial Loss}{\partial w_{i}} + \lambda * w_{i}) \\ =w_{i}(1-\lambda)-\frac{\partial Loss}{\partial w_{i}}
可以看到加上正则项后权重的更新公式也只不过是比原来多乘了个1λ1-\lambda,而λ\lambda是一个大于0小于1的数,所以权重在数值上会衰减。
接下来分别采用添加weight decay和不添加weight decay来进行一元回归模型的结果测试:
Pytorch系列之——正则化
从运行结果可以看到,不带weight decay的损失值下降至0,虽然带weight decay的模型的损失值最终没能减至0,但是蓝色这条曲线其实是比较符合我们期望的模型的。而红色的曲线虽然loss比较小,但是它已经产生了过拟合现象(产生了高方差)。
因此L2正则项可以有效地缓解过拟合现象,降低高方差,并且它不仅对训练集有效,对测试集也有较好的表现。

正则化之Dropout

  • Dropout概念
  • Dropout注意事项

Dropout的作用就是随机失活,就是让神经元以某种概率失去“活性”,即权重为0。
Pytorch系列之——正则化左边的是正常的神经网络,每一层的神经元都与上一层的全部神经元相连,而右边的就是添加dropout的神经网络模型,可以看到有一些神经元已经“失活”,这些神经元与其他的神经元就没有了连接。
在无添加dropout时,举例来说,某个神经元a和上一层的全部神经元连接,如果某对神经元连接的权重较大则意味着这个神经元a过度依赖于和它相连的那个神经元,而其他和该神经元a相连的权重较小的神经元,则表明神经元a并不主要关注这些神经元(也就是这些特征),而加入dropout之后,则和神经元a相连的所有神经元它都是平等看待的,连接的权重都是不大不小的,并没有主次特征关注之分,这也就在一定程度上减轻了特征依赖性。

一般在使用中,数据尺度变化:测试时,所有权重乘以1-drop_prob,drop_prob=0.3,1-drop_prob=0.7。

参考文献:《Dropout:A simple way to prevent neural networks from overfitting》

nn.Dropout

功能:Dropout层
Pytorch系列之——正则化
参数:

  • p:被舍弃概率,失活概率

Pytorch系列之——正则化
可以看到迭代了2000轮之后,红色的不加Dropout的模型已经过拟合了,而蓝色的加入了Dropout之后的模型则比较平滑,没有产生过拟合现象。
实现细节:
训练时权重均乘以$$\frac{1}{1-p},即除以1-p。

Batch Normalization

  • Batch Normalization概念
  • Pytorch的Batch Normalization 1d/2d/3d实现

Batch Normalization:批标准化
批:一批数据,通常为mini-batch
标准化:0均值,1方差
优点:

  1. 可以用更大的学习率,加速模型收敛
  2. 可以不用精心设计权值初始化
  3. 可以不用dropout或较小的dropout
  4. 可以不用L2或者较小的weight decay
  5. 可以不用LRN(local response normalization)

参考文献:《Accelerating Deep Network Training by Reducing Internal Covariate Shift》

计算方式:
Pytorch系列之——正则化
这个是将x作为输入,并通过学习两个参数最后传入BN层得到一个输出。可以看到,首先它会对输入x求取mini-batch的一个均值,之后会根据求得的均值计算方差,得到均值和方差之后就可以进行normalize了,但BN算法还没有结束最后一步是affine transform(scale and shift),这步可以增强模型的容纳能力使模型更灵活选择性更多。

Pytorch系列之——正则化
其实在BN的原论文中,Batch Normalization的提出是为了解决ICS(Internal Covariate Shift)的问题的。具体内容可以参考列出的文献…

_BatchNorm

  • nn.BatchNorm1d

  • nn.BatchNorm2d

  • nn.BatchNorm3d
    Pytorch系列之——正则化参数:

  • num_features:一个样本特征数量(最重要)

  • eps:分母修正项

  • momentum:指数加权平均估计当前mean/var

  • affine:是否需要affine transform

  • track_running_stats:是训练状态还是测试状态

1d/2d/3d三个基本方法:
Pytorch系列之——正则化主要属性:

  • running_mean:均值
  • running_var:方差
  • weight:affine transform中的gamma
  • bias:affine transform中的beta

running_mean和running_var的计算方式:
训练:均值和方差采用加权平均计算
测试:当前统计值
runningmean=(1momentum)prerunningmean+momentummeantrunning_-mean = (1-momentum)*pre_-running_-mean+momentum*mean_-t
runningvar=(1momentum)prerunningvar+momentumvartrunning_-var = (1-momentum)*pre_-running_-var+momentum*var_-t

  • nn.BatchNorm1d input=B特征数1d特征
  • nn.BatchNorm2d input=B特征数2d特征
  • nn.BatchNorm3d input=B特征数3d特征
    Pytorch系列之——正则化

1d的话是在minibatch样本集的每个特征维度上都有均值、方差、weight和bias;2d的话是在每个特征图上都有均值、方差、weight和bias;3d就像下图那样比较复杂了。
Pytorch系列之——正则化

BN、LN、IN and GN

  • 为什么要Normalization?
  • 常见的Normalization——BN、LN、IN and GN
  • Normalization小结

为什么在深度学习中要用Normalization?

其实这个问题在Batch Normalization中已经给了我们答案,由于ICS经常会导致数据尺度/分布异常,导致训练困难,而进行Normalization会解决数据尺度/分布异常的问题,使模型的训练更加简便。

常见的Normalization:

  • Batch Normalization(BN)
  • Layer Normalization(LN)
  • Instance Normalization(IN)
  • Group Normalization(GN)

这四种Normalization方法不同的地方在于均值和方差求取的方式不同,但Normalization的计算公式都是一样的。

Layer Normalization

起因:BN不适用于变长的网络,如RNN
思路:逐层计算均值和方差
注意事项:

  1. 不再有running_mean和running_var
  2. gamma和beta为逐元素的
    Pytorch系列之——正则化解决方案就是逐层计算均值和方差,比如红色线画的是一层有5个神经元的网络层,那么就先计算这个网络层的均值和方差,依次类推。

pytorch中提供的LayerNorm这个网络层:

nn.LayerNorm

Pytorch系列之——正则化
主要参数:

  • normalized_shape:该层特征形状
  • eps:分母修正项
  • elementwise_affine:是否需要affine transform

Instance Normalization

起因:BN在图像生成(Image Generation)中不适用
思路:逐Instance(channel)计算均值和方差

Pytorch系列之——正则化举例说明,可以看到这里有三个样本,其中每个样本有三个特征图,每个特征图都是2x2的。而IN是逐通道的去计算均值和方差,也就是说不仅是每个样本都单独计算均值和方差,而且每个样本的每个特征图也是单独计算它的均值和方差的。
参考文献:
《Instance Normalization:The Missing Ingredient for Fast Stylization》
《Image Style Transfer Using Convolutional Neural Networks》

pytorch中IN的实现:

nn.InstanceNorm

Pytorch系列之——正则化主要参数:

  • num_features:一个样本特征数量(最重要)
  • eps:分母修正项
  • momentum:指数加权平均估计当前mean/var
  • affine:是否需要affine transform
  • track_running_stats:是训练状态还是测试状态

Group Normalization

起因:小batch样本中,BN估计的值不准
思路:数据不够,通道来凑
注意事项:

  1. 不再有running_mean和running_var
  2. gamma和beta为逐通道(channel)的
    应用场景:大模型(小batch size)任务

pytorch中的GN实现:

nn.GroupNorm

Pytorch系列之——正则化
主要参数:

  • num_groups:分组数
  • num_channels:通道数(特征数)
  • eps:分母修正项
  • affine:是否需要affine transform

以上四个BN、LN、IN和GN都是为了克服ICS(Internal Covariate Shift),ICS问题可能会导致模型训练过程中的梯度消失和梯度爆炸,从而使模型正常训练。

参考资料

深度之眼训练营——pytorch课程笔记

相关文章: