一、BN层
1. 背景
为了追求更高的性能,卷积网络被设计得越来越深,然而网络却变得难以训练收敛与调参。
2. 原因
浅层网络的微弱变化经过多层线性变换与激活函数后会被放大,改变了每一层的输入分布,造成深层的网络需要不断调整以适应这些分布变化,最终导致模型难以训练收敛。
3. ICS现象
由于网络中参数变化导致的内部节点数据分布发生变化的现象被称为ICS(Internal Covariate Shift)。ICS现象容易使训练过程陷入饱和区,减慢网络的收敛。
4. 解决方法
2015年提出的BN层,从改变数据分布的角度避免了参数陷入饱和区。
BN层首先对每一个batch的输入特征进行白化操作,即去均值方差过程。假设一个batch的输入数据为 x x x: B = B= B= { x 1 x_{1} x1, x 2 x_{2} x2, . . . ... ..., x m x_{m} xm},首先求该batch数据的均值与方差,如式(1-1)和式(1-2)所示。
μ B = 1 m ∑ i = 1 m x i (1-1) \mu _{B}= \frac{1}{m}\sum_{i=1}^{m}x_{i}\tag{1-1} μB=m1i=1∑mxi(1-1)
σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 (1-2) \sigma _{B}^{2}=\frac{1}{m}\sum_{i=1}^{m}\left ( x_{i}-\mu _{B} \right )^{2}\tag{1-2} σB2=m1i=1∑m(xi−μB)2(1-2)
以上公式中, m m m代表batch的大小, μ B \mu _{B} μB为批处理数据的均值, σ B 2 \sigma _{B}^{2} σB2为批处理数据的方差。在求得均值方差后,利用公式(1-3)进行去均值方差操作。
x i ^ = x i − μ B σ B 2 + ϵ (1-3) \hat{x_{i}}=\frac{x_{i}-\mu _{B}}{\sqrt{\sigma _{B}^{2}+\epsilon }}\tag{1-3} xi^=σB2+ϵxi−μB(1-3)
白化操作可以使输入的特征分布具有相同的均值和方差,固定了每一层的输入分布,从而加速网络的收敛。然而,白化操作虽然从一定程度上避免了梯度饱和,但也限制了网络中数据的表达能力,浅层学到的参数信息会被白化操作屏蔽掉,因此,BN层在白化操作后又增加了一个线性变换操作,让数据尽可能恢复本身的表达能力,如公式(1-4)所示。
y i = γ x i ^ + β (1-4) y_{i}=\gamma \hat{x_{i}}+\beta \tag{1-4} yi=γxi^+β(1-4)
公式(1-4)中, γ \gamma γ与 β \beta β为新引进的可学习参数,最终的输出为 y i y_{i} yi。
5.BN层的优点
BN层可以看做是增加了线性变换的白化操作,在实际工程中被证明了能够缓解神经网络难以训练的问题。BN层的优点主要有以下3点:
- 缓解梯度消失,加速网络收敛
BN层可以让激活函数的输入数据落在非饱和区,缓解了梯度消失问题。此外,由于每一层数据的均值与方差都在一定范围内,深层网络不必去不断适应浅层网络输入的变化,实现不层间解耦,允许每一层独立学习,也加快了网络的收敛。
- 简化调参,网络更稳定
在调参时,学习率调得过大 容易出现震荡与不收敛,BN层则抑制了参数微小变化随网络加深而被放大的问题,因此对于参数变化的适应能力更强,更容易调参。
- 防止过拟合
BN层将每一个batch的均值与方差引入到网络,由于每个batch的这两个值都不相同,可看作为训练过程增加了随即噪音,可以起到一定的正则效果,防止过拟合。
6.BN层的缺点
- 功效难发挥
由于BN层是在batch的维度进行归一化,BN层要求较大的batch才能有效地工作,而物体检测等任务由于占用内存较高,限制了batch的大小,这会限制BN层有效地发挥归一化功能。
- 测试集依赖于训练集
数据的batch大小在训练与测试时往往不一样。在训练时一般采用滑动来计算平均值与方差,在测试时直接拿训练集的平均值与方差来使用。这种方式会导致测试集依赖于训练集,然而有时训练集与测试集的数据分布并不一致。
7.Pytorch示例
from torch import nn
bn = nn.BatchNorm2d(64) # 使用BN层需要传入一个参数num_features,即特征的通道数
print('BN:',bn)
input = torch.randn(4, 32, 224, 224)
output = bn(input)# BN层不改变输入层的特征大小,只改变通道数
print('Output Shape:',output.shape)