我读Batch Normalization

来源:互联网 发布:java开发常用工具 编辑:程序博客网 时间:2024/06/05 07:59

论文地址:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
论文代码:GitHub

0. 背景

从标题中我们就可以看出,本文是通过 Batch Normalization 来 Reducing Internal Covariate Shift 加速神经网络训练。在上篇博客《我读ResidualNet》里作者使用了 BN 训练而且去掉了 dropout,而 dropout 是自从 AlexNet 就被大家广泛使用的避免过拟合的方法,从这点我们可以变相的知道 BN 的牛逼之处。那 BN 究竟解决了什么问题,他的原理和具体方法是什么?

1. 问题

  • 神经网络每层输入的分布总是发生变化,不利于拟合,训练速度慢
  • 激活函数在某个输入区间很容易达到饱和状态,导致 gradient vanishing 问题,训练速度慢
  • learning rate 较低,训练速度慢

2. 贡献

  • 减少神经网络每层输入的分布变化,加快训练速度
  • 降低激活函数达到饱和状态概率,避免 gradient vanishing 问题,加快训练速度
  • learning rate 提高,加快训练速度
  • 类似正则项,某些程度可以替代 dropout
  • BN-inceptionv1 较原 googlenet,训练期间快了 14 倍达到相同训练误差,在 Imagenet 分类问题的 top5 上达到 4.8%,超过了人类标注 top5 准确率

3. 原理

在 AlexNet 时就已经通过实验证明,预处理过的图像会比原始图像训练快上很多。常见的预处理如白化(whitening)、PCA 等,不过计算协方差矩阵的特征值太耗时也太耗空间,AlexNet 只是对所有输入相同位置像素 normalize 处理。本文将初始化输入图像泛化成对每一层的输入做初始化,达到加速效果。为什么每层输入,初始化之后训练速度会变快?
从人脑神经学的角度,神经网络与大脑皮层接受视觉信号有很多相似的地方,网络的每一层神经元可以响应不同 level 的信号,如第一层的神经元可能响应边角,第二层神经元响应三角形/矩形,随着层数的加深,神经元响应的复杂程度逐渐加深。也就是说每个神经元只对某种输入有响应,而神经系统的最终结果就是确认这一系列的响应,进而对图像分类等操作。
加入每次迭代当中,训练某神经元的输入分布一直变化,我们可以理解为这个神经元响应的复杂程度不变,但是响应对象是变化的。比如这次响应的是个三角形,下次迭代又要响应四边形,降低了收敛速度。这种输入分布变化在原始的神经网络中是一直存在的,神经元的输入受所有浅层神经元影响。作者提出了一种批规范化(Batch Normalization,BN)方法,对每个神经元的输出规范化,即均值为 0,方差为 1,之后再进入激活函数。
这样做有两个好处,

  • 第一个好处就如上面所讲,每个神经元的输入分布相同了,加快了训练速度
  • 第二个好处是避免了 gradient vanishing

如何避免梯度消失的呢,众所周知 sigmoid 激活函数在两边的梯度变化极小,bp 算法求梯度的话很容易落入这个梯度极小的区间,所以最初几层在 bp 过程变化很慢,训练速度自然就低。每一层规范化后,极大地概率会落在靠近中心的区间,如 [-1, 1],这时的梯度变化很大,bp 过程中浅层学习速度也很快,提高了训练速度。
sigmoid
图片来源1

但是这样做又有一个缺点,可以看到上图 sigmoid 激活函数,[-1, 1] 这段区间近似直线,也就是激活函数变成了线性的,所以整个网络绝大多数就都是线性表达,降低了神经网络的表达能力。所以作者又再次引入了两个变量,对规范化后的神经元输出做了一次线性映射,参数也是可以学习的,使得最终输出落在非线性区间的概率大一些。这样就在 sigmoid 函数梯度小和线性变化之间做了一个平衡,使得神经网络在保证学习能力的基础上,加快训练速度。

4. 实现

既然是批规范化,那么使用的肯定是 mini-batch 方式训练数据,相比于每次迭代使用 1 个样本有两点好处,loss function 是对整个训练样本的近似,并且这种近似随着 batch_size 的增大而越来越像。第二个是并行带来的速度提升。
首先是在 forward 阶段计算方法,针对某一个神经元,在经过 Wx+b 计算后有输出 x,在一个 batch 当中就是一系列的输出 {x1,x2,...,xm},按照之前的神经网络,接下来应该是计算 sigmoid 激活函数的输出值,bn 在这中间加入了 Normalization 层,具体做法如下:
forword

在 back propagation 阶段还是使用梯度下降算法,更新公式:
bp

在测试阶段怎么办呢,使用全部训练数据的均值作为均值,以及全部训练数据的无偏估计量作为方差。
test

在 conv 层当中是每个 feature map 共享一对 γβ,证明了学习率可以调高,并且可以忽略 dropout 层。

5. 实验结果

Activations over time

首先验证收敛速度变快,数据集使用 MINST 手写数字,输入图片为 28x28,3 个全连接隐藏层加 softmax 层,每层 100 个神经元,激活函数为 sigmoid。
result1
图片来源2

上图中a)是 with/without BN 的正确率随迭代次数对比,b)c)为最后一个全连接层某神经元的输出分布。可以看到使用 BN 层收敛速度快,分布相同。

ImageNet Classification

作者又在 ImageNet 数据集合上用有无 BN 层的 GoogLeNet 做了对比,可能是同属 Google,文中使用的是 Inception 而不是 GoogLeNet。
带 BN 的 Inception 网络有如下修改:

  • 增加 learning rate
  • 移除 dropout 层
  • 降低 loss function 权重(1/5)
  • 当发现网络误差平了之后,加快降低 learning rate 的速度
  • 移除 Local Response Normalization
  • 更加彻底的使样本无序,防止一个样本在多个 mini-batch 多次出现
  • 减少光度失真(Reduce the photometric distortions)

resutl2
上图中 BN-Baseline 只在 Inception 中加入了 BN 层,BN-x5 使用上面说的修改,并 5 倍 learning rate,BN-x30 使用了 30 倍 learning rate,BN-x5-Sigmoid 在 BN-x5 基础上使用 Sigmoid 激活函数。可以看到相同达到 72.2% 的准确度,BN-x5 比 Inception 快了 14 倍,并且提高了准确度。
接下来又与其他算法比较了最终准确度,咱忽略不计,因为 BN 可以在任何网络(此时还不支持 rnn)当中使用,加速训练。

6. 结论

这货牛逼,以后用它了


  1. Wikipedia: Sigmoid function ↩
  2. 解读Batch Normalization ↩
1 0
原创粉丝点击