googLeNet--Inception四部曲二Batch Normalization

来源:互联网 发布:c语言16进制转换2进制 编辑:程序博客网 时间:2024/04/28 22:58

原论文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

作者:Sergey Ioffe,Christian Szegedy

时间:Feb 2015

本文的大部分观点来自于这篇论文,并且加入了一些自己的理解。该博客纯属读书笔记,欢迎吐槽。

mini-batch

使用mini-batch作为训练单位,取代原来的以单个样本作为训练单位的训练方式。文章指出这样做有两个好处。第一,以单个样本作为训练单位,那么损失函数计算得到的误差是不具有代表性的,个体不能代表整体嘛,所以用它计算得到的梯度the gradient of the loss function也是不具有代表性的,很可能通过两个样本计算得到的梯度是差别很大的,这样就会导致参数调整不稳定。而以mini-batch作为训练单位,损失函数计算公式和梯度计算公式分别如下所示。

图1      图2         

可以看到只是简单的求了一下mini-batch中包含的N个样本的损失函数的均值,但是这样得到的数据就很具有代表性了,并且随着包含样本数量的增加,这种效果更加明显 quality improves as the batch size increases。第二点也很重要,computation over a batch can be much more efficient than m computations for individual examples,计算效率提高了啊,随着DNN结构变得越来越复杂,这个优点更加明显。

Internal covariate Shift

文章提到一个词Internal covariate Shift,它是由covariate Shift(变量偏移?)扩展来,我们知道,在机器学习中,合适的样本数据是很重要的,样本分布distributions of samples是否全面直接影响到训练出来的模型的泛化能力,为了解决这个问题,我们通常的做法是尽量保证训练样本与测试样本的分布保持一致。而文章提到Internal covariate Shift,意思是现在DNN里面存在很多的sub-network,因为DNN中高层神经元的输入是底层神经元的输出,这样就存在一个问题了:我们可以保证训练样本输入与测试样本的分布一致,但是训练样本输入通过神经元的传递成为它下一层神经元的输入。。。以此类推,这样的话我们就不能保证高层神经元的输入的分布了啊。也许有人会问我们为什么要保证sub-network的输入分布?第一,调整过的参数更加稳定,也可以使训练时间有效减少,因为参数不需要去重新适应新的输入分布;第二,避免非线性过饱和,比如我们使用sigmod函数作为激活函数,那么我们会发现越到后面,数据很可能会越往sigmod函数的两边靠,进入the saturated regime of the nonlinearity,导致梯度变化很慢,参数很难收敛,所以我们可以发现,在DNN中,靠近输出的网络层的神经元参数调整得很好,但是越往后因为梯度变化越小导致参数基本没有变化。当然我们可以使用ReLu函数代替,但是效果不明显。

这里作者讲了两种行不通的方法为后面提出的新方法做了铺垫。第一种方法如图3所示。

图3

但是发现最后对b的更新不能使损失函数的值下降,因为每一次参数更新完后随着而来的是输入的再次更新。

第二种方法是将输入向量看出一个整体去进行白化,但是这样需要计算协方差矩阵,如果样本很大,计算规模会爆炸。

所以最后为了解决这个Internal covariate Shift,文章提出了一种新算法Batch Normalization,下面就简单讲讲它的原理。

Batch Normalization

意思是以之前提到的mini-batch为单位,对输入数据进行Normalization操作,步骤分为两步:减均值->除以标准差。其中均值和标准差都是以mini-batch中的样本数据进行计算的。假设有n个输入,则对于每一个输入k的样本数据都进行如图4所示操作。将向量分解为单个输入,独立地进行白化操作就不需要考虑矩阵运算了。
图4
但是作者说这样做会降低神经元的表现能力,例如,如果激活函数是sigmod函数,那么因为输入数据在(-1,1)之间,基本上只能覆盖sigmod函数中间的接近线性的一段,这是不可取的,因为生物神经元不仅是存在激活态,相应的也应该存在抑制态,而这里我们相当于只是模拟了激活态。
为了解决这个问题,作者提出了一个解决办法,公式如图5所示。
图5

加了两个参数,gamma和beta,让输入数据可以缩放和偏移。作者没有固定这两个参数,而是让它们在训练中自动学习,这在很大程度上增加了神经网络的表现能力。

但是normalization的对象也就是公式中的x应该是什么呢?我们看一看常用的sigmod函数z = g(Wu + b),其中u代表上一个神经元的输出,我们可以直接对u进行normalization操作,但是作者说这样不好,因为在训练过程中u的分布是不稳定;所以我们选择对Wu + b进行normalization操作,因为它在训练过程中可以保持对称,非稀疏的分布。但是这样的话就会出现Internal covariate Shift提到的第一种方法中出现的问题,就是在训练过程中我们更新了b的大小,但是经过下一次的normalization操作,b并不能对新的x参数影响,这导致了b的值会不断增大但是损失函数的值却不变。作者采用的解决办法是把b归到beta里,这时候就变成了z = g(BN(Wu))了。

在训练DNN的时候我们以mini-batch为单位,去计算样本的均值和方差然后以它们为基础将输入变量进行转换,这是没问题的。但是,当把训练好的DNN用于分类或者其它任务的时候,问题就来了:应该以哪一个mini-batch的均值和方差对输入的变量进行转换呢?随便选一个肯定不不可能了,取当前需要分类的多个样本去计算新的均值和方差更加不靠谱,所以作者提出,在训练的时候根据每一个mini-batch的均值和方差,来求取所以用于训练的样本的均值和方差(其中方差使用的是无偏估计),这样我们计算得到均值和方差就很有代表性了。

在对卷积神经网络进行Batch Normalization时,mini-batch不再只是单纯的由m个一维变量构成了。为了使特征图片中不同位置的元素经过Batch Normalization后仍然能够保持差异,这时候mini-batch的大小变为m*p*q,其中p*q是特征图片的大小。每一种特征图片中的元素都共有唯一的gamma和beta参数。

总的来说,Batch Normalization的好处主要有以下几点:

1 减少Dropout的使用,因为Dropout一般是为了防止过拟合现象,但是通过BN,这种现象已经可以有效的避免了。

2 可以使用更高的学习率

3 可以使深层的参数得到更好的优化,因为使用BN后,误差梯度不能随着传递的深入而显著减小,使得深层的参数也得到很好的训练。

4 最重要的一点是训练效率提高了!



1 0
原创粉丝点击