批量归一化模拟器 返回
机器学习

批量归一化模拟器

用于可视化使深度神经网络学习稳定的"批量归一化(Batch Normalization)"的工具。改变小批次的均值·标准差、缩放γ、移位β,可以实时理解某个活性值如何通过归一化值x̂变为BN输出y,以及跨层分布如何变化。

参数设置
批次均值 μB
小批次中生活性值的均值
批次标准差 σB
生活性值的变异性(分散)
缩放参数 γ
可学习。决定输出的标准差
移位参数 β
可学习。决定输出的均值
关注的活性值 x
追踪x̂·y的单个样本值
计算结果
归一化值 x̂
BN输出 y
归一化后批次均值
归一化后批次标准差
输出批次均值
输出批次标准差
分布变换 — 生批次 → 归一化 → 缩放·移位

从左到右:生批次、归一化后(均值0·标准差1)、仿射变换后(均值β·标准差γ)的分布。用点表示关注样本 x → x̂ → y 的位置。

输入输出映射 y(x)
批次统计比较(均值·标准差)
理论·主要公式

$$\hat x=\frac{x-\mu_B}{\sqrt{\sigma_B^{2}+\varepsilon}},\qquad y=\gamma\,\hat x+\beta$$

归一化值 x̂ 和BN输出 y。批次的均值 μB 和方差 σB² 从整个小批次计算,缩放 γ 和移位 β 通过误差反向传播学习。ε是用于数值稳定化的微小常数(本工具中为 1e-5)。

$$\mathrm{E}[\hat x]\approx0,\quad \mathrm{Std}[\hat x]\approx1,\qquad \mathrm{E}[y]=\beta,\quad \mathrm{Std}[y]=\gamma$$

归一化后的批次均值≈0·标准差≈1。仿射变换后的批次均值=β·标准差=γ。

什么是批量归一化

🙋
神经网络的讲解中经常出现"批量归一化(Batch Normalization)",它到底在干什么?
🎓
简单来说就是"统一各层输出的数值大小"的处理。在深度网络中,某一层的输出(活性值)随着层数增加会变得越来越大或越来越小。批量归一化通过查看小批次中的活性值,进行减法和除法,使其均值为0、标准差为1。看左边的"批次均值 μB",改变它时,生活性值的分布会左右移动。批量归一化就是每次都把它重置为0的过程。
🙋
仅仅统一数值大小,学习就会产生这么大的变化吗?
🎓
确实会产生很大的变化。前一层的权重更新后,下一层接收的输入分布也会偏移。这称为"内部协变量漂移"。对于下一层来说,输入的目标在每一步都在移动,这使学习变得困难。批量归一化将分布固定在均值0·标准差1,使损失曲面更光滑,梯度波动减少。因此可以使用更大的学习率,收敛速度更快。
🙋
但如果总是固定在均值0·标准差1,不会限制层能表达的范围吗?
🎓
问得好。这正是 γ(缩放)和 β(移位)的作用。归一化后通过 y = γ·x̂ + β 这一仿射变换。γ 和 β 是和网络其他权重一样需要学习的参数,如果归一化对网络有害,可以学习 γ=σB、β=μB 来恢复原始分布。左边改变 γ 时输出的标准差随之改变,改变 β 时输出的均值随之改变。γ=1·β=0 正好是"纯粹归一化"的状态。
🙋
训练时使用批次均值。那推理时只输入一张图像时怎么办?
🎓
这是实际工作中容易出问题的地方。如果只有一张图像,无法计算批次的均值和标准差(标准差会变成0)。因此在训练期间悄悄累积 μB 和 σB² 的移动平均,推理时使用这些固定值。PyTorch中是 model.eval(),TensorFlow中是 training=False 来切换。忘记这一点、在训练模式下进行推理,会导致同一张图像每次结果都不同的诡异bug。
🙋
最近还听说"层归一化"。这和批量归一化怎样区分使用?
🎓
是的,归一化有多种类型。批量归一化在批次方向(多个样本)上计算统计,所以批次很小时统计会不稳定。而层归一化在单个样本的特征维度上进行归一化,不依赖于批次大小。因此在处理变长序列的Transformer和RNN中,层归一化是主流;在处理图像分类的CNN中,批量归一化至今仍是标准做法。这样进行区分使用。

常见问题

要对活性值 x 进行批量归一化,首先使用小批次的均值 μB 和标准差 σB 计算 x̂ = (x − μB) / √(σB² + ε)。ε是用于数值稳定化的微小常数(本工具中为 1e-5)。接下来通过可学习的缩放参数 γ 和移位参数 β 进行仿射变换,得到最终输出 y = γ·x̂ + β。例如,当 μB=3、σB=2.5、γ=1、β=0、x=6 时,x̂=(6−3)/√(6.25+1e-5)≈1.200,y=1.200。
每一层的活性值分布会随着前一层参数的更新而改变(内部协变量漂移)。批量归一化将每层的输出重新中心化和重新缩放到均值0·标准差1,因此后续层看到的输入分布保持稳定。这使得损失曲面更光滑,梯度波动较小,因此可以使用更大的学习率,收敛速度更快。此外,对初始值的依赖性也减弱了,并具有接近正则化的效果。
仅仅进行归一化会将活性值固定在均值0·标准差1,这限制了层能表达的范围。通过加入可学习的 γ(缩放)和 β(移位),网络可以在必要时抵消归一化,恢复任意的均值和方差。仿射变换后的批次均值=β,标准差=γ。γ=1·β=0 等同于纯粹的归一化,γ 和 β 通过误差反向传播与其他权重一起学习。
训练时使用每个小批次的 μB·σB²,但推理时通常只输入一个样本,批次统计会变得不稳定。因此在训练过程中累积 μB·σB² 的移动平均(running mean / running variance),推理时使用这些固定值。这确保对相同输入总能得到相同输出。训练模式和推理模式下BN行为的差异是框架中常见的错误源。

现实应用

图像分类的CNN:ResNet 和 Inception 等卷积神经网络中,几乎每个卷积层之后都会插入批量归一化。即使网络深度超过100层,也能稳定地进行学习,这正是得益于BN对每层活性值分布的统一。BN成为标准配置后,我们不再需要依靠谨慎的权重初始化和小学习率。

与卷积层的融合(推理加速):推理时,批量归一化只使用训练中固定的统计量(均值·方差)和 γ·β 进行线性变换。利用这种线性性,将前面卷积层的权重与BN"融合"到一个卷积操作中的优化方法(BN folding / fusion)被广泛应用。这减少了推理的计算量和内存访问,实现了边缘设备上的加速。

迁移学习和微调:在将预训练模型应用于其他数据集时,BN的移动统计量(running mean / variance)的处理方式会影响结果。如果新域的图像统计与原始数据差异很大,可以选择只重新训练BN层,或将BN固定在推理模式。不理解BN的行为很容易导致迁移学习效果不佳。

正则化效果的利用:批量归一化每个小批次的统计略有不同,这对每个样本施加了轻微的噪声效果,具有过学习的正则化作用。据悉,使用BN的模型对Dropout的需求会降低。是否同时使用两者取决于具体任务的验证。BN不仅使学习稳定,还有助于泛化性能。

常见误解和注意事项

最大的陷阱是"在训练模式下进行推理"。批量归一化在训练时使用小批次的统计,推理时使用训练中累积的移动平均。忘记 model.eval()(PyTorch)或 training=False(Keras)的切换,推理时也会使用批次统计,导致同样的输入在不同批次中产生不同的输出。用批次大小1进行推理时,标准差接近0,输出甚至会发散。反过来,在评估循环中保持 eval() 然后继续训练,也会导致BN统计不更新的bug。

其次是"小批次大小也能同样有效使用BN"的误解。批量归一化从整个小批次估计均值和方差,当批次大小为2~4这样很小时,统计估计变得非常不稳定,反而会恶化学习。在物体检测和分割等由于GPU内存限制无法使用大批次的任务中,通常选择组归一化或层归一化来避免这个问题。本工具中直接指定 μB·σB,但要记住,实际BN中"批次越小,这些估计值越不可靠"。

最后,"BN通过消除内部协变量漂移而生效,这是唯一的真理"的说法并非绝对。提案初期确实以抑制内部协变量漂移作为效果的原因,但后来的研究认为"BN的本质是使损失曲面更光滑,提高梯度的可预测性"。此外,BN前后置偏差项会冗余、激活函数前后位置不同会改变行为等实现细节也有讲究。BN是"随便加就有效"的便利工具,但为什么有效至今仍是活跃的研究课题。了解到这一点,能避免对结果的误解。

使用指南

  1. 设置输入批次的均值μ(范围-2.0~2.0)和标准差σ(范围0.1~2.0)以确定批次数据分布
  2. 调整缩放参数γ(0.5~2.0)和移位参数β(-1.0~1.0)以控制BN层的变换特性
  3. 通过实时输出查看归一化值x̂、BN输出y、归一化后批次的均值和标准差,直观理解内部协变量漂移的抑制效果

具体计算示例

ResNet-50初期卷积层应用BN的例子:对于活性值的输入批次均值μ=0.85、标准差σ=0.72,设置γ=1.2、β=0.3时,归一化值x̂被统一为均值0·方差1,BN输出y=γx̂+β=1.2x̂+0.3。通过这个处理,下层的输入分布稳定化,可以将学习率提高25%。

实际使用中的注意事项