参考:深度学习归一化
BN是由Google于2015年提出,这是一个深度神经网络训练的技巧,它不仅可以加快了模型的收敛速度,而且更重要的是在一定程度缓解了深层网络中“梯度弥散”的问题,从而使得训练深层网络模型更加容易和稳定。所以目前BN已经成为几乎所有卷积神经网络的标配技巧了。
1. 我们为什么需要BN?
1.1 ICS
神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低。
在BN出现之前,输入层的数据已经被人为的归一化了(对输入的数据减去均值再除以方差)。但是伴随着训练,网络每一层的输入数据分布是一直在发生变化的,这种数据分布的变化被称为"Internal Covariate Shift"(ICS)。而且,网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去,因此必然会引起后面一系列层的输入分布均发生非常大的改变,使得网络的训练减缓。BN的提出,就是要解决在训练过程中,中间层数据分布发生改变的情况。
在文章Batch Normalization:Accelerating Deep Network Training by Reducing Internal Covariate Shift中,其对与ICS是这样解释的:由于前一层的参数更新,所以这一层的输入(前一层的输出)的分布会发生变化,这种现象被称之为ICS
1.2 ICS如何影响训练
- 后面层需要不停调整来适应输入数据分布的变化,导致网络学习速度的降低。
前面我们说到伴随着训练(反向传播参数更新),网络每一层的输入数据的分布都会发生变化。后面层就要不停地去适应这种分布变化,这个时候就会使得整个网络的学习速率过慢。
- 网络的训练过程容易陷入梯度饱和区,减缓网络收敛速度。
神经网络层的输出分布逐渐往非线性激活函数的取值区间的上下限两端靠近。假如我们的激活函数为sigmoid函数,越靠近两边,导致反向传播时低层神经网络的梯度越小,这是训练深层神经网络收敛越来越慢的本质原因。
对于激活函数梯度饱和问题,有两种解决思路。第一种就是更为非饱和性激活函数,例如线性整流函数ReLU可以在一定程度上解决训练进入梯度饱和区的问题。另一种思路是,我们可以让激活函数的输入分布保持在一个稳定状态来尽可能避免它们陷入梯度饱和区,这也就是Normalization的思路。
在这里再次引用知乎:
首先BN提出来是为了解决internal covariate shift的(随着神经网络层数的增加,使得每一层的输入的分布在训练过程中发生很大变化)。我理解的每层的输入分布发生变化有两个部分:一是随着训练增加神经网络中某些神经元总是很活跃(这部分神经元之间依赖性很强)而某些却很难激活或是激活值很低,如果总是那一部分神经元激活那就限制了模型的泛化能力。二是,深层次的神经元的输入相比较于前面浅层的神经元更难激活,因为随着前面分布偏移的累积使得后面神经元更难激活,例如输入落入sigmoid激活函数的两端导致梯度消失。
为了解决神经元输入分布偏移的情况,对每个神经元的带权输入(一个mini-batch上)进行标准化,把发生偏移的带权输入拉回到同一分布上。首先这样做解决了上述中第一个分布发生变化的问题,使得每个神经元都会适当的激活,同时标准化使得带权输入分布在0附近更容易激活神经元解决梯度消失问题。但只做标准化容易把之前学习到的特征丢弃掉,这时候就引入了伸缩因子和平移因子(这两个参数是需要学习的),相当于对标准化后的带权输入又做了个线性变换。这样使得所有神经元带权输入都有一个同一的分布,但又保持了相对差异。
由此可以说BN让神经网络中各个神经元的训练更加均衡,也就避免不同参数取值相差很大(想象多项式回归,如果参数取值很大或很小那学习出的曲线震荡幅度很大就容易过拟合而我们希望学习的曲线更平滑)。我觉得这一点和 @xxxddd 说的限制了参数取值空间一样。同时由于每个神经元右保持了相对差异,这样不同神经元之间的依赖性很低,模型也就没有那么复杂了就一定程度避免了过拟合。
2. BN基本原理
通过上面的叙述,我们自然而然地都可以想到把每一层输出分布拉回来,BN做的就是这个工作。通过在每一层后增加BN层(一般在卷积层后,激活层之前,例如conv-bn-relu),把上一层的输出分布强行拉回到均值为0方差为1的标准正态分布,使得非线性变换函数的输入值落入比较敏感的区域,以此避免梯度消失问题。
但是仅仅把输入变换成均值为0,方差为1的标准正态分布还是有缺陷的。因为网络每一层都学习到了数据的特征,如果强行进行标准化处理,那么就会破坏这一层学到的特征。因此,所提出的方法既要避免梯度消失的问题,还要能够在经过规范化处理后让数据尽可能保留原始的表达能力。
为此在标准化的基础上,引入了两个可以学习的参数γ和β,发呢别表示scale和shift,即将学到的特征重新映射回原来的网络所学习到的特征分布,补偿非线性的表达能力。
总结一下就是,对于每一个神经元的输出
,BN先把它拉回到均值为0方差为1的标准正态分布
,然后为了增加非线性要素,在增加scale和shift操作y=scale*
+shift。
3. BN步骤
3.1 训练
通过上面的学习,我们知道BN层是对于每一层的每个神经元做归一化处理,而不是对一整层网络的神经元进行归一化。既然BN是对单个神经元的运算,那么在CNN中卷积层上要怎么搞?假如某一层卷积层有6个特征图,每个特征图的大小是100*100,这样就相当于这一层网络有6*100*100个神经元,如果采用BN,就会有6*100*100个参数γ、β,这样岂不是太恐怖了。因此卷积层上的BN使用,其实也是使用了类似权值共享的策略,把一整张特征图当做一个神经元进行处理。
卷积神经网络经过卷积后得到的是一系列的特征图,如果min-batch sizes为B,那么网络某一层输入数据可以表示为四维矩阵(B,W,H,C),B为min-batch sizes,C为特征图个数,W、H分别为特征图的宽高。在CNN中我们可以把每个特征图看成是一个神经元,因此在使用Batch Normalization,mini-batch size 的大小就是:B*W*H,于是对于每个特征图都只有一对可学习参数:γ、β。
说白了吧,这就是相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,然后对这个特征图神经元做归一化。
如上图所示,BN步骤主要分为4步:
1、求每一个训练批次数据的均值
2、求每一个训练批次数据的方差
3、使用求得的均值和方差对该批次的训练数据做归一化,获得0-1分布。其中ε是为了避免除数为0时所使用的微小4、正数。
4、尺度变换和偏移:将
乘以
调整数值大小,再加上
增加偏移后得到
,这里的
是尺度因子,
是平移因子。这一步是BN的精髓,由于归一化后的
基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,我们引入两个新的参数:
,
。
和
是在训练时网络自己学习得到的。
3.2 测试
先说结论:并不是测试时的mean,var的计算方式与训练时不同,而是测试时的mean,var在训练完成整个网络中就全部固定了。
由于在优化网络的时候,我们一般采用的是batch梯度下降。所以在训练过程中,只能计算当前batch样本上的mean和var。但是我们做的normalization是对于整个输入样本空间,因此需要对每个batch的mean, var做指数加权平均来将batch上的mean和var近似成整个样本空间上的mean和var.
而在测试Inference过程中,一般不必要也不合适去计算测试时的batch的mean和var,比如测试仅对单样本输入进行测试时,这时去计算单样本输入的mean和var是完全没有意义的。因此会直接拿训练过程中对整个样本空间估算的mean和var直接来用。此时对于inference来说,BN就是一个线性变换。
4. BN到底解决了什么?
一个标准的归一化步骤就是减均值除方差,那这种归一化操作有什么作用呢?我们观察下图,
a中左图是没有经过任何处理的输入数据,曲线是sigmoid函数,如果数据在梯度很小的区域,那么学习率就会很慢甚至陷入长时间的停滞。减均值除方差后,数据就被移到中心区域如右图所示,对于大多数激活函数而言,这个区域的梯度都是最大的或者是有梯度的(比如ReLU),这可以看做是一种对抗梯度消失的有效手段。对于一层如此,如果对于每一层数据都那么做的话,数据的分布总是在随着变化敏感的区域,相当于不用考虑数据分布变化了,这样训练起来更有效率。
那么为什么要有第4步,不是仅使用减均值除方差操作就能获得目的效果吗?我们思考一个问题,减均值除方差得到的分布是正态分布,我们能否认为正态分布就是最好或最能体现我们训练样本的特征分布呢?不能,比如数据本身就很不对称,或者激活函数未必是对方差为1的数据最好的效果,比如Sigmoid激活函数,在-1~1之间的梯度变化不大,那么非线性变换的作用就不能很好的体现,换言之就是,减均值除方差操作后可能会削弱网络的性能!针对该情况,在前面三步之后加入第4步完成真正的batch normalization。
BN的本质就是利用优化变一下方差大小和均值位置,使得新的分布更切合数据的真实分布,保证模型的非线性表达能力。BN的极端的情况就是这两个参数等于mini-batch的均值和方差,那么经过batch normalization之后的数据和输入完全一样,当然一般的情况是不同的。
5. BN的优点
-
BN使得网络中每层输入数据的分布相对稳定,加速模型收敛速度;
BN通过规范化与线性变换使得每一层网络的输入数据的均值与方差都在一定范围内,使得后一层网络不必不断去适应底层网络中输入的变化,有利于提高整个神经网络的学习速度。
-
缓解梯度消失何梯度爆炸;
-
缓解过拟合问题;
在Batch Normalization中,由于我们使用mini-batch的均值与方差作为对整体训练样本均值与方差的估计,尽管每一个batch中的数据都是从总体样本中抽样得到,但不同mini-batch的均值与方差会有所不同,这就为网络的学习过程中增加了随机噪音(可以认为是进行了data augmentation)与Dropout通过关闭神经元给网络训练带来噪音类似,在一定程度上对模型起到了正则化的效果。
- 调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率。