BN的利弊
为什么要进行 BN
机器学习领域对于数据的假设是,数据间独立同分布,而BatchNorm的作用是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。
神经网络在训练开始之前,要对输入的数据做Normalization,原因在于神经网络学习过程本质上是为了学习数据的分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另一方面,一旦在mini-batch梯度下降训练的时候,每批训练数据的分布不相同,那么网络就要在每次迭代的时候去学习以适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对所有训练数据做一个Normalization预处理的原因。
深度神经网络随着网络深度加深,训练起来越困难,收敛会越来越慢。和ReLU激活函数,以及ResNet一样,BN本质上也从某个不同的角度缓解了这个问题。
BN 层通常设置在激活函数之前。BN层的作用机制是对隐藏层输入的分布进行平滑,缓解随机梯度下降权重更新对后续层的负面影响。对sigmoid和tanh而言,放非线性激活之前,也许顺便还能缓解sigmoid或者 tanh的梯度衰减问题,而对ReLU而言,BN放到relu之前,可以防止某一层的激活值全部都被抑制,从而防止从这一层往前传的梯度全都变成0,也就是防止梯度消失。(当然也可以防止梯度爆炸)
怎样进行BN
假设神经网络的某一层的batch的输入为 X n , c , h , w = ( x 1 , x 2 . . . x n ) X_{n,c,h,w}=(x_1,x_2...x_n) Xn,c,h,w=(x1,x2...xn)
mini-batch里元素的均值是:
μ
=
∑
i
=
1
n
x
i
n
\mu = \frac {\sum_{i=1}^n x_i}{n}
μ=n∑i=1nxi
mini-batch的方差是:
σ
2
=
∑
i
=
1
n
(
x
i
−
μ
)
2
n
\sigma ^2 = \frac{\sum_{i=1}^n(x_i-\mu)^2}{n}
σ2=n∑i=1n(xi−μ)2
对每个元素进行归一化:
y
i
=
x
i
−
μ
σ
2
+
ϵ
y_i = \frac {x_i - \mu}{\sqrt{\sigma^2 + \epsilon}}
yi=σ2+ϵxi−μ
进行尺度缩放和偏移:
y
i
=
y
i
γ
i
+
β
i
y_i = y_i \gamma_i + \beta_i
yi=yiγi+βi
测试时的操作
在训练结束后,网络的mean和std就固定住了。
因为测试时计算batch的均值方差不适合(单样本的时候),因此会直接拿训练过程中对整个样本空间估算的mean和var直接来用。
BN的优点
(1)可以解决内部协变量偏移,使各层分布相似,是可以使loss更加的平滑,加快收敛速度
(2)缓解了梯度饱和问题(如果使用sigmoid这种含有饱和区间的激活函数的话),加快收敛。
BN的缺点
(1)batch_size较小的时候,效果差
(2)BN 在RNN中效果比较差,RNN的输入是长度是动态的
(3)就是在测试阶段的问题,均值和方差的计算可能与训练集的相差较大
使用场景
BN在MLP和CNN上使用的效果都比较好,在RNN这种动态文本模型上使用的比较差。至于为什么NLP领域BN效果会差