BN是由Google于2015年提出,这是一个深度神经网络训练的技巧,它不只能够加快了模型的收敛速度,并且更重要的是在必定程度缓解了深层网络中“梯度弥散”的问题,从而使得训练深层网络模型更加容易和稳定。因此目前BN已经成为几乎全部卷积神经网络的标配技巧了。网络
从字面意思看来Batch Normalization(简称BN)就是对每一批数据进行归一化,确实如此,对于训练中某一个batch的数据{x1,x2,...,xn},注意这个数据是能够输入也能够是网络中间的某一层输出。在BN出现以前,咱们的归一化操做通常都在数据输入层,对输入的数据进行求均值以及求方差作归一化,可是BN的出现打破了这一个规定,咱们能够在网络中任意一层进行归一化处理,由于咱们如今所用的优化方法大多都是min-batch SGD,因此咱们的归一化操做就成为Batch Normalization。函数
咱们知道网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(由于输入层数据,咱们已经人为的为每一个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,由于在训练的时候,前面层训练参数的更新将致使后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算获得的,而第一层的参数在整个训练过程当中一直在变化,所以必然会引发后面每一层输入数据分布的改变。咱们把网络中间层在训练过程当中,数据分布的改变称之为:“Internal Covariate Shift”。BN的提出,就是要解决在训练过程当中,中间层数据分布发生改变的状况。性能
如上图所示,BN步骤主要分为4步:学习
一个标准的归一化步骤就是减均值除方差,那这种归一化操做有什么做用呢?咱们观察下图,测试
a中左图是没有通过任何处理的输入数据,曲线是sigmoid函数,若是数据在梯度很小的区域,那么学习率就会很慢甚至陷入长时间的停滞。减均值除方差后,数据就被移到中心区域如右图所示,对于大多数激活函数而言,这个区域的梯度都是最大的或者是有梯度的(好比ReLU),这能够看作是一种对抗梯度消失的有效手段。对于一层如此,若是对于每一层数据都那么作的话,数据的分布老是在随着变化敏感的区域,至关于不用考虑数据分布变化了,这样训练起来更有效率。优化
那么为何要有第4步,不是仅使用减均值除方差操做就能得到目的效果吗?咱们思考一个问题,减均值除方差获得的分布是正态分布,咱们可否认为正态分布就是最好或最能体现咱们训练样本的特征分布呢?不能,好比数据自己就很不对称,或者激活函数未必是对方差为1的数据最好的效果,好比Sigmoid激活函数,在-1~1之间的梯度变化不大,那么非线性变换的做用就不能很好的体现,换言之就是,减均值除方差操做后可能会削弱网络的性能!针对该状况,在前面三步以后加入第4步完成真正的batch normalization。spa
BN的本质就是利用优化变一下方差大小和均值位置,使得新的分布更切合数据的真实分布,保证模型的非线性表达能力。BN的极端的状况就是这两个参数等于mini-batch的均值和方差,那么通过batch normalization以后的数据和输入彻底同样,固然通常的状况是不一样的。orm
在训练时,咱们会对同一批的数据的均值和方差进行求解,进而进行归一化操做。可是对于预测时咱们的均值和方差怎么求呢?好比咱们预测单个样本时,那还怎么求均值和方法呀!实际上是这种样子的,对于预测阶段时所使用的均值和方差,其实也是来源于训练集。好比咱们在模型训练时咱们就记录下每一个batch下的均值和方差,待训练完毕后,咱们求整个训练样本的均值和方差指望值,做为咱们进行预测时进行BN的的均值和方差:blog
最后测试阶段,BN的使用公式就是:input
关于BN的使用位置,在CNN中通常应做用与非线性激活函数以前,s型函数s(x)的自变量x是通过BN处理后的结果。所以前向传导的计算公式就应该是:
其实由于偏置参数b通过BN层后实际上是没有用的,最后也会被均值归一化,固然BN层后面还有个β参数做为偏置项,因此b这个参数就能够不用了。所以最后把BN层+激活函数层就变成了:
注意前面写的都是对于通常状况,对于卷积神经网络有些许不一样。由于卷积神经网络的特征是对应到一整张特征响应图上的,因此作BN时也应以响应图为单位而不是按照各个维度。好比在某一层,batch大小为m,响应图大小为w×h,则作BN的数据量为m×w×h。
BN在深层神经网络的做用很是明显:若神经网络训练时遇到收敛速度较慢,或者“梯度爆炸”等没法训练的状况发生时均可以尝试用BN来解决。同时,常规使用状况下一样能够加入BN来加速模型训练,甚至提高模型精度。