您的位置:首页 > 其它

深度学习中的BatchNormalization理解

2018-03-26 10:06 316 查看
参考资料:

- 深度学习中 Batch Normalization为什么效果好?

- 斯坦福CS231 Lecture6

- Batch Normalization 学习笔记

各种讲解深度学习的课程、博客中都会强调BN(Batch Normalization)的优点和重要性,于是仔细研读了一下各种资料,发现其思想并不复杂。虽然在实际中还没有体会过它的作用。。希望有机会可以尝试一下。

Batch Normalization是在2015的一篇论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中提出的。论文中阐述了其优点:

优点

可以选择比较大的初始学习率,让你的训练速度飙涨。即使你选择了较小的学习率,也比以前的收敛速度快,因为它具有快速训练收敛的特性。

如果每层的scale不一致,实际上每层需要的学习率是不一样的,同一层不同维度的scale往往也需要不同大小的学习率,通常需要使用最小的那个学习率才能保证损失函数有效下降,BN将每层、每维的scale保持一致,那么我们就可以直接使用较高的学习率进行优化。

移除或使用较低的dropout,因为BN具有提高网络泛化能力的特性。dropout是常用的防止overfitting的方法,而导致overfit的位置往往在数据边界处,如果初始化权重就已经落在数据内部,overfit现象就可以得到一定的缓解。

降低L2权重衰减系数。同上,边界处的局部最优往往有几维的权重(斜率)较大,使用L2衰减可以缓解这一问题,现在用了Batch Normalization,就可以把这个值降低了,论文中降低为原来的5倍。

不再需要使用使用局部响应归化层Local Response Normalization(局部响应归一化是Alexnet网络用到的方法),因为BN本身就是一个归一化网络层;

减少图像扭曲的使用。由于现在训练epoch数降低,所以要对输入数据少做一些扭曲,让神经网络多看看真实的数据。

为什么提出BN

在神经网络训练开始前,都要对输入数据做一个归一化处理,那么具体为什么需要归一化呢?归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同,那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

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

我们知道网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算得到的,而第一层的参数在整个训练过程中一直在变化,因此必然会引起后面每一层输入数据分布的改变。我们把网络中间层在训练过程中,数据分布的改变称之为:“Internal Covariate Shift”。Paper所提出的算法,就是要解决在训练过程中,中间层数据分布发生改变的情况。

BN说到底还是为了防止“梯度弥散”。关于梯度弥散,大家都知道一个简单的栗子:

。在BN中,是通过将activation规范为均值和方差一致的手段使得原本会减小的activation的scale变大。可以说是一种更有效的local response normalization方法

BN是什么

就像激活函数层、卷积层、全连接层、池化层一样,BN也属于网络的一层。在前面我们提到网络除了输出层外,其它层因为低层网络在训练的时候更新了参数,而引起后面层输入数据分布的变化。这个时候我们可能就会想,如果在每一层输入的时候,再加个预处理操作那该有多好啊,比如网络第三层输入数据,把它归一化至:均值0、方差为1,然后再输入第三层计算,这样我们就可以解决前面所提到的“Internal Covariate Shift”的问题了。

而事实上,paper的算法本质原理就是这样:在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。不过文
a4f0
献归一化层,可不像我们想象的那么简单,它是一个可学习、有参数的网络层。



传统的神经网络,只是在将样本x输入输入层之前对x进行标准化处理(减均值,除标准差),以降低样本间的差异性



BN是在此基础上,不仅仅只对输入层的输入数据

x进行标准化,还对每个隐藏层的输入进行标准化。

BN算法实现

一般的归一化操作(z-score):



如果是仅仅使用上面的归一化公式,对网络某一层A的输出数据做归一化,然后送入网络下一层B,这样做会将数据分布限制在正态分布下,是会影响到本层网络A所学习到的特征的。打个比方,比如我网络中间某一层学习到特征数据本身就分布在S型激活函数的两侧,你强制把它给我归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,这样就相当于我这一层网络所学习到的特征分布被你搞坏了,这可怎么办?于是文献提出了一种方法:变换重构,引入了可学习参数γ、β,这就是算法关键之处:



每一个神经元xk都会有一对这样的参数γ、β。这样其实当:





是可以恢复出原始的某一层所学到的特征的。因此我们引入了这个可学习重构参数γ、β,让我们的网络可以学习恢复出原始网络所要学习的特征分布。最后Batch Normalization网络层的前向传导过程公式就是:



上面的公式中m指的是mini-batch size。

BN的实际应用

上述算法应用于训练阶段,而在测试阶段是一个样本一个样本输入的,没有了min-batch这个概念。那么这时上面的均值u、标准差σ 要哪里来?只能使用训练数据来估计了。



即对于均值来说直接计算所有batch u值的平均值;然后对于标准偏差采用每个batch σB的无偏估计。最后测试阶段,BN使用的公式就是:



根据文献说,BN可以应用于一个神经网络的任何神经元上。文献主要是把BN变换,置于网络激活函数层的前面。在没有采用BN的时候,激活函数层是这样的:

z=g(Wu+b)

也就是我们希望一个激活函数,比如s型函数s(x)的自变量x是经过BN处理后的结果。因此前向传导的计算公式就应该是:

z=g(BN(Wu+b))

其实因为偏置参数b经过BN层后其实是没有用的,最后也会被均值归一化,当然BN层后面还有个β参数作为偏置项,所以b这个参数就可以不用了。因此最后把BN层+激活函数层就变成了:

z=g(BN(Wu))

什么时候用BN比较好?例如,在神经网络训练时遇到收敛速度很慢,或梯度爆炸等无法训练的状况时可以尝试BN来解决。另外,在一般使用情况下也可以加入BN来加快训练速度,提高模型精度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐