BatchNorm 和 LayerNorm 有什么区别?
手写 BatchNorm

英文问法What's the difference between BatchNorm and LayerNorm? · Implement BatchNorm, in training and inference mode. · Why do Transformers use LayerNorm?

考过微软 Bing Ads AS2 2021 面经(用 tf.keras 手写 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、WD
统计量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)

必答点

追问

推理时忘了切 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