Batch Normalization,Layer Normalization,Weight Normalization
1 Interral Covariate Shift
在深度神经网络的训练过程中,每次优化,低层的参数变化,一方面,随着层数加深,这些变化会被放大,另一方面。底层参数变化会导致高层的输入分布变化,上层网络需要不断的适应这些变化,导致训练困难,这一现象叫做Interal Covariate Shift。
1.1 什么是Interal Covariate Shift
Interal Covariate Shift:在深层网络训练过程中,由于参数变化导致内部节点数据分布发生变化的过程称为Interal Covariate Shift。
1.2 Interal Covariate Shift存在的问题
(1)学习速度变慢:上层网络输入分布不断变换,导致上层学习困难,学习速度降低。
(2)容易陷入激活函数的梯度饱和区:我们通常会在输入层做标注化操作,这样输入层的x均值时0。激活函数sigmoid在0附近梯度敏感,经过多层非线性变化后,上层的输入可能会位于激活函数的梯度饱和区。
解决梯度饱和主要两个思路:1)使用更理想的激活函数,如Relu 2)正则,维持输入分布避免陷入梯度饱和区
1.3 如何缓解Interal Covariate Shift
1.3.1 白化操作
白化有两个目的:(1)去除特征的相关性,(2)使输入分布具有相同的均值和方差。PCA白化使每个特征均值为0,方差为1,;ZCA白化使得每个特征的均值为0,方差相等。
但是如果在每层都进行白化操作存在问题
(1)计算成本高
(2)让每层的分布均值为0,方差为1会限制网络的表达能力。
于是提出了改进版的正则化操作:Batch Normlization
(1)对计算量的优化:在batch数据中,对每一个特征进行均值归一化(也就是每层中的每一个神经元)。
(2)为增加表达能力:在增加一个线性变换,对0均值1方差的分布微调。
Z
=
γ
Z
+
β
Z=\gamma Z+\beta
Z=γZ+β
其中
γ
,
β
\gamma,\beta
γ,β都是需要学习的参数。
Normlization的优点:
(1)避免梯度饱和的同时缓解Interal Covariate Shift问题。使用相对小的计算代价,使得每层的输入分布都接近0均值1方差的分布。避免梯度饱和的同时缓解Interal Covariate Shift问题。
(2)保证网络的表达能力。同时又不是严格的0均值,1方差分布,又保证了网络的表达能力。
缺点:
(1)要求batch size足够大。Batch normlization简化了白化操作的计算量,只使用batch数据计算均值和方差,替换使用全部数据来计算均值和方差。为了batch计算的均值方差近似整体的均值和方差,所以BN要求batch size要足够大。
(2)不使用RNN,因为RNN中batch的各输入序列可能不等长。
注意:测试时,可能只有一个样本,无法计算均值或方差。我们使用所有训练样本每个特征在每层的均值和方差,在测试时进行标准化。即要求在每层和每个batch的数据都要记录下均值和方差,导致不适用与RNN网络。因为RNN计算时间步计算的。BN用于RNN会占用很多的内存,并且RNN处理的sequence可以是变长的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0euLbkak-1620993574247)(C:\Users\sfang.fangsh\Desktop\20180714183939113.png)]
Layer Normlization :BN是对每个神经元(每维特征)在batch数据内进行标准化。Layer Normlization是对每个样本的所有特征进行标准化。
BN和Layer Normlization都是在网络层内部归一化的操作。
y
=
x
−
E
[
x
]
v
a
r
(
x
)
+
ε
∗
γ
+
β
(1)
y=\frac{x-E[x]}{\sqrt{var(x)+\varepsilon}}*\gamma+\beta\tag1
y=var(x)+εx−E[x]∗γ+β(1)
BN和LN的公式都是(1),只是期望
E
[
x
]
和
v
a
r
(
x
)
E[x]和var(x)
E[x]和var(x)计算的方式不同,如figurew2,BN对N,H,W维归一化操作。LN是对H,W,C进行归一化操作。
BN:
E
c
[
x
]
=
1
N
×
H
×
W
∑
N
∑
H
∑
W
x
c
σ
c
(
x
)
=
1
N
×
H
×
W
∑
N
∑
H
∑
W
(
x
c
−
E
[
x
]
)
2
+
ε
E_c[x]=\frac{1}{N\times H\times W}\sum_N\sum_H\sum_Wx_c\\ \sigma_c(x)=\sqrt{\frac{1}{N\times H\times W}\sum_N\sum_H\sum_W(x_c-E[x])^2+\varepsilon}
Ec[x]=N×H×W1N∑H∑W∑xcσc(x)=N×H×W1N∑H∑W∑(xc−E[x])2+ε
LN:
E
n
[
x
]
=
1
C
×
H
×
W
∑
C
∑
H
∑
W
x
n
σ
n
(
x
)
=
1
C
×
H
×
W
∑
C
∑
H
∑
W
(
x
n
−
E
[
x
]
)
2
+
ε
E_n[x]=\frac{1}{C\times H\times W}\sum_C\sum_H\sum_Wx_n\\ \sigma_n(x)=\sqrt{\frac{1}{C\times H\times W}\sum_C\sum_H\sum_W(x_n-E[x])^2+\varepsilon}
En[x]=C×H×W1C∑H∑W∑xnσn(x)=C×H×W1C∑H∑W∑(xn−E[x])2+ε
实验证明,用于RNN中LR的效果较好,明显优于BN,但是在CNN中不如BN。
dropout
是一种避免过拟合的方法。
- 一方面,dorpout随机屏蔽可以避免过度依赖某些特征
- 另一方面,可以看做是模型集成。底层特征共用,结构不同的多个模型融合。
训练过程:
以p的概率使隐含层的每个神经元随机失活。只保留(1-p)的隐含层神经元。
预测过程:
使用全部神经元,由于使用神经元个数增加。所以要加权重衰减每个神经元的权重。如训练时只使用(1-p)比例的神经元,测试时使用神经元个数是训练的1/(1-p)倍。所以每个神经元的权重要设置为(1-p)。也可以在训练时,提高每个神经元的权重1/(1-p)。那么测试时就无需修改。
代码实现:
import torch
import torch.nn as nn
class dropout(nn.Module):
def __init__(self,drop_rate=0.5):
super(nn.Module,self).__init__()
self.drop_rate = daop_rate
def forward(x):
keep_rate = 1 - self.drop_rate
if keep_rate == 0:
return torch.zeros_like(x)
else:
mask = (torch.rand(x.size()) < keep_rate).float()
y = (x * mask)/(keep_rate)
return y
Multi-sample dropout
加速收敛。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEksR3hv-1620993574248)(C:\Users\sfang.fangsh\AppData\Roaming\Typora\typora-user-images\image-20200612161914872.png)]
正常的dropout在隐藏层后面加一层dropout。而Multi-sample dropout在隐藏层后增加M个并行连接的dropout。并且每个dropout的随机失活mask矩阵不同(每个dropout会使不同的神经元失活)。之后全连接层的权重是共享的。
为什么可以加速训练:
如果将一个样本复制M份输入正常dropout结构的网络中,每个样本在dropout的随机失活掩码矩阵不同。同时计算量增加了M倍。M个并行连接的dropout等价于将一个样本复制M份,并且增加大量计算量。没有显著增加计算成本的情况下获得相似收益。所以可以加速收敛。