《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KangRoger/article/details/62091914

神经网络训练原则是最小化loss函数,最常用的是mini-batch SGD。虽然SGD简单高效,但是它对调参要求很高,例如学习率以及参数初始化。每一个batch的数据,都是对整个训练集的估计;当输入改变,每一层的输出就会改变,即使前面层改变很小,经过几层处理,很可能放大这个变化。

输入层的改变,引起后面层的改变;这就要求层要不断适应新的数据分布。这种变化叫做“covariate shift”。

如果每层的输入分布都可以固定,那么训练神经网络将会变得简单。为了减少covariate shift,文章提出Batch Normalization算法;该算法不仅可以加速训练过程,还有利于梯度在网络间的传递(减小了梯度关于参数值大小的依赖)。Batch Normalization可以让网络使用更大的学习率,甚至不使用dropout。

Internal Covariate Shift是指网络中激活值得改变(因为神经网络训练过程中参数的改变)。如果可以固定每一层输入的分布,那么可以提升训练速度。例如,可以通过白化,固定好每一层输入的分布,这样就可以减少internal covariate shift带来的影响。

首先想到的是白化每层的激活值,1通过直接修改网络,2或改变激活值依赖的参数。但是这样的修改将会干扰优化算法,导致优化算法是按照Normalization来更新。

要确保对于任何参数值,网络的激活值总是服从期望分布。x是输入,χ是整个训练集,那么normalization为:

x^=Norm(x,χ)

不仅仅依赖x,还依赖χ。反向传播还要计算

Norm(x,χ)xNorm(x,χ)χ

这样的话,白化每一层的输入,计算量很大,要计算

Cov[x]=Exχ[xxT]E[x]E[x]TCov[x]12(xE[x])

还要计算它们的偏导。上面计算量太大,要寻找一种不需要在每次参数更新时都计算整个训练集的方法。

对整个训练集做Normalization,代价太大,一种容易想到的方法是对一个Mini-Batch做Normalization。一层的输入时d维x=(x(1)x(d)),对每一个维度做normalize

x^(k)=x^(k)E[x(k)]Var[x(k)]

通过上面的白化处理,可以改变数据分布,但是也改变了数据的表达能力。例如使用sigmod作为激活函数,白化操作会使数据分布在“0”附近,即在sigmod线性附近。为了确保变换是“表达能力”方面的等价变换,还要再每一维度引入缩放和平移参数:γ(k),β(k)

y(k)=γ(k)x^(k)+β(k)

这些参数和网络参数一起来学习获得,用来恢复网络表达能力。实际上如果γ(k)=Var[x(k)],β(k)=E[x(k)]就可以恢复出输入的原始值。

上面均值和方差,都是计算一个mini-batch数据获得的,而不是整个训练集。

假设一个mini-batch数据有m个,去一个维度的数据

β={x1m}

经过线性变换得到y1m,这个变化可以表示为:

BNγ,β:x1my1m

下面就是Batch Normalization算法过程

batch_norm_01.jpg

假设l为loss,那么反向传播时,链式法则求导为:

batch_norm_02.jpg

在训练时,使用mini-batch计算均值和方差,在intference时,就要使用无偏估计了,均值估计时无偏估计,但是方差不是,无偏估计的方差为:

Var[x]=mm1Eβ[σ2β]

最后可以得到一个完整的Batch Normalization算法

batch_norm_03.jpg

展开阅读全文

没有更多推荐了,返回首页