Batch Normalization论文笔记
个人博客:http://www.chenjianqu.com/
原文链接:http://www.chenjianqu.com/show-70.html
论文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. Sergey Ioffe, Christian Szegedy
素质三连
1.论文贡献
提出Batch Normalization,消除了Internal covariate shift的影响,加快了网络的收敛速度。
2.实验结果
在GoogLeNet中加入BN,达到原模型的精度少了14trainning steps。在imagenet上达到4.9%的top-5错误率,超越人类水平。
3.存在的问题
稍微多了一点点计算量。
模型提出
Internal Covariate Shift
随机梯度下降(SGD)的目标是最小化损失函数:
上式中的X1…XN是分别是大小为m的mini-batch,mini-batch用来估计损失函数对参数的梯度:
使用mini-batch的优点:
A.如果一次计算整个训练集的梯度,其计算量无法接受。因此使用mini-batch的梯度用来估计整个训练集的梯度,而且mini-batch的越大越能代表训练集。
B.当前的计算机硬件都可以并行计算,因此使用大小为m的mini-batch要比单独m个样本计算要高效。
使用sgd训练时需要仔细调整模型的超参数,尤其是学习率和参数的初始化。神经网络每一层的输入受前面所有层影响,随着网络变得更深,参数的微小变化会被放大,这使得训练变得更加复杂。网络层的输入数据分布变化会带来问题:层需要不断适应新的分布。当一个学习系统的输入分布变化时,被称为covariate shift,通常采用域适应[论文:A literature survey on domain adaptation of statistical classifiers]来解决这个问题。
考虑网络计算:
设F1、F2是**函数,theta1、theta2是参数,L是损失函数。令x=F1(u,theta1),则L=F2(x, theta2),则theta2的参数更新为:
m是batch_size,alpha是学习率。像上面的例子中,theta2不得不重新适应x分布的改变。但如果我们将每层的输入分布固定,不仅有利于当前层的训练,而且对后面层也是有益的。
作者把训练过程中,深层网络内部节点分布的变化称为内部协变量移位(internal covariate shift)。
Batch Normalization的优点
论文提出Batch Normalization来解决internal covariate shift,还附带很多好处:
1.BN可以减少internal covariate shift,使得模型的训练大大加速。
2.BN归一化输入batch到固定的均值和方差,BN还有利于网络中梯度的流动,它减小了梯度对参数和初始值的依赖。
3.BN让我们可以使用更高的学习率,而不同担心网络会发散。
4.BN可以作为正则化器,减小dropout的使用。
5.BN的加入,让模型可以使用饱和非线性函数。
白化减小Internal Covariate Shift
总所周知,如果输入数据白化后网络能收敛的更快。白化:将数据线性变换为均值为0,方差为1,去相关的数据。而Internal Covariate Shift定义为由于网络参数变化引起的网络**值分布的改变。那么如果可以对每一层的输入进行白化,这样就固定每层的输入数据分布,从而减小internal covariate shift。
而要对每层的输入进行白化,要么直接修改网络,要么根据网络**值改变优化算法的参数。这些修改如果和参数优化步骤穿插在一起,那么sgd会尝试以一种需要更新归一化的方式更新参数,这样就减小了sgd的作用。举个例子:
u是输入数据,需要优化的参数是b,x=u+b,x通过减去均值来归一化,且E(x)是batch x的均值。如果梯度下降时无视E(x)对b的依赖,则进行参数更新:
那么当下一个batch输入时:
可以看到,层的输出值没变,那么loss也不变,也就是说整个网络没有被优化。随着训练的进行,b会增加逐渐到inf,但是loss仍然不会减少。出现这个问题的原因是梯度下降没有考虑到归一化,为了解决这个问题,我们希望确保对于任何参数值,网络总是生成具有所需分布的**。
令x为当前层输入,chi是数据集所有的数据,归一化可以写作:x_=Norm(x, chi)。也就是说归一化后的数据不仅依赖于当前输入,而且依赖所有的数据。反向传播时,需要计算雅可比矩阵:
忽略上面的右项将导致前面的参数爆炸问题,但是使用上面的公式计算代价是昂贵的,需要计算协方差矩阵和它的逆矩阵平方根:
和
以及这些变换的导数。需要找一个替代的方式执行输入归一化,要求可微而且不需要计算整个训练集。
使用BN代替白化
每一层全白化台昂贵了而且不可微,因此需要进行两个简化:
1.首先,不需要对层输入和输出的特征进行联合白化,而是通过使其均值为0,方差为1来独立地对每个标量特征进行归一化。x为输入,则归一化为:
这样的归一化可以加快网络的收敛速度,但这么简单的归一化可能会改变网络层的表示。比如:对一个sigmoid**函数的输入进行归一化会将其约束到非线性的线性状态。为了解决这个问题,需要保证the transformation inserted in the network can represent the identity transform。 因此引入了两个参数lambda和beta,为缩放参数和平移参数,公式如下:
这两个参数和网络一起学习,用于恢复网络的表示能力。
而当和
时,上式等价于无参数归一化的情况。
2.在1.中提到,每个训练步基于整个数据集,即使用整个数据集归一化**,这是不切实际的。因此做第二个简化:因为使用sgd优化,因此使用每个mini-batch产生整体均值和方差的估计。注意mini-batches计算每一维的方差而不是联合协方差;在联合的情况下,将需要正则化,因为小批处理的大小可能小于正在漂白的**数,从而导致奇异协方差矩阵。
上面1.和2.就是BN算法,具体过程如下:
其中加上一个很小的系数是防止方差为0。
BN变换并不是独立地处理每个训练样本,相反BN变换依赖mini-batch中的其它样本。上面的步骤中经过归一化后的batch是均值为0方差为1的数据(忽略那个小常量)。后面再接一个缩放和平移的线性变换层,以保证网络的分布不变。尽管这些经过BN层的数据分布在训练期间还是会被改变,但是我们期望归一化的引入能加入网络的收敛。
反向传播更新参数:
从上面可以看到,BN变换是可微的。这确保了训练时,网络层可以继续学习输入分布,从而减少internal covariate shift,加速网络的训练。此外,可学习的仿射变换应用在归一化**函数允许BN变换表示恒等变换,保留了网络的容量。
在网络中使用BN
在网络中**函数的前使用BN层。**的归一化在训练时是有效的,但是推断时既无必要也不可行。推断时我们希望输出仅仅依赖于输入。所以,推断时,我们使用如下的归一化:
上式的均值是训练过程中mini-batches的均值的均值,方差来源如下,使用无偏估计:
公式中的均值是训练过程中所有mini-batches的方差的均值。由于在推理过程中均值和方差是固定的,因此BN只是对每个**应用一个线性变换。因此可以进一步简单,用一个线性变换代替BN。
下面是训练一个BN网络的流程:
在卷积神经网络中使用BN
设某层神经网络可表示为:z=g(Wu+b),其中W是参数,u是输入,b是偏置,g(x)是非线性**函数。我们可以应用BN变换在里面,其中b可以去掉 因为后面归一化会减掉,因此得公式:z=g(BN(Wu))
对于卷积层,我们还希望BN遵循卷积的特性:在不同的位置,相同feature map的不同元素就会以相同的方式归一化。
发现使用BN后学习率可以放大
在传统的深度学习网络中,太高的学习率会导致梯度消失或梯度爆炸,或陷入局部最小值。使用BN层,可以防止参数的微小变化在深层网络被放大。BN层也使得训练对参数的scale更有弹性。一般来说,越大的学习率,参数的scale越大,使得反向传播的梯度变大导致梯度爆炸。然而使用BN之后,反向传播的梯度不受参数scale的影响。对于一个scalar a:BN(Wu)=BN((aW)u),对该式求梯度:
scale不影响层的雅可比矩阵,也不影响梯度传播。而且,权值越大,梯度越小,BN可以稳定参数的增长。我们进一步推测,BN可能导致层雅可比矩阵的奇异值接近1,这对训练是有益的。
发现BN有正则化作用
作者发现使用BN后,Dropout可以去掉。
实验
对比实验
为了验证internal covariate shift对训练的影响,以及BN层的效果,作者使用一个简单的网络在MNIST数据集上训练,模型细节为:28x28的输入,三层100个**的全连接隐层,使用sigmoid**函数,使用高斯随机初始化权重。输出10个分类,使用交叉熵损失。训练50000步,batch_size=60。设置添加了BN的对照组,下面展示测试结果:
上图a显示bn能加快收敛速度,图bc显示:对于每个网络的最后一个隐层的一个典型**,我们展示了它的分布是如何演变的。原始网络中分布的均值和方差随时间变化很大,这使后续层的训练变得复杂。相比之下,随训练的进行,批处理规范化网络中的分布更加稳定,这有助于训练的进行。
GoogLeNet加入BN
作者在Inception网络、ImageNet上进行对比测试。使用的架构如下:
网络使用带动量的SGD训练,batch_size=32。
跟原来的Inception相比,不同的地方在于原来的5x5卷积核被替换为两个3x3卷积串联,这一点参考了VGGNet。除此之外,还对网络进行了如下改进:
增加BN层
增加学习率
移除dropout
减小L2增加化衰减,原来的系数除以5
加快学习率衰减,比从前快6倍。
去除LRN层
更加测底的shuffle。使用within-shard shuffe,防止相同的样本出现在同一个mini-batch。这符合BN作为一个正则化器的观点: the randomization inherent in our method should be most beneficial when it affects an example differently each time it is seen (这句没看懂)
减小光度失真。因为BN的网络训练速度更快,观察每个训练样本的次数更少,所以我们让训练器通过较少的失真来关注更多的“真实”图像。
最后模型在LSVRC2012上训练和测试。设置了如下对照组:
Inception:未加BN的Inception ,学习率:0.0015
BN-Baseline: 在Inception的每个**函数前加入BN
BN-x5:在Inception的每个**函数前加入BN,而且像上面说的一样修改一些地方。学习率为0.0075
BN-x30:跟BN-x5差不多,但是学习率为0.045
BN-x5-Sigmoid:跟BN-x5差不多,但是使用Sigmoid替代ReLU。
下图是训练结果:
由上可知,加入BN会大幅加快收敛速度,有趣的是,学习率太大反而会减慢收敛速度,但是能达到更高的精度。上面还设置了sigmoid替换relu的对照组,用于测试internal covariate shift是否有所改善,结果是大大消除了ICS。
使用集成模型
集成模型达到SOTA。