Batch Normalization

这篇博客介绍了BatchNormalization(BN)如何通过批内标准化来缓解神经网络训练过程中的InternalCovariateShift问题,加快收敛速度,并提及了BN的白化过程和额外的可训练参数。后续的Normalization方法扩展展示了BN技术的影响力。

  2015年 Google 技术团队发表论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,在文中正式提出了批标准化(Batch Normalization, BN)。

Internal Covariate Shift

  对神经网络的参数初始化有了解的读者可能知道神经网络有一个重要的假设——每层的各个输入之间相互独立且服从正态分布。网络在训练的过程中,可训练参数在不断发生着变化,某神经元的可训练参数发生变化后,其输出值的概率分布很可能发生变化(数学期望和方差发生变化)。这也就意味着,经过一次训练后,该神经元的输出值的概率分布与本次训练之前的不服从同一分布。以上这种现象被论文的作者称为 “Internal Covariate Shift”。
  这种现象会导致以该神经元的输出作为输入的神经元需要调整权重以适应概率分布的变化。显然,这无疑会降低网络的收敛速度。再进一步说,为了降低两次训练之间的分布变化的程度,以让相关神经元及时适应这种变化,我们就需要设置一个较小的学习率。小的学习率也就意味着慢的收敛速度。

Batch Normalization

  为了缓解上述现象,论文作者提出了 BN 方法。我们知道在训练网络时,每次送入网络的不是一个样本,而是由多个样本组成的 batch。假设一个 batch 中有 h h h 个样本,那么神经元的一个输入端每次就会得到 h h h 个输入值(如果不理解此处,可以参考神经网络的基本原理一文中正向传播的矩阵公式)。如果我们将对这 h h h 个输入值进行统一调整,使调整后的这 h h h 个输入值的均值为 0 0 0、方差为 1 1 1。虽然是在 h h h 个输入值上进行的调整,并不是在整个训练集上,但这已经有了一定的近似了。那么,经过这样的调整,我们就可以近似的认为在训练的过程中输入值的概率分布始终稳定在数学期望为 0 0 0、方差为 1 1 1 的同一分布,这也就解决了 Internal Covariate Shift。这种将 h h h 个值的均值和方差分别调整为 0 0 0 1 1 1 的过程被作者称为白化(whitening)。
  我们对每个神经元内输入激活函数的激活值进行白化与上文中提到的对每个输入端的输入值进行白化所达到的效果是相同的。因为通过概率论的知识,我们知道两个独立的服从同一分布的随机变量,经过同一个函数变换后,仍然服从同一分布。如果每次训练中的激活值都服从同一分布,因为它们每次经过的都是同一个激活函数的变换,所以激活函数的输出值即神经元的输出值必然也服从同一分布。本层神经元的输出值就是下一层神经元的输入值,本层输出服从同一分布即下一层输入服从同一分布。
  事实上,BN 就是对激活值进行了白化,而没有对输入值进行白化。一方面,根据上一段,我们知道激活值和输入值的白化效果相同。另一方面,对激活值进行白化,会使白化后的激活值大部分分布到 0 0 0 附近,这可以缓解 Sigmoid、tanh 的梯度消失现象,也可以减少 ReLU 发生神经元死亡的可能性。(如果此处不理解,可以参考神经网络的激活函数一文)
  设 batch 中有 h h h 个样本,batch 中第 k k k 个样本使某神经元产生的激活值记作 s { k } s^{\{k\}} s{k},白化后的记作 s ~ { k } \tilde{s}^{\{k\}} s~{k}。设激活值的均值为 μ \mu μ,方差为 σ \sigma σ。则对激活值的白化公式如下:
μ = 1 h ∑ k = 1 h s { k } \mu = \frac{1}{h}\sum_{k=1}^h{s^{\{k\}}} μ=h1k=1hs{k} σ = 1 h ∑ k = 1 h ( s { k } − μ ) 2 \sigma = \sqrt{\frac{1}{h}\sum_{k=1}^h{\left( s^{\{k\}}-\mu \right)^2}} σ=h1k=1h(s{k}μ)2 s ~ { k } = s { k } − μ σ + ϵ \tilde{s}^{\{k\}} = \frac{s^{\{k\}} - \mu}{\sigma + \epsilon} s~{k}=σ+ϵs{k}μ  其中 ϵ \epsilon ϵ 是为了避免 σ \sigma σ 为零时发生运算错误而设置的常数(通常为 1 × 1 0 − 10 1 \times 10^{-10} 1×1010)。经过如上处理 s ~ { 1 } ,   s ~ { 2 } ,   ⋯   ,   s ~ { h } \tilde{s}^{\{1\}}, \, \tilde{s}^{\{2\}}, \, \cdots, \, \tilde{s}^{\{h\}} s~{1},s~{2},,s~{h} 的均值为 0 0 0,方差为 1 1 1。论文作者认为,白化后的激活值虽然解决了 Internal Covariate Shift,但却大都集中在 0 0 0 附近,这可能会降低一些神经元的表达能力。所以,作者又为每个神经元配置两个新的可训练参数 γ \gamma γ β \beta β,对白化后的激活值再进行一次线性变换。又经过线性变换后的激活值记作 s ~ ~ { k } \tilde{\tilde{s}}^{\{k\}} s~~{k},则公式如下:
s ~ ~ { k } = γ ⋅ s ~ { k } + β \tilde{\tilde{s}}^{\{k\}} = \gamma \cdot \tilde{s}^{\{k\}} + \beta s~~{k}=γs~{k}+β  当 γ = σ \gamma = \sigma γ=σ β = μ \beta = \mu β=μ 时,最终的激活值也就相当于没有做白化。作者并未论述加入这两个新的可训练参数的理论依据。可能是想做一种调和吧,不把事情做的太绝?
  作者的实验结果表明:

  • BN 可以提高收敛速度。
  • 使用 BN 时,可以达到 Dropout 的缓解过拟合效果,因此可以不使用 Dropout。
  • 使用 BN 时,可以使用较大的学习率,对于权重的初始化可以不再十分严格。

其他 Normalization

  在 BN 出现之后,相继出现了很多其它的 Normalization,它们进行 Normalization 的计算方式与 BN 一致,不同的是 Normalization 的作用范围不同,参看Group Normalization中的插图。
各类 Normalization 作用范围示意图

批归一化(Batch Normalization)是深度学习中一种重要的技术,用于加速神经网络的训练过程并提高模型的稳定性。其核心思想是在训练过程中对每一层的输入进行标准化处理,使得数据分布更加稳定,从而缓解内部协变量偏移(Internal Covariate Shift)问题[^2]。 ### 概念 批归一化的基本步骤包括以下几个方面: 1. **标准化输入**:对于某一层的输入 $ x $,计算其均值 $ \mu_B $ 和方差 $ \sigma_B^2 $,然后对输入进行标准化: $$ \hat{x}^{(k)} = \frac{x^{(k)} - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} $$ 其中 $ \epsilon $ 是一个很小的常数,用于防止除零错误。 2. **可学习的参数**:在标准化之后,引入两个可学习的参数 $ \gamma $ 和 $ \beta $,用于缩放和偏移标准化后的值: $$ y^{(k)} = \gamma^{(k)} \hat{x}^{(k)} + \beta^{(k)} $$ 这一步确保了网络能够学习到适合当前任务的数据分布。 ### 应用 批归一化在深度学习中的应用非常广泛,尤其在卷积神经网络(CNN)和全连接网络(FCN)中效果显著。以下是一些典型的应用场景和优势: - **加速训练**:通过减少内部协变量偏移,批归一化可以显著加快模型的训练速度。实验表明,使用批归一化的模型可以在更少的迭代次数内达到相同的准确率。 - **提高模型稳定性**:批归一化有助于缓解梯度消失和梯度爆炸问题,从而提高模型的稳定性。它使得网络对初始化的敏感度降低,从而更容易训练深层模型。 - **减少对正则化的需求**:由于批归一化本身具有一定的正则化效果,因此在使用该技术时可以减少对其他正则化方法(如Dropout)的依赖。 - **提升模型性能**:在许多任务中,例如图像分类和目标检测,批归一化可以显著提升模型的性能。例如,在ImageNet数据集上,使用批归一化的模型通常可以获得更高的准确率。 ### 示例代码 以下是一个简单的示例,展示了如何在PyTorch中使用批归一化: ```python import torch import torch.nn as nn class SimpleNet(nn.Module): def __init__(self): super(SimpleNet, self).__init__() self.layer = nn.Sequential( nn.Linear(100, 256), nn.BatchNorm1d(256), nn.ReLU(), nn.Linear(256, 10) ) def forward(self, x): return self.layer(x) ``` 在这个示例中,`nn.BatchNorm1d(256)` 对全连接层的输出进行批归一化处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值