Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
关于Batch Normalization的作用和原理,感觉一百篇博文有一百种说法,看得越多怀疑越多,还是自己翻出原文看看吧。
Abstract
训练深度神经网络的困难之处在于:每一层输入的分布会因为前一层参数的变化而不断的发生变化,这一点使得训练网络时需要采用更小的学习率,而且对参数的初始化要求也更高,很难训练具有饱和非线性特性模型(sigmoid)。这一现象作者称之为“internal covariate shift”。
为了解决这一问题,文章采用的方法是:对每一个mini-batch的输入,将网络中每一层的输入做归一化,即Batch normalization, 其优势在于:
- 加速网络训练: 可以使用更大的学习率,缓解梯度消失
- 对参数初始化的要求降低
- 防止过拟合:起到正则化的作用,在某些情况下可以不再使用dropout.
Introduction
mini-batches SGD的优点:
- 损失函数的梯度可作为所以训练数据梯度的近似值,batch越大近似效果越好
- 由于计算平台的平行能力,计算mini-batches比计算m次单个样本的效率更高。
缺点:
- 大量参数的调整:学习率、初始化权重
- 每一层的输入都受到前面层的参数变化的影响,参数很小的变动带来的影响会随着网络层数的加深而被放大。
每一层输入的分布变化带来的问题在于:每一层都需要不断的拟合新的分布。当一个学习系统的输入分布是变化的时,即训练集的样本分布和测试集的样本分布不一致,训练的模型就很难有较好的泛化能力,这叫做 covariate shift (Shimodaira, 2000),解决办法是domain adaptation (Jiang, 2008)。这一概念和可以拓展但系统内部,比如:
其中F1/F2是某一种变化,θ1和θ2是需要学习的参数用来最小化损失L。对θ2的学习可以看做是将F1作为输入的子网络:
当训练一个网络时,良好的输入分布会使得训练更为有效,这一点对子网络也是同样适用的。所以如果输入X的分布保持恒顶,θ2就不需要重新调整以补偿x1分布的变化。
另一方面,固定某一子网络的输入分布也会给其他子网络带来正面效果。考虑sigmoid的特性,当其输入x没有集中在0附近是,梯度会变得特别小,训练缓慢甚至带来梯度消失。而输入x会受到前面其他层的参数的影响,这些参数的改变可能会使得x变化到sigmoid的饱和区域,从而减缓收敛速度,这一效应会随着网络的加深而加剧。
在实际应用中,梯度消失和饱和的问题可以通过使用ReLU、好的初始值和较小的学习率来缓解。但如果我们能够让输入变得稳定,训练也会加快。
为了解决这一问题,提出了BN:
- 通过保持每层输入的均值和方差的稳定,来减弱internal covariate shift和加速训练。
- 通过减弱梯度收到参数即其初值的影响,有利于梯度的反向流动,并能使用更高的学习率。
- 起到正则化的作用,减少了对Dropout的依赖
- BN使得使用饱和非线性时被卡在饱和区域的概率降低。
小结:
- 训练的本质是学习数据分布。如果训练数据与测试数据的分布不同会降低模型的泛化能力。对于子网络而言,因为每个隐层的参数不同,会使下一层的输入发生变化,从而导致每一批数据的分布也发生改变;致使网络在每次迭代中都需要拟合不同的数据分布,增大了网络的训练难度与过拟合的风险。因此,应该在开始训练前对所有输入数据做归一化处理。
- 由于饱和激活函数的特性,参数的变化可能会使得输入变化到激活函数的饱和区, 导致梯度消失。
Towards Reducing Internal Covariate Shift
我们将 Internal Covariate Shift 定义为:在神经网络的训练过程中,由于参数改变,而引起的神经网络激活值分布的改变。通过保持神经网络层输入的分布不变,来提高训练的速度。根据前人的研究((LeCun et al., 1998b; Wiesler & Ney,2011),们已经知道,在训练的过程中加入白化处理能,如0均值1方差化和去相关化,能够加速模型的收敛。通过对每一层的输入进行白化处理,我们能够保持输入的分布,从而消除 Internal Covariate Shift 的病态影响。
通过白化对数据进行变换,可以达到以下两个目的:
- 使得输入特征分布具有相同的均值与方差。其中PCA白化保证了所有特征分布均值为0,方差为1;而ZCA白化则保证了所有特征分布均值为0,方差相同;
- 去除特征之间的相关性。
但是白化操作也具有以下问题:
- 白化过程计算成本太高,并且在每一轮训练中的每一层我们都需要做如此高成本计算的白化操作;
- 白化过程由于改变了网络每一层的分布,因而改变了网络层中本身数据的表达能力。底层网络学习到的参数信息会被白化操作丢失掉。
Normalization via Mini-Batch Statistics
因为对于每一层的输入进行白化花费较高,并且也不是处处可微,所有我们做了两个必要的简化。,一方面,我们提出的normalization方法要能够简化计算过程;另一方面又需要经过规范化处理后让数据尽可能保留原始的表达能力。于是就有了简化+改进版的白化——Batch Normalization。
第一是,我们对特征进行单独的进行零均值一方差归一化,来代替白化同时对层的输入和输出同时进行归一化。于有 d 维输入 x=(x(1)…x(d)),可通过下式进行归一化:
式子中的期望和方差由训练数据集计算得到。此过程可以加速收敛,甚至当特征之间没有相关性的时候也是如此(LeCun et al., 1998b)。
简单的归一化神经网络层的输入,可能会改变该层的表征能力。例如,对 sigmoid 函数的输入进行归一化,会使归一化后的输入趋向 s 型函数的线性端。为了避免这样的情况出现,我们确保穿插在网络内部的变换能够表示同样的变换。为了达到这样的目的,我们对每一个激活值 x(k)都引入一对参数 γ(k)和 β(k) ,这两个参数能够缩放和平移归一化后的输入:
这两个参数与模型原始的参数一起学习,并恢复了模型的表征能力。当γ和β分别等于数据的方差和均值时,就能恢复原来的激活值。
第二是,考虑到在batch的设置中,我们可以用整个训练数据集来归一化激活值。但是,当我们使用随机梯度下降法的时候这一选择是不实际的,在随机梯度下降中我们采用mini-batch的方式,这样我们就能够通过每个mini-batch为每个激活值计算出对应的均值和方差。通过这样的方式,归一化所需统计信息就能够完全被考虑到梯度下降中去。利用mini-batch就能计算每一维激活值的方差,而不是计算所有激活值的协方差矩阵。如果是计算协方差矩阵的话,batch的数量可能比激活值向量的大小还要小,这样就会产生奇异协方差矩阵。
假设有一个mini-batch B,其大小为 m 。因为是对激活值的每一维进行归一化,所有我们只考虑其中的一个激活值 x(k) ,同时在下文中忽略 k。BN的算法结构为:
进行反向传播是,通过链式法则,有:
因此BN变换是将归一化激活值引入神经网络的一种可微变换。这确保了网络可训练性,以及神经网络层能够持续学习输入数据分布。从而能够减少Internal Covariate Shift发生,同时加速网络的训练。进一步的,将学习好的仿射变换应用到归一化激活值中,能够允许BN变换比表示同样的变换,进而保存神经网络的表征能力。
小结:
- BN 方法会针对每一批数据,在网络的每一层输入之前增加归一化处理,使输入的均值为 0,标准差为 1。目的是将数据限制在统一的分布下。
- 具体来说,针对每层的第 k 个神经元,计算这一批数据在第 k 个神经元的均值与标准差,然后将归一化后的值作为该神经元的激活值。
- BN 可以看作在各层之间加入了一个新的计算层,对数据分布进行额外的约束,从而增强模型的泛化能力
- 但同时 BN 也降低了模型的拟合能力,破坏了之前学到的特征分布,为了恢复数据的原始分布,BN 引入了一个重构变换来还原最优的输入数据分布
测试阶段的BN
我们知道BN在每一层计算的均值方差 都是基于当前batch中的训练数据,但是这就带来了一个问题:我们在预测阶段,有可能只需要预测一个样本或很少的样本,没有像训练样本中那么多的数据,此时的均值和方差的计算一定是有偏估计,这个时候我们该如何进行计算呢?
当测试或预测时,每次可能只会传入单个数据,此时我们使用整个样本的统计量来对Test数据进行归一化,具体来说使用均值与方差的无偏估计:
参考: