神经网络归一化技术:Batch/Layer/Instance/Group Norm 全解析
归一化(Normalization)是现代深度神经网络中几乎必不可少的一环。它不仅能加速训练收敛,还能起到一定的正则化作用,让模型对初始化和学习率不再那么敏感。本文聚焦四种最常被提及的归一化方法:Batch Normalization(BN)、Layer Normalization(LN)、Instance Normalization(IN)与 Group Normalization(GN),逐一剖析它们的数学原理、统计量的计算维度、训练与推理的差异,并给出可直接运行的 PyTorch 代码,帮助你在不同任务里选对方法。
背景与动机
深层网络在训练时存在一个棘手现象:随着前层参数不断更新,后层输入数据的分布会持续发生偏移。这种偏移迫使后层不断去适应新的分布,导致训练变得缓慢且不稳定,往往需要较小的学习率与精心的初始化。
归一化的核心思想,是在网络的某些中间位置对激活值做「减均值、除标准差」的标准化,把数据拉回均值接近 0、方差接近 1 的稳定区间,从而让每一层面对的输入分布更加平稳。不同的归一化方法,本质区别在于「沿哪个维度集合样本、计算均值与方差」。
内部协变量偏移概念
Ioffe 与 Szegedy 在提出 Batch Normalization 时,把前面描述的分布偏移现象命名为「内部协变量偏移」(Internal Covariate Shift, ICS)。他们主张:通过最小化层输入分布的变化,可以加速训练。
需要说明的是,ICS 是否真的就是 BN 起效的唯一原因,学界存在争议。后续有研究(如 Santurkar 等人 2018 年的研究)指出,BN 的主要收益可能来自「让优化问题的条件数更优、损失曲面更平滑」,而不完全是消除了协变量偏移。不过无论机制如何,归一化能显著加速并稳定训练,这一点已被大量实践证实。
Batch Normalization 原理与公式
Batch Normalization(BN)在训练时,针对一个 mini-batch 内的同通道特征计算均值与方差。
给定 mini-batch 中某个通道的一组激活值 $x_1, x_2, \dots, x_m$,BN 的计算步骤如下:
均值:μ_B = (1/m) · Σ x_i
方差:σ_B² = (1/m) · Σ (x_i - μ_B)²
标准化:x̂_i = (x_i - μ_B) / √(σ_B² + ε)
缩放平移:y_i = γ · x̂_i + β
其中 $\varepsilon$ 是为数值稳定加入的微小常数;$\gamma$ 与 $\beta$ 是可学习的缩放与平移参数,让网络有能力恢复(或调整)被标准化的表示。
BN 的统计量是在「批次(batch)维度」上聚合的。以二维卷积为例,统计量跨整个 mini-batch 的 N 张图、H×W 个空间位置,只对通道 C 分别求取。因此 BN 的效果强依赖 batch size:批次越小,均值方差估计越不准,效果越差。
Layer Normalization 原理
Layer Normalization(LN)由 Ba、Kiros 与 Hinton 提出,初衷是解决 BN 难以用于循环神经网络、且依赖 batch size 的问题。
LN 不再跨样本聚合,而是对「单个样本在某一层内的所有激活」计算均值与方差:
对单个样本某层的全部元素 x_1, …, x_H:
μ = (1/H) · Σ x_i
σ² = (1/H) · Σ (x_i - μ)²
x̂_i = (x_i - μ) / √(σ² + ε)
y_i = γ · x̂_i + β
关键在于,LN 的统计量只来自「当前这一个样本」,因此它的计算在训练与推理时完全一致,也不受 batch size 影响。这使得 LN 成为 Transformer、RNN 以及自回归生成模型的主流选择。
Instance Normalization 原理
Instance Normalization(IN)由 Ulyanov 等人在图像风格迁移工作中提出。它与 BN 公式相同,但统计量只在一个样本的「单个通道」内部计算,既不跨样本、也不跨通道、也不跨空间——实际是「只跨该样本该通道的 H×W 空间位置」。
对单个样本单个通道的特征图(空间尺寸 H×W,共 H·W 个元素):
μ = (1/(H·W)) · Σ 空间位置上的 x
σ² = (1/(H·W)) · Σ 空间位置上的 (x - μ)²
x̂ = (x - μ) / √(σ² + ε)
y = γ · x̂ + β
IN 的核心价值在于:它把每张图自身的对比度、色调等「实例级」信息归一化掉,只保留内容结构,从而非常适合风格迁移、图像生成等需要解耦「内容」与「风格」的任务。
Group Normalization 原理
Group Normalization(GN)由 Wu 与 He 提出,是 BN 在小批次场景下的替代方案。它把通道分成若干组,在「单个样本 + 同一组通道」的内部计算统计量:
设通道总数为 C,分成 G 组,每组 C/G 个通道。
对单个样本、同一组内的所有通道与空间位置求均值与方差:
μ = (1/((C/G)·H·W)) · Σ 组内所有元素 x
σ² = (1/((C/G)·H·W)) · Σ 组内所有元素 (x - μ)²
x̂ = (x - μ) / √(σ² + ε)
y = γ · x̂ + β
GN 的统计量既不跨样本、也不依赖 batch size,因此在目标检测、分割、视频等被迫使用很小 batch 的视觉任务里表现稳定。当 G 等于通道数时,GN 退化为 Instance Norm;当 G 等于 1 时,GN 退化为 Layer Norm,三者其实是同一族方法在不同分组粒度上的特例。
四者对比表
| 方法 | 统计量计算维度 | 依赖 batch size | 典型适用场景 |
|---|---|---|---|
| Batch Norm | 跨 batch、同通道 | 强依赖 | CNN 图像分类(大 batch) |
| Layer Norm | 单样本整层 | 不依赖 | RNN、Transformer、自回归生成 |
| Instance Norm | 单样本单通道 | 不依赖 | 风格迁移、图像生成 |
| Group Norm | 单样本分组通道 | 不依赖 | 检测/分割/视频等小 batch 视觉任务 |
从归一化族的角度看,BN、LN、IN、GN 的区别可以统一用「沿哪些轴聚合统计量」来描述;GN 通过调整分组数 G,能够在 IN(G=C)与 LN(G=1)之间平滑过渡。
PyTorch 代码示例
下面给出四种归一化在 PyTorch 中的标准用法。注意:BN 与 IN 在训练与推理行为不同,需要正确切换 model.train() 与 model.eval();LN 与 GN 则不受此影响。
import torch
import torch.nn as nn
# 假设输入为卷积特征:形状 (N, C, H, W)
N, C, H, W = 4, 16, 32, 32
x = torch.randn(N, C, H, W)
# 1) Batch Normalization:对通道 C 归一化
bn = nn.BatchNorm2d(num_features=C, eps=1e-5, momentum=0.1, affine=True)
y_bn = bn(x)
print("BatchNorm2d 输出形状:", y_bn.shape)
# 2) Layer Normalization:对最后 D 个维度(此处为 C*H*W)归一化
# 对于特征图,通常把 C、H、W 都纳入归一化维度
ln = nn.LayerNorm(normalized_shape=[C, H, W], eps=1e-5, elementwise_affine=True)
y_ln = ln(x)
print("LayerNorm 输出形状:", y_ln.shape)
# 3) Instance Normalization:单样本单通道
in_op = nn.InstanceNorm2d(num_features=C, eps=1e-5, affine=True)
y_in = in_op(x)
print("InstanceNorm2d 输出形状:", y_in.shape)
# 4) Group Normalization:把 C 个通道分为 G 组
G = 4
gn = nn.GroupNorm(num_groups=G, num_channels=C, eps=1e-5, affine=True)
y_gn = gn(x)
print("GroupNorm 输出形状:", y_gn.shape)
# 训练 / 推理切换(仅对 BN、IN 等含 running statistics 的方法有意义)
bn.train()
out_train = bn(x)
bn.eval()
out_eval = bn(x)
print("BN 训练与推理使用不同的统计量来源")
补充说明:在 Transformer 的序列场景里,输入形状通常为 (batch, seq_len, hidden),此时 nn.LayerNorm(hidden) 即可对该样本整个 hidden 维度归一化,无需关心 seq_len,这也是 LN 在 NLP 中广受欢迎的原因。
训练推理差异与常见坑
坑一:BN 的 running mean/var 未更新。 BN 在推理时使用训练阶段通过指数移动平均累积的 running_mean 与 running_var,因此务必在训练时调用 model.train()、推理时调用 model.eval()。若忘记切换,推理会错误地使用当前 batch 的统计量,导致结果抖动甚至错误。
坑二:小 batch 下 BN 失效。 当 batch size 小到 2 甚至 1 时,BN 的统计量估计噪声极大,模型精度会明显下降。此时应优先选用 GN 或 LN。
坑三:BN 在训练初期的累积统计量不可信。 训练最开始若干步,running 统计量尚不稳定,有时需要先用较大 momentum 或 warmup 学习率过渡。
坑四:LN/IN/GN 不需要 running 统计量。 它们每个样本独立计算均值方差,因此不存在 train/eval 行为差异,移动端或静态图部署时更省心。
坑五:归一化位置与激活顺序。 经典 BN 放在卷积(或全连接)之后、激活函数之前;但如 Pre-Activation ResNet 把 BN 放在卷积之前。顺序会影响梯度流,实际应以所用架构的官方实现为准,不要随意调换。
坑六:batch 维度被拆分(如多卡、padding 样本)时要小心。 数据并行下若各卡 batch 不一致,BN 的统计量会失真;可改用同步 BN(SyncBN)或在小 batch 场景直接换 GN。
小结
归一化技术的本质是「决定沿哪些维度计算均值与方差」。BN 跨 batch 聚合,适合大 batch 的 CNN;LN 在单样本整层聚合,适合 RNN 与 Transformer;IN 在单样本单通道聚合,适合风格迁移与生成;GN 在单样本的分组通道内聚合,适合小 batch 的视觉任务。它们并非互相排斥,而是同一思路在不同粒度上的体现:GN 在 G=C 时即 IN,在 G=1 时即 LN。实践中,先按任务类型选大类,再结合 batch size 与部署约束微调,往往就能得到稳定的训练效果。
参考与延伸阅读
- Ioffe, S. & Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. arXiv:1502.03167.
- Ba, J. L., Kiros, J. R., & Hinton, G. E. (2016). Layer Normalization. arXiv:1607.06450.
- Ulyanov, D., Vedaldi, A., & Lempitsky, V. (2016). Instance Normalization: The Missing Ingredient for Fast Stylization. arXiv:1607.08022.
- Wu, Y. & He, K. (2018). Group Normalization. arXiv:1803.08494.
- Santurkar, S., Tsipras, D., Ilyas, A., & Madry, A. (2018). How Does Batch Normalization Help Optimization? arXiv:1805.11604.(探讨 BN 收益来源,对 ICS 假设提出补充解释)
- PyTorch 官方文档:torch.nn 中的 BatchNorm2d、LayerNorm、InstanceNorm2d、GroupNorm 模块说明。