Batch Normalization

论文及背景

Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

这篇论文提出了深度学习里加速训练的一个策略:Batch Normalization

Motivation

Distribution of each layer’s inputs changes during training. This slows down the training by requiring lower learning rates and careful parameter initialization

— Internal Covariate Shift Phenomenon

在深度学习训练过程中,每一层输入的分布是变化的,很小的参数改变可能引发网络剧烈变动,而且随着网络深度的增加这种情况会更严重。为了防止网络剧烈波动,学习率就需要设置的很小,导致训练会很慢。同时,参数的初始设置也需要很小心。

而且如果参数变动厉害,对于一些非线性变换,会有gradient vanish的问题。如:

其中,$g$是sigmoid。如果$W,b$变化剧烈,$u=Wx+b$的值也会变动很大,很容易到达sigmoid两边的区域,梯度会很小。

解决方法

出发点

神经网络可看出多个子网络的组合,比如计算:

这个网络可看成2个子网络$F_1,F_2$.

对于每个网络$F$,更新步骤为:

其中$x$为当前子网络的输入,之前网络的输出。

正如如果训练集和测试集样本分布一致的话,模型的Generalization会很好一样,如果每个子网络的输入分布保持一致,训练速度会加快。(感觉有点牵强)

一般白化的问题

要想得到一致的分布,一下子想到的做法是在每一层输出的时候白化一下(标准化)。比如,有个网络计算:

不考虑方差的话,标准化过程是:$x = x - E(x)$。

如果忽略$E(x)$与$b$之间的关系,更新$b$时有:$b = b + \Delta b$,那么

其实是没有变化的,那么最后loss也不会变,最后$b$会变成正无穷。

出现上面情况的原因是,这个计算过程忽略了大量关联关系:如期望与参数之间的关系,样本与样本之间的关系。

一般的,如果把白话抽象表示如下:

那么$x$ 与$X$是有关系的,那么在计算梯度时不仅$\frac{\partial loss}{\partial x}$要考虑,同时$\frac{\partial loss}{\partial X}$也要考虑。这时计算代价会很高,需要计算:

为此需要一种新的白化方法

论文的方法

为了解决一般白化的问题,作者做了两个简化:

  1. 将每一层的每个特征看作独立
  2. 在一个mini-batch上白化,而不是在整个数据集上白化

具体来说,对于一个输入$x = (x^{(1)},\cdots,x^{(d)})$,白化过程是:

为了保证不改变模型的表达能力,会加入一个线性变化:

当$\gamma^{(k)} = \sqrt{Var[x^{(k)}]}$,$\beta^{(k)} = E[x^{(k)}]$,事实上是恢复了原来的分布。

过程如下:

BN 过程

那么问题来了,既然分布恢复了,那又如何保证每个子网络输入分布保持一致?

这其实要绕过弯,如果我们把式(1)和后面网络放在一起当作一个子网络,那么对于这个子网络来说输入的分布就是标准正态分布

在inference阶段,确定$E[x]$和$Var[x]$的方法是取多个训练集batch,求出相应的均值和方差,然后用无偏估计:

具体训练步骤如下:

BN 网络训练

另外,batchnorm能够使得网络训练对参数大小不敏感。对于:

也就是说即使参数变大了,使用BN后,backward的时候实际上是没有影响的

并且

权值变大的时候,相应的梯度会变小,可以使得网络训练更加稳定。