『Batch Normalization』Batch Normalization一文吃透


在神经网络模型中,批量归一化(Batch Normalization)已然是很常见的一种操作,自2015年被谷歌提出以来,由于能够有效提升网络训练效率,已被广泛应用于处理图像相关的网络。

为了透彻理解BN究竟为何而提出,又起到了什么作用,笔者搜索诸多博客、书籍资料并将内容梳理成本文,以作备忘。


协变量偏移

在机器学习中,一般会假设模型的输入数据的分布是稳定的。

若是模型输入数据的分布发生变化,这种现象被称为 协变量偏移(covariate shift)

值得一提的是,模型的训练集和测试集的分布不一致,也属于协变量偏移现象。

同理,在一个复杂的机器学习系统中,也会要求系统的各个子模块在训练过程中输入分布是稳定的。若是不满足这一条件,则会称为内部协变量偏移(internal covariate shift, ICS)

以深度神经网络为例,在训练过程中神经网络内部的数据分布发生变化,便是一种典型的内部协变量偏移现象。

为什么内部的数据分布会发生变化呢?我们通过一个全连接网络进行前向传播的实例来一探究竟。


神经网络前向传播

对于全连接网络的一层来说,设一个Batch的输入 x 1 x_1 x1,隐藏层的权重为 W 1 W_1 W1,两者矩阵相乘得到输出为 y 1 y_1 y1,经过激活函数后得到 z 1 z_1 z1

当前批次的前向传播
在训练过程中,当一次前向传播结束后,神经网络将会反向传播更新隐藏层参数 W 1 W_1 W1 W 2 W_2 W2

当下一个Batch的输入 x 2 x_2 x2进入该层,与更新后的隐藏层参数 W 2 W_2 W2计算得到输出 y 2 y_2 y2,经过激活函数后得到 z 2 z_2 z2

下一批次的前向传播
由于隐藏层参数的更新,相比于 z 1 z_1 z1,该层的输出数据 z 2 z_2 z2的分布发生变化,进而下一层的输入数据分布发生变化,这便是发生了内部协变量偏移现象。

当前层的输出分布发生变化,即是下一层的输入分布发生变化,此处不必纠结这一问题。

用更为一般化的语言总结这种现象就是:

在训练过程中,由于隐藏层参数的更新,同分布不同批次的数据进入网络同一层后的输出分布发生变化。

ICS一般指的是不同批次的数据进入同一层时的输出分布变化,除此之外,还有几种“分布不同”的情况:

  • 同批次的数据,每穿过一层网络后数据分布均会发生变化。
  • 同批次的数据,不同的样本点分布可能不同。比如一个样本点 d 1 d_1 d1为[1.2, 1.4],另一个样本点 d 2 d_2 d2是[40, 66],两者的量级不同, d 2 d_2 d2的数据范围很大,那么会导致 d 2 d_2 d2的参数 W 2 W_2 W2梯度很大,更新速度更快,反之 W 1 W_1 W1的更新速度很慢,于是模型被迫只能使用较小的学习率,以防 W 2 W_2 W2更新时迈的步子太大,导致模型收敛速度慢。

那么,这种内部协变量偏移现象会带来什么问题呢?


引起的问题

  • 收敛速度慢,学习不稳定

本质上,神经网络学习的是数据分布,ICS现象使得网络每一层需要不断适应输入数据的分布变化

试想,网络刚刚才适应学习了这种分布,然而下一个批次又需要学习另一种分布,像这样“推倒重来”的学习过程很不稳定,从而导致收敛速度降低。

另一方面,由于之前提到的同一批数据中不同样本点的分布可能不同等原因,为保证训练的稳定性和收敛性,在实际应用中往往会采用较小的学习率,防止参数更新过快,从而导致收敛速度降低。

  • 产生梯度消失问题

经过网络前几层的变换,很可能使得后几层的输入数据变得过大或过小,从而掉进激活函数(Sigmoid、Tanh)的饱和区。

Sigmoid函数图像
饱和区的梯度变化很不明显,会产生梯度消失问题,进而导致学习过程停止。

我们希望的是,数据落入激活函数中间的非饱和区。

为了降低内部协变量偏移所带来的负面影响,在训练过程中一般会采用非饱和型激活函数(ReLU)、精细的网络参数初始化,保守的学习率,但这不仅会使得网络的学习速度太慢,还会使得最终效果特别依赖于网络的初始化。


Batch Normalization的登场

批量归一化(Batch Normalization)作为英雄横空出世,一举解决上述问题。

批量归一化可以看作是在每一层输入和上一层输出之间加入了一个新的计算层,对数据的分布进行额外的约束。

其算法流程如图所示:

BN算法流程
核心即为这一公式:

y ( k ) = γ ( k ) x ( k ) − μ ( k ) ( σ ( k ) ) 2 + ϵ + β ( k ) y^{(k)} = \gamma^{(k)}\frac{x^{(k)}-\mu^{(k)}}{\sqrt{(\sigma^{(k)})^2+\epsilon}}+\beta^{(k)} y(k)=γ(k)(σ(k))2+ϵ x(k)μ(k)+β(k)

其中,上标 k k k表示数据的第 k k k维,BN在一个批次数据的各个维度上独立进行; x ( k ) x^{(k)} x(k)是输入数据, y ( k ) y^{(k)} y(k)是BN后的输出数据; μ ( k ) \mu^{(k)} μ(k) σ ( k ) \sigma^{(k)} σ(k)分别是输入数据当前batch的均值和标准差, β ( k ) \beta^{(k)} β(k) γ ( k ) \gamma^{(k)} γ(k)分别是可学习的平移参数和缩放参数; ϵ \epsilon ϵ是防止分母为0的一个小量。

你或许会觉得很眼熟,这不是一个标准化的过程嘛?标准化的公式如下:

y = x − μ σ y = \frac{x-\mu}{\sigma} y=σxμ

此处需要强调的是,归一化与标准化并不是一回事。

将数据变化为均值为0,方差为1的分布这一过程被称为标准化(Standardization),而归一化(Normalization)一般指的是将一列数据变化到某个固定区间(范围)中。

可以看出,批量归一化相当于在标准化的基础上利用参数 β \beta β γ \gamma γ进一步修正分布,至于为何称为批量归一化这一点我并未深入探究。

那么,很自然地会引出一个问题,参数 β \beta β γ \gamma γ起到什么作用呢?


为什么存在 β \beta β γ \gamma γ

  • 保留网络各层在训练过程中的学习成果,使BN模块具有自我关闭能力

如若没有 β \beta β γ \gamma γ,那么BN就会退化为普通的标准化(Standardization)。训练过程中尽管参数在更新,但是网络各层的输出分布始终不变(均值为0,标准差为1),无法有效学习。

添加 β \beta β γ \gamma γ后,网络可以为每个神经元自适应地学习一个量身定做的分布(均值为 β \beta β,标准差为 γ \gamma γ),保留每个神经元的学习成果。

从另一个角度来说,若是在训练过程中,网络发现目前的标准化操作并不有效,便可以通过 β \beta β γ \gamma γ参数再次修正分布的变化,比如当 γ \gamma γ等于 σ σ σ β \beta β等于 μ μ μ,此时数据分布再次恢复原状,相当于进行了“反标准化”。换句话说,参数 β \beta β γ \gamma γ使得BN模块具有自我关闭能力,当BN导致特征分布被破坏,或者使网络泛化能力减弱时,可以通过这两个参数将其关闭。

对于标准化再修正分布这一过程,知乎@soplars文章中的一张图可以直观地展示出来。

BN效果

  • 保证激活单元的非线性表达能力

如前所述,没有 β \beta β γ \gamma γ时,BN的输出分布始终是均值为0,标准差为1。对于Sigmoid、Tanh等激活函数来说,数据将会落在近似线性的非饱和区域,这样确实有效缓解了梯度消失问题。

然而,我们也不希望数据全部挤在线性区,因为这样无法利用非线性区,会使得模型丧失非线性特征的提取能力,以及其非线性表达能力

因此,通过添加参数 β \beta β γ \gamma γ为分布带来一定的偏移,我们希望能够找到线性和非线性的平衡点,既能享受非线性的较强表达能力,又能享受线性区较大的下降梯度。

  • 引入噪音,防止过拟合

引入参数 β \beta β γ \gamma γ,适当地增加噪音,有助于增加鲁棒性,防止过拟合。


预测时如何使用BN?

预测的时候只有单个样本,无法计算均值和方差,该如何进行BN操作呢?

我们在训练时对于每个batch可以计算出相应的均值和标准差,对这些batch对应的均值和标准差进行加权求和即可。

之所以要使用加权求和的方式,是因为对于同一层网络来说,后进来的batch数据其所对应的均值和标准差更加接近实际测试时输入数据对应的均值和标准差(因为训练后期的参数更贴近于测试时的网络参数),所以后进来的batch数据理应有更高的权重,使得计算得到的均值和标准差更加接近数据集的均值与标准差。

还有一种方法是,使用训练数据集整体的均值和标准差,固定网络参数后将所有数据输入进行计算,这种方法效率很低,计算代价大。


BN放在哪?

  • 将BN放在激活函数之前

如前所述,可以保证激活单元的非线性表达能力,缓解梯度消失问题。

同时,可以有效避免BN破坏非线性特征的分布。

  • 将BN放在激活函数之后

当使用ReLU作为激活函数时,它不存在像Sigmoid、Tanh一样的饱和区问题,所以可以将BN放置于激活函数之后。

避免数据在激活函数之前被转化成相似的模式,从而使得非线性特征分布趋于同化。

在原论文中,BN被放置于激活函数之前,但学术界和工业界也有不少人倾向于将BN放置于激活函数之后,且从后续的发展来看貌似后者的做法更加主流。

BN究竟应该放在什么位置,仍是一个存争议的问题。


BN的作用

上文尽可能清晰地讲解了BN的原理及其动机,本节系统地梳理BN可以起到什么作用。

  • 可以采用较大学习率,加快收敛速度

BN使得每一层的输入输出同分布,此时数据处于同一量级,不同参数的梯度不再有差别,无需因为梯度大的参数而使用较小的学习率,因此可以使用较大的学习率,加快收敛速度。

  • 避免梯度消失和梯度爆炸问题

每次都把数据分布调整到标准位置上,因此进入激活函数时不存在梯度消失和梯度爆炸的问题。

  • 对参数初始化不敏感

直观上来说,在批量归一化下参数初始值 W W W k W kW kW所计算得到的结果是相同的,都会拉回到均值为0,标准差为1,因此这会使模型对参数初始化的方法不那么敏感,而不会像之前所说的“特别依赖于初始化”。

B N ( k W ) = γ k W x − k μ k σ + β = γ W x − μ σ + β = B N ( W ) BN(kW) = \gamma \frac{kWx-k\mu}{k\sigma} + \beta = \gamma \frac{Wx-\mu}{\sigma} + \beta = BN(W) BN(kW)=γkσkWxkμ+β=γσWxμ+β=BN(W)

  • 一定程度上防止过拟合

对散乱的数据分布进行归一化,可以一定程度上减小噪音,防止模型学习无用的特征,导致泛化能力变差,从而导致过拟合。

引入参数 β \beta β γ \gamma γ,适当地增加噪音,有助于增加鲁棒性,防止过拟合。

这里更多的是基于BN效果好的直觉解释,并无权威验证,意会即可,无需较真。


与Layer Normalization有什么区别?

我们知道,在Transformer中使用了Layer Normalization,即LN,而非本文所提的BN。这是为什么呢?两者的区别又在于什么?

Batch Normalization 是对一批样本的同一维度特征做归一化, Layer Normalization 是对单个样本的所有维度特征做归一化。

BN用在图像较多,LN用在文本较多,其原因在于LN更适合处理变长序列,比如文本。

假如现在需要计算第 k k k维特征的均值与方差,但由于序列的长度不固定,可能会出现下图这种锯齿状:

BN与变长序列
而LN不会存在这种问题,其在样本内计算均值与方差,不受序列长度的影响。


参考

《百面深度学习》《百面机器学习》

一篇极为全面的BN介绍博客,本文很多内容借鉴于此篇博客,感谢分享!

https://blog.youkuaiyun.com/weixin_44492824/article/details/123266953

各种归一化的总结

深度学习中的BN,LN,IN,GN总结

讲解Batch Normalization的系列

理解Batch Normalization系列1–原理(清晰解释)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值