BatchNorm 和 LayerNorm 有什么区别?
手写 BatchNorm
先弄清楚:每个概念是什么
- Normalization(标准化)
- 减均值、除以标准差,把一组数变成 mean 0、variance 1。
- BatchNorm
- 对每个 feature,拿 batch 里所有 sample 的这一维一起算。CNN 里每个 channel 一组,在 batch 和所有像素位置上一起算。
- LayerNorm
- 对每个 sample(Transformer 里是每个 token),拿它自己的所有 feature 一起算,不看别的 sample。
- γ 和 β(learnable scale、shift)
- 标准化后再乘 γ、加 β,让网络自己决定输出的大小和偏移。γ = σ、β = μ 时正好还原原输入,不损失表达能力。
- Running mean / variance
- BatchNorm 训练时用当前 batch 的统计量,同时用 EMA 记一份,eval 时只用这份。
30 秒回答
Both normalize activations to zero mean and unit variance, then apply a learnable scale γ and shift β; the difference is the axis. BatchNorm computes statistics per feature, or per channel in a CNN, across the batch, so it depends on the batch: training uses batch statistics and updates running averages, which are used at inference. LayerNorm computes statistics per sample across its features, so it behaves the same in training and inference and works with any batch size. That's why CNNs use BatchNorm, while RNNs and Transformers use LayerNorm.
关键公式
BatchNorm:每个 feature \(j\),沿 batch 的 \(m\) 个 sample
\[ \mu_j = \frac1m\sum_{i=1}^{m} x_{ij},\qquad \sigma_j^2 = \frac1m\sum_{i=1}^{m}(x_{ij}-\mu_j)^2 \] \[ y_{ij} = \gamma_j\,\frac{x_{ij}-\mu_j}{\sqrt{\sigma_j^2+\epsilon}} + \beta_j \]LayerNorm 公式一样,只是改成沿 \(j\) 求和,每个 sample 在自己的 \(D\) 个 feature 上算一组 \(\mu, \sigma\)。
Running statistics(只有 BatchNorm 有)
\[ \hat\mu \leftarrow (1-\alpha)\,\hat\mu + \alpha\,\mu_B \]\(\hat\sigma^2\) 同理,但存 unbiased 的 \(\tfrac{m}{m-1}\sigma_B^2\);\(\alpha\) 即 PyTorch 的 momentum,默认 0.1。
沿哪个轴:一个例子
3 个 sample(行)、2 个 feature(列):
\[ X = \begin{pmatrix} 1 & 10 \\ 2 & 20 \\ 3 & 30 \end{pmatrix} \]| 怎么算 | 结果 | |
|---|---|---|
| BatchNorm:按列 | 第 1 列 mean 2、var 2/3;第 2 列 mean 20、var 200/3 | 两列都是 −1.22、0、1.22 |
| LayerNorm:按行 | 第 1 行 mean 5.5、std 4.5,(1 − 5.5)/4.5 = −1 | 每行都是 −1、1 |
换成真实 shape:
| BatchNorm(CNN) | LayerNorm(Transformer) | |
|---|---|---|
| 输入 | (N, C, H, W) = (8, 16, 32, 32) | (B, T, D) = (4, 10, 512) |
| 沿哪些维平均 | N、H、W | D |
| 统计量 | 16 组,每组 8192 个数 | 40 组,每组 512 个数 |
手撕代码(NumPy)
def batchnorm(x, gamma, beta, run, train, mom=0.1, eps=1e-5):
# x: (N, D)。CNN:axis=(0,2,3), keepdims=True,n=N·H·W
if train:
mu, var = x.mean(0), x.var(0) # biased var
n = x.shape[0]
run["mean"] = (1 - mom) * run["mean"] + mom * mu
run["var"] = (1 - mom) * run["var"] + mom * var * n / (n - 1)
else:
mu, var = run["mean"], run["var"]
return gamma * (x - mu) / np.sqrt(var + eps) + beta
# LayerNorm:没有 running stats,train/eval 一样,只换轴:
# mu, var = x.mean(-1, keepdims=True), x.var(-1, keepdims=True)
必答点
- 同一个公式,区别只在沿哪个轴算 \(\mu, \sigma\):BatchNorm 沿 batch,LayerNorm 沿 feature
- BatchNorm train 用 batch stats 并更新 running stats,eval 用 running stats;LayerNorm 两种模式一样
- BatchNorm 依赖 batch size → CNN;LayerNorm 与 batch 无关 → RNN、Transformer
- 都有 learnable γ、β
- 作用:能用更大 learning rate;原论文说减少 internal covariate shift,Santurkar et al. 2018 认为主要是 loss landscape 更 smooth
追问
推理时忘了切 eval 模式会怎样?
BatchNorm 仍用当前 batch 的统计量,同一张图的预测会随同 batch 的其他样本变。batch 只有 1 个样本时 \(x-\mu=0\),FC 层后的 BatchNorm 输出全等于 β。
Transformer 为什么用 LayerNorm?
sequence 长短不一、batch 小,按 batch 算的统计量不稳。用在 RNN 上还得每个 time step 存一组,测试序列更长就没得用(LayerNorm 原文 §3.1)。LLaMA 用 RMSNorm,不减均值,只除以 \(\sqrt{\tfrac1D\sum_j x_j^2}\)。
batch 很小怎么办?
换 GroupNorm,channel 分组,每个 sample 每组单独算。只分 1 组就是 LayerNorm(Murphy §14.2.4.2)。
BatchNorm 的 backward 怎么写?
记 \(\sigma=\sqrt{\sigma_B^2+\epsilon}\),沿 batch 求和:\(dx = \frac{\gamma}{m\sigma}\big(m\,dy - \sum dy - \hat x\sum dy\,\hat x\big)\),\(d\gamma = \sum dy\,\hat x\),\(d\beta = \sum dy\)。原论文 p.4 有 chain rule。
来源Ioffe & Szegedy 2015 Alg. 1–2、§3.1(pp.3–4)· Ba et al. 2016 §3–3.1(pp.2–3)· Santurkar et al. 2018 abstract · Zhang & Sennrich 2019(RMSNorm)eq. 4 · Touvron et al. 2023(LLaMA)§2.2 · d2l §8.5 · Murphy, PML1 §14.2.4(pp.476–479)· PyTorch BatchNorm2d