【深度学习】批归一化(Batch Normalization)

参考:深度学习归一化

BN是由Google于2015年提出,这是一个深度神经网络训练的技巧,它不仅可以加快了模型的收敛速度,而且更重要的是在一定程度缓解了深层网络中“梯度弥散”的问题,从而使得训练深层网络模型更加容易和稳定。所以目前BN已经成为几乎所有卷积神经网络的标配技巧了。

我们为什么需要BN?

神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低。

在BN出现之前,输入层的数据,已经人为的的归一化(对输入的数据减去均值再除以方差),后面网络每一层的输入数据分布是一直在发生变化的,前面层训练参数的更新将导致后面层输入数据分布的变化,因此必然会引起后面每一层输入数据分布的改变。而且,网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去,使得网络的训练减缓。把网络中间层在训练过程中,数据分布的改变称之为:"Internal Covariate Shift"。BN的提出,就是要解决在训练过程中,中间层数据分布发生改变的情况。

那中间数据层的分布改变是怎么影响我们训练呢?

随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性激活函数的取值区间的上下限两端靠近。假如我们的激活函数为sigmoid函数,sigmoid函数的导数图如下所示,越靠近两边,导致反向传播时低层神经网络的梯度越小,这是训练深层神经网络收敛越来越慢的本质原因。

【深度学习】批归一化(Batch Normalization)_第1张图片

因此,我们可以在网络中任意一层进行归一化处理,因为我们现在所用的优化方法大多都是min-batch SGD,所以我们的归一化操作就成为Batch Normalization。

BN基本原理

通过上面的叙述,我们自然而然地都可以想到把神经元的分布拉回来,BN做的就是这个工作。把每一层的每一个神经元分布强行拉回到均值为0方差为1的标准正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。

但是很明显,看到这里,稍微了解神经网络的读者一般会提出一个疑问:如果都通过BN,那么不就跟把非线性函数替换成线性函数效果相同了?这意味着什么?我们知道,如果是多层的线性函数变换其实这个深层是没有意义的,因为多层线性网络跟一层线性网络是等价的。这意味着网络的表达能力下降了,这也意味着深度的意义就没有了。所以BN为了保证非线性的获得,对变换后的满足均值为0方差为1的x又进行了scale加上shift操作(y=scale*x+shift),每个神经元增加了两个参数scale和shift参数,这两个参数是通过训练学习到的,意思是通过scale和shift把这个值从标准正态分布左移或者右移一点并长胖一点或者变瘦一点,每个实例挪动的程度不一样,这样等价于非线性函数的值从正中心周围的线性区往非线性区动了动。核心思想应该是想找到一个线性和非线性的较好平衡点,既能享受非线性的较强表达能力的好处,又避免太靠非线性区两头使得网络收敛速度太慢。

总结一下就是,对于每一个神经元x,BN先把它拉回到均值为0方差为1的标准正态分布\hat{x},然后为了增加非线性要素,在增加scale和shift操作y=scale*\hat{x}+shift。

【深度学习】批归一化(Batch Normalization)_第2张图片

 

BN步骤

通过上面的学习,我们知道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,于是对于每个特征图都只有一对可学习参数:γ、β。

说白了吧,这就是相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,然后对这个特征图神经元做归一化

【深度学习】批归一化(Batch Normalization)_第3张图片

如上图所示,BN步骤主要分为4步:

1、求每一个训练批次数据的均值

2、求每一个训练批次数据的方差

3、使用求得的均值和方差对该批次的训练数据做归一化,获得0-1分布。其中ε是为了避免除数为0时所使用的微小4、正数。

4、尺度变换和偏移:将x_{i}乘以\gamma调整数值大小,再加上\beta增加偏移后得到y_{i},这里的\gamma是尺度因子,\beta是平移因子。这一步是BN的精髓,由于归一化后的x_{i}基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,我们引入两个新的参数:\gamma,\beta\gamma\beta是在训练时网络自己学习得到的。

BN到底解决了什么? 

一个标准的归一化步骤就是减均值除方差,那这种归一化操作有什么作用呢?我们观察下图,

【深度学习】批归一化(Batch Normalization)_第4张图片

【深度学习】批归一化(Batch Normalization)_第5张图片

a中左图是没有经过任何处理的输入数据,曲线是sigmoid函数,如果数据在梯度很小的区域,那么学习率就会很慢甚至陷入长时间的停滞。减均值除方差后,数据就被移到中心区域如右图所示,对于大多数激活函数而言,这个区域的梯度都是最大的或者是有梯度的(比如ReLU),这可以看做是一种对抗梯度消失的有效手段。对于一层如此,如果对于每一层数据都那么做的话,数据的分布总是在随着变化敏感的区域,相当于不用考虑数据分布变化了,这样训练起来更有效率。

那么为什么要有第4步,不是仅使用减均值除方差操作就能获得目的效果吗?我们思考一个问题,减均值除方差得到的分布是正态分布,我们能否认为正态分布就是最好或最能体现我们训练样本的特征分布呢?不能,比如数据本身就很不对称,或者激活函数未必是对方差为1的数据最好的效果,比如Sigmoid激活函数,在-1~1之间的梯度变化不大,那么非线性变换的作用就不能很好的体现,换言之就是,减均值除方差操作后可能会削弱网络的性能!针对该情况,在前面三步之后加入第4步完成真正的batch normalization。

BN的本质就是利用优化变一下方差大小和均值位置,使得新的分布更切合数据的真实分布,保证模型的非线性表达能力。BN的极端的情况就是这两个参数等于mini-batch的均值和方差,那么经过batch normalization之后的数据和输入完全一样,当然一般的情况是不同的。

BN的优点

  1. 不仅仅极大提升了训练速度,收敛过程大大加快;
  2. 还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果;
  3. 另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。

你可能感兴趣的:(深度学习)