批量归一化 - BatchNorm
批量归一化(Batch Normalization),由Google于2015年提出,是近年来深度学习(DL)领域最重要的进步之一。该方法依靠两次连续的线性变换,希望转化后的数值满足一定的特性(分布),不仅可以加快了模型的收敛速度,也一定程度缓解了特征分布较散的问题,使深度神经网络(DNN)训练更快、更稳定。
- 损失出现在最后,后面的层训练较快
- 数据在最底部
- 底部的层训练较慢
- 底部层一变化,所有都得跟着变
- 最后的那些层需要重新学习多次
- 导致收敛变慢
- 我们可以在学习底部层的时候避免变化顶部层吗?
固定小批量里面的均值和方差
μ
B
=
1
∣
B
∣
∑
i
∈
B
x
i
a
n
d
σ
B
2
=
1
∣
B
∣
∑
i
∈
B
(
x
i
−
μ
B
)
2
+
ϵ
\mu_B = \frac{1}{|B|}\sum\limits_{i\in B}x_i\ and\ \sigma_B^2=\frac{1}{|B|}\sum\limits_{i\in B}(x_i-\mu_B)^2+\epsilon
μB=∣B∣1i∈B∑xi and σB2=∣B∣1i∈B∑(xi−μB)2+ϵ
然后再做额外的调整(可学习的参数)
x
i
+
1
=
γ
x
i
−
μ
B
σ
B
+
β
x_{i+1}=\gamma\frac{x_i-\mu_B}{\sigma_B}+\beta
xi+1=γσBxi−μB+β
其中,
γ
\gamma
γ和
β
\beta
β可学习的参数。
批量归一化层
- 可学习的参数为 γ \gamma γ和 β \beta β
- 作用在
- 全连接层和卷积层输出上,激活函数前(批量归一化是线性变换)
- 全连接层和卷积层输入上
- 对于全连接层,作用在特征维
- 对于卷积层,作用在通道维
总结:
批量归一化固定小批量中的均值和方差,然后学习出适合的偏移和缩放
可以加速收敛速度(增大学习率),但一般不改变模型精度
当使用了批量归一化层之后,再使用丢弃法的话,效果就没有太大了。
应用BatchNorm于LeNet模型
class MyLeNet(nn.Module):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.model = nn.Sequential(
Reshape(),
nn.Conv2d(1,6,kernel_size=5,padding=2),
nn.BatchNorm2d(6),
nn.Sigmoid(),
nn.MaxPool2d(2,stride=2),
nn.Conv2d(6,16,kernel_size=5),
nn.BatchNorm2d(16),
nn.Sigmoid(),
nn.MaxPool2d(2,stride=2),
nn.Flatten(),
nn.Linear(16*5*5,120),
nn.BatchNorm1d(120),
nn.Sigmoid(),
nn.Linear(120,84),
nn.BatchNorm1d(84),
nn.Sigmoid(),
nn.Linear(84,10)
)
def forward(self,x):
return self.model(x)