深度学习中的Batch Normalization


关注微信公众号【Microstrong】,我现在研究方向是机器学习、深度学习,分享我在学习过程中的读书笔记!一起来学习,一起来交流,一起来进步吧!


本文同步更新在我的微信公众号中,公众号文章地址:https://mp.weixin.qq.com/s/o_Gwa11BauT60U7S1--3fQ

本文同步更新在我的知乎中:

深度学习中的Batch Normalization - Microstrong的文章 - 知乎https://zhuanlan.zhihu.com/p/36222443


1.为什么需要Batch Normalization

Batch Normalization就是在神经网络的训练过程中对每层的输入数据进行预处理。对输入数据预处理方法有很多,比如常用Z-score、白化等。

1.1 传统神经网络如何使用Normalization

传统的神经网络中,只是在输入层之前或在输出层之后对 x 进行标准化处理(减去均值,除标准差),让数据处于均值为0、方差为1的分布中,以降低样本间的差异性。过程如图1所示。


图1:传统网络的Normalization

思考一个问题:为什么传统的神经网络在训练开始之前,要对输入的数据做Normalization?

原因在于神经网络学习过程本质上是为了学习数据的分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另一方面,一旦在mini-batch梯度下降训练的时候,每批训练数据的分布不相同,那么网络就要在每次迭代的时候去学习以适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对所有训练数据做一个Normalization预处理的原因。

那么传统神经网络中使用Normalization的缺点是什么呢?

对于深度网络的训练是一个复杂的过程,只要网络的前面几层参数发生微小的改变,那么后面几层网络就会被积累放大发生更大的变动。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练数据的分布发生变化,那么将会影响网络的训练速度。

1.2 白化预处理

在论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中,算法的本质原理是:在网络的每一层输入的时候,插入一个Normalization层,就是先对输入的数据做一个归一化处理,然后再进入下一层网络中。加入的这些Normalization层,可不像我们想象的那么简单,它们一个个是可学习、有参数的网络层。

说到神经网络输入数据预处理,最强的预处理算法肯定是白化(whitening)预处理。然而白化计算量太大,不是处处可微,所以在深度学习中,我们不能在每层加入白化。白化预处理一般包含两个目的:

(1)除去数据特征之间的相关性。(特征之间独立

(2)使得所有数据的特征具有相同的均值和方差。(特征数据同分布

白化比较经典的算法是PCA白化、ZCA白化。

1.3 深度学习中的Internal Covariate Shift

深度神经网络模型的训练为什么会很困难?其中一个重要的原因是,深度神经网络涉及到很多层的叠加,而每一层的参数更新会导致后面层的输入数据分布发生变化,数据通过层层叠加的网络,靠近输出层的隐层网络输入分布变化会非常的剧烈,这就使得靠近输出层的隐层网络需要不断的去重新适应前面层的参数更新。举个例子:网络的第二层输入是由第一层的参数和输入计算得到的,而第一层的参数在整个训练过程中一直在变化,因此势必会引起后面每一层输入数据分布的改变。我们把在深度神经网络训练过程中,中间层数据分布发生改变的情况称之为"Internal Covariate Shift"。而这篇论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》所提出的算法,就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了Batch Normalization算法。

1.4 Internal Covariate Shift导致的问题

简而言之,每个神经元的输入数据不再是"独立同分布"。

其一,靠近输出层的隐含层网络的参数需要不断适应新的输入数据分布,降低学习速度。

其二,靠近输入层的隐含层网络的参数变化可能趋向于变大或者变小,导致后面的网络层落入激活函数的饱和区,使得学习过早停止。

其三,每层的参数更新都会影响到其他层,因此每层的参数更新策略需要尽可能的谨慎。

2. 详细介绍Batch Normalization

2.1 什么是Batch Normalization?


图2:论文中给出的Batch Normalization算法

经过前面的介绍,你也许会想:不就是在网络中间层的数据做一次归一化处理么,这么简单的方法,为什么之前没有人提出来呢?其实实现起来没有那么容易的,要是那么容易大家都发顶会论文啦!如果仅仅使用减去均值除标准差的规一化方法,对网络某一层A的输出数据做归一化,然后送到网络下一层B中,这样会影响本层网络A所学到的特征。举个例子:比如网络中间某一层学习到特征数据分布在S型激活函数的两侧,我们强制把它归一化处理到均值为0方差为1分布中,把数据变换到分布于S型函数的中间部分,这样就相当于这一层网络所学到的特征被搞坏了。于是Batch Normalization中最厉害的方法出来了:变换重构。变换重构是为了让因训练所需而刻意加入的Normalization能够有可能还原到最初的输入。这一方法引入了学习参数γ、β,公式(1)是BN算法关键之处。

(1)

每一个神经元都会有一对这样的参数γ、β。其实当满足公式(2)的时候,是可以恢复出原始的某一层所学到的特征。因此我们引入了这两个可学习重构参数γ、β,让我们的网络可以恢复出原始网络所要学习的特征分布。

(2)

如果你对图2中的Batch Normalization算法还是不清楚,我再给大家来个更通俗易懂的。下面,我们来走一遍Batch Normalization网络层的前向传播过程。设每个batch输入是x=\left[ x_{0},x_{1},x_{2},...,x_{n} \right] (其中每个 x_{i} 都是一个样本,n 是batch size)。假如在第一层后加入Batch Normalization Layer后,h_{1} 的计算就被替换为图3所示的过程。


图3:Batch Normalization的算法

(1)矩阵 x 先经过W_{h_1} 的线性变换后得到s_1

:因为减去batch的平均值\mu_B 后,b 的作用会被抵消掉,所以没必要加入b (红色删除线)。

(2)将 s_1 再减去batch的平均值\mu_B ,并除以batch的标准差\sqrt{\sigma_B+\epsilon} 得到s_2\epsilon 是为了避免除数为0的情况所使用的微小正数。

\mu_B=\frac {1}{m} \sum^m_{i=0}W_{h_1}x_{i,:}

\sigma^2_B=\frac {1}{m} \sum^m_{i=0}(W_{h_1}x_{i,:}-\mu_B)^2

:但s_2 基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,引入两个新的parameters:\gamma\beta\gamma\beta 是在训练时网络自己学习得到的。

(3)将 s_1 乘以\gamma 调整数值大小,再加上\beta 增加偏移后得到s_3

(4)为加入非线性能力, s_3 也会当作ReLU等激活函数的输入,最终得到的h_1 会被送到下一层作为输入。

需要注意的是,上述的计算方法用于在训练中。因为测试时经常会只预测一个新样本,也就是说batch size为1。若还用相同的方法计算\mu_B\mu_B 就会是这个新样本自身,s_1-\mu_B 就会成为0。所以在测试时,所使用的\mu\sigma^2整个训练集的均值\mu_P 和方差\sigma^2_P 。而整个训练集的均值\mu_P和方差\sigma^2_P 的值通常也是在训练的同时用移动平均法来计算。

这一部分参考:YJango的Batch Normalization--介绍 - YJango的文章 - //zhuanlan.zhihu.com/p/27938792

2.2 如何学习Batch Normalization中的参数?

学习Batch Normalization中的参数,通过反向传播中的链式法则。计算公式如图4所示。


图4:反向传播学习参数

2.3 Batch Normalization用在网络的哪里?

根据论文中说,BN可以应用于一个神经网络的任何神经元上。论文中指出把BN置于网络激活函数的前面。在没有采用BN的时候,激活函数层是公式(3)。采用BN的时候,前向传播的计算公式是(4)。因为偏置参数b经过BN层后其实是没什么用的,最后也会被均值归一化,当然BN层后面还有个β参数作为偏置项,b的作用就会被抵消掉了。因此最后把BN层和激活函数层就变成了公式(5)。

z=g\left( W_{u}+b \right) (3)

z=g\left(BN\left( W_{u}+b\right) \right) (4)

z=g\left(BN\left( W_{u}\right) \right) (5)

2.4 BN算法在CNN中的应用

BN算法在CNN中往往放在每个卷积层之后,ReLU操作之前。在CNN中使用BN是把每个特征图看做一个神经元,计算该特征图对应数据的均值和方差进行归一化,并且每个特征图对应两个学习变量γ、β。想具体了解BN在CNN中的使用方法,可以详细看一下深度学习(二十九)Batch Normalization 学习笔记 - CSDN博客这篇文章。

3. Batch Normalization的优点

(1)可以使用更高的学习率,BN有快速收敛的特性。在没有加Batch Normalization的网络中我们要慢慢的调整学习率时,甚至在网络训练到一半的时候,还需要想着学习率进一步调小的比例选择多少比较合适。现在,我们在网络中加入Batch Normalization时,可以采用初始化很大的学习率,然后学习率衰减速度也很大,因此这个算法收敛很快。

(2)模型中BN可以代替dropout或者使用较低的dropout。dropout是经常用来防止过拟合的方法,但是模型中加入BN减少dropout,可以大大提高模型训练速度,提高网络泛化性能。

(3)减少L2权重衰减系数。用了Batch Normalization后,可以把L2权重衰减系数降低,论文中降低为原来的5倍。

(4)取消Loacl Response Normalization层。(局部响应归一化是Alexnet网络用到的方法),因为BN本身就是一个归一化网络层。

(5)BN本质上解决了反向传播过程中梯度消失的问题。BN算法对Sigmoid激活函数的提升非常明显,解决了困扰学术界十几年的sigmoid过饱和造成梯度消失的问题。在深度神经网络中,靠近输入的网络层在梯度下降的时候,得到梯度值太小,导致深层神经网络只有靠近输出层的那几层网络在学习。因为数据使用BN后,归一化的数据仅使用了sigmoid线性的部分。

(6)可以把训练数据彻底打乱。防止了每批训练的时候,某一个样本经常被挑选到。论文中指出这个操作可以提高1%的精度。

个人总结:自从Google在2015年提出Batch Normalization方法优化深度神经网络之后,BN就成为深度学习中重要的优化方法。并且,自Batch Normalization提出之后,又有许多基于BN改进的优化方法:Layer Normalization、Weight Normalization、Cosine Normalization。这些优化深度神经网络模型训练的方法,也成为面试中经常被问到的题目。

Reference:

(1)Ioffe S, Szegedy C. Batch normalization: Accelerating deep network training by reducing internal covariate shift[J]. arXiv preprint arXiv:1502.03167, 2015.

(2)详解深度学习中的Normalization,不只是BN - Juliuszh的文章 - //zhuanlan.zhihu.com/p/33173246

(3)YJango的Batch Normalization--介绍 - YJango的文章 - //zhuanlan.zhihu.com/p/27938792

(4)深度学习中 Batch Normalization为什么效果好? - zhihu.com/question/3810

(5)深度学习(二十九)Batch Normalization 学习笔记 - CSDN博客

(6)《Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift》阅读笔记与实现


猜你喜欢

转载自blog.csdn.net/program_developer/article/details/80143470