2015年,Sergey Ioffe和Christian Szegedy在ICML上发表了一篇论文,提出了Batch Normalization。这篇论文后来成为深度学习领域被引用最多的工作之一。但很少有人注意到,这项最初为计算机视觉设计的技术,在自然语言处理领域却"水土不服"——Transformer选择了完全不同的Layer Normalization。

更令人惊讶的是,2025年CVPR的一篇论文发现,Transformer中的归一化层产生的输入-输出映射竟然类似于tanh函数,以至于用简单的 $\tanh(\alpha x)$ 就能替代复杂的归一化操作。这个发现动摇了"归一化层是神经网络必不可少的组件"这一共识。

为什么神经网络需要归一化?为什么Transformer选择了LayerNorm而不是BatchNorm?为什么LLaMA进一步简化为RMSNorm?这些问题背后,是深度学习十年来的技术博弈与认知演进。

一个被误解的概念:Internal Covariate Shift

归一化层的诞生,源于一个被称为Internal Covariate Shift(内部协变量偏移)的问题。

在机器学习中,“协变量偏移”(Covariate Shift)指的是训练数据和测试数据的输入分布不同。Ioffe和Szegedy将这个概念延伸到神经网络内部:当网络训练时,每一层的参数更新都会改变其后所有层的输入分布。

graph TD
    subgraph ICS["Internal Covariate Shift 问题示意"]
        A["输入数据 x"] --> B["第1层<br/>参数 θ₁"]
        B --> C["激活 a₁<br/>分布 P₁"]
        C --> D["第2层<br/>参数 θ₂"]
        D --> E["激活 a₂<br/>分布 P₂"]
        E --> F["第3层<br/>参数 θ₃"]
        F --> G["输出"]
        
        H["训练过程中<br/>θ₁, θ₂, θ₃ 更新"] --> I["P₁, P₂ 分布变化"]
        I --> J["后续层需要<br/>不断适应新分布"]
        
        style I fill:#ffcccc
        style J fill:#ffcccc
    end

用数学语言描述:假设网络第 $l$ 层的输入为 $x^{(l)}$,随着前面层参数 $\theta^{(1)}, \theta^{(2)}, ..., \theta^{(l-1)}$ 的更新,$x^{(l)}$ 的分布也在不断变化。这意味着第 $l$ 层需要不断适应新的输入分布,如同追逐一个移动的目标。

这个问题的直观后果是:深层网络训练困难,需要精心设计学习率和初始化策略。BatchNorm的解决方案是强制将每层的输入标准化为零均值、单位方差的分布,从而"固定"输入分布。

然而,学术界对Internal Covariate Shift的解释一直存在争议。2018年,Santurkar等人在NeurIPS上发表的论文"How Does Batch Normalization Help Optimization?“指出,BatchNorm有效的原因可能并不是因为它减少了Internal Covariate Shift,而是因为它使优化景观更加平滑,梯度更可预测。

这个争议揭示了深度学习研究的一个特点:一个技术可能在实践中非常有效,但其背后的理论解释可能并不完全准确。

BatchNorm:计算机视觉的基石

Batch Normalization的核心思想是:在 mini-batch 的维度上计算均值和方差,然后对每个特征进行标准化。

graph LR
    subgraph BN["BatchNorm 计算维度"]
        direction TB
        A["样本1"] --> A1["特征1 | 特征2 | 特征3"]
        B["样本2"] --> B1["特征1 | 特征2 | 特征3"]
        C["样本3"] --> C1["特征1 | 特征2 | 特征3"]
        D["样本4"] --> D1["特征1 | 特征2 | 特征3"]
        
        A1 --- E["↓ 沿样本维度计算统计量 ↓"]
        B1 --- E
        C1 --- E
        D1 --- E
        
        E --> F["μ₁, σ₁² | μ₂, σ₂² | μ₃, σ₃²"]
        
        style E fill:#e6f3ff
        style F fill:#cce5ff
    end

假设一个 mini-batch 有 $m$ 个样本,每个样本有 $d$ 个特征。对于第 $k$ 个特征,BatchNorm计算:

$$\mu_k = \frac{1}{m} \sum_{i=1}^{m} x_{i,k}$$$$\sigma_k^2 = \frac{1}{m} \sum_{i=1}^{m} (x_{i,k} - \mu_k)^2$$$$\hat{x}_{i,k} = \frac{x_{i,k} - \mu_k}{\sqrt{\sigma_k^2 + \epsilon}}$$

然后通过可学习的参数进行缩放和平移:

$$y_{i,k} = \gamma_k \hat{x}_{i,k} + \beta_k$$

这里 $\gamma$ 和 $\beta$ 是可学习参数,$\epsilon$ 是防止除零的小常数。

BatchNorm的一个关键特性是:训练时使用当前 mini-batch 的统计量,推理时使用训练过程中累积的全局统计量(移动平均)。这种设计在计算机视觉中工作得很好,因为:

  1. 图像数据通常是固定大小的,batch中的每个样本维度相同
  2. 视觉任务中batch size通常较大(如32、64、128),统计量估计准确
  3. 卷积层后使用BatchNorm已成为标准做法

但在自然语言处理领域,BatchNorm遇到了根本性的困难。

LayerNorm:Transformer的必然选择

当Transformer在2017年提出时,它选择了Layer Normalization而不是Batch Normalization。这个选择并非偶然。

LayerNorm由Jimmy Lei Ba、Jamie Ryan Kiros和Geoffrey Hinton在2016年提出。与BatchNorm跨样本计算统计量不同,LayerNorm在每个样本内部计算统计量:

graph LR
    subgraph LN["LayerNorm 计算维度"]
        direction TB
        A["样本1"] --> A1["特征1 | 特征2 | 特征3"]
        B["样本2"] --> B1["特征1 | 特征2 | 特征3"]
        C["样本3"] --> C1["特征1 | 特征2 | 特征3"]
        
        A1 --> E["→ 沿特征维度计算 →"]
        A1 --> F["μ₁, σ₁²"]
        
        B1 --> G["→ 沿特征维度计算 →"]
        B1 --> H["μ₂, σ₂²"]
        
        C1 --> I["→ 沿特征维度计算 →"]
        C1 --> J["μ₃, σ₃²"]
        
        style F fill:#cce5ff
        style H fill:#cce5ff
        style J fill:#cce5ff
    end
$$\mu_i = \frac{1}{d} \sum_{j=1}^{d} x_{i,j}$$$$\sigma_i^2 = \frac{1}{d} \sum_{j=1}^{d} (x_{i,j} - \mu_i)^2$$$$y_{i,j} = \gamma_j \frac{x_{i,j} - \mu_i}{\sqrt{\sigma_i^2 + \epsilon}} + \beta_j$$

注意关键区别:BatchNorm对每个特征跨样本归一化,LayerNorm对每个样本跨特征归一化。

这个看似简单的变化,解决了NLP任务中的三个核心问题:

变长序列问题。NLP中的句子长度各不相同。如果使用BatchNorm,不同batch中参与计算的token数量不同,归一化常数不稳定,导致训练不稳定。LayerNorm对每个token独立计算,完全不受序列长度影响。

小批量问题。大语言模型训练时,由于显存限制,batch size往往较小(如1-4)。BatchNorm在小batch下统计量估计不准确,性能急剧下降。LayerNorm不依赖batch size,即使batch size为1也能正常工作。

推理一致性。BatchNorm在训练和推理时行为不同(训练用batch统计量,推理用全局统计量),这种不一致可能导致性能下降。LayerNorm在训练和推理时计算方式完全相同,没有这个问题。

import torch
import torch.nn as nn

class LayerNorm(nn.Module):
    def __init__(self, dim, eps=1e-5):
        super().__init__()
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))
        self.bias = nn.Parameter(torch.zeros(dim))
    
    def forward(self, x):
        # x shape: (batch_size, seq_len, dim)
        mean = x.mean(dim=-1, keepdim=True)
        var = x.var(dim=-1, keepdim=True, unbiased=False)
        x_norm = (x - mean) / torch.sqrt(var + self.eps)
        return x_norm * self.weight + self.bias

Pre-Norm还是Post-Norm:位置之争

原始Transformer(Post-Norm)将LayerNorm放在残差连接之后:

$$\text{output} = \text{LayerNorm}(x + \text{Sublayer}(x))$$

但2020年,Xiong等人在论文"On Layer Normalization in the Transformer Architecture"中发现,这种设计会导致训练不稳定。他们用均值场理论(Mean Field Theory)证明:在初始化时,Post-LN Transformer靠近输出层的参数梯度期望值很大,使用大学习率会导致训练不稳定,因此需要学习率warm-up阶段。

解决方案是将LayerNorm放在残差连接之前(Pre-Norm):

$$\text{output} = x + \text{Sublayer}(\text{LayerNorm}(x))$$
graph TD
    subgraph PostNorm["Post-Norm (原始Transformer)"]
        A1["输入 x"] --> B1["子层操作<br/>Attention/FFN"]
        A1 --> C1["残差连接 (+)"]
        B1 --> C1
        C1 --> D1["LayerNorm"]
        D1 --> E1["输出"]
    end
    
    subgraph PreNorm["Pre-Norm (现代Transformer)"]
        A2["输入 x"] --> B2["LayerNorm"]
        B2 --> C2["子层操作<br/>Attention/FFN"]
        A2 --> D2["残差连接 (+)"]
        C2 --> D2
        D2 --> E2["输出"]
    end
    
    PostNorm -.->|"梯度需穿过LayerNorm"| F["梯度流动受阻碍"]
    PreNorm -.->|"梯度直接传递"| G["梯度流动顺畅"]

Pre-Norm的优势可以用梯度流动来解释。在Post-Norm中,梯度需要穿过LayerNorm才能传递到前面的层,而LayerNorm会重新缩放梯度。在Pre-Norm中,梯度可以通过残差连接无损地向前传递,因为残差路径上没有任何操作。

graph LR
    subgraph GradFlow["梯度流动对比"]
        direction TB
        A["Post-Norm 梯度"] --> B["← 梯度穿过LayerNorm被缩放"]
        B --> C["← 梯度穿过子层"]
        C --> D["← 梯度穿过残差"]
        D --> E["← 梯度到达前面层<br/>可能消失或爆炸"]
        
        F["Pre-Norm 梯度"] --> G["← 梯度穿过LayerNorm被缩放"]
        G --> H["← 梯度穿过子层"]
        I["← 梯度通过残差直接传递"] --> J["无损传递到前面层"]
        F --> I
        
        style E fill:#ffcccc
        style J fill:#ccffcc
    end

这个发现解释了为什么现代大模型(GPT-2之后、LLaMA等)都采用Pre-Norm架构:它允许直接使用大学习率训练,不需要warm-up阶段,训练更加稳定。

当然,Pre-Norm也有代价。有研究发现Pre-Norm可能导致"表征崩塌”——后面层的表征可能变得相似,降低了模型的表示能力。但在实践中,训练稳定性的收益往往大于这个代价。

RMSNorm:更简单的选择

2020年,Zhang和Sennrich在论文"Root Mean Square Layer Normalization"中提出了RMSNorm,这是一个对LayerNorm的简化。

他们的核心洞察是:LayerNorm有两个功能——重新居中(re-centering,通过减去均值)和重新缩放(re-scaling,通过除以标准差)。re-centering真的必要吗?

实验表明,只需要re-scaling就够了。RMSNorm的计算公式:

$$\text{RMSNorm}(x) = \gamma \odot \frac{x}{\sqrt{\frac{1}{d}\sum_{i=1}^{d}x_i^2 + \epsilon}}$$
graph TD
    subgraph Compare["LayerNorm vs RMSNorm 计算对比"]
        A["输入 x"] --> B["LayerNorm"]
        A --> C["RMSNorm"]
        
        B --> D["1. 计算均值 μ"]
        D --> E["2. 计算方差 σ²"]
        E --> F["3. 标准化: (x-μ)/σ"]
        F --> G["4. 缩放平移: γ·x̂ + β"]
        
        C --> H["1. 计算RMS"]
        H --> I["2. 缩放: x/RMS"]
        I --> J["3. 乘权重: γ·x/RMS"]
        
        style D fill:#ffe6e6
        style G fill:#ffe6e6
        style H fill:#e6ffe6
        style J fill:#e6ffe6
    end

与LayerNorm相比,RMSNorm省略了均值计算,只计算均方根(RMS)进行缩放。

这个简化带来了两个好处:

计算效率。不需要计算均值,减少了一次reduction操作。在大模型训练中,这个节省是显著的。论文报告RMSNorm比LayerNorm快7%-64%。

更稳定的训练。有研究表明,在残差连接的场景中,LayerNorm的re-centering操作可能导致信息丢失,而RMSNorm避免了这个问题。

LLaMA系列模型选择了RMSNorm,这个选择背后是效率和稳定性的权衡。在千亿参数规模的模型中,每一个计算的简化都意味着显著的资源节省。

import torch
import torch.nn as nn

class RMSNorm(nn.Module):
    def __init__(self, dim, eps=1e-6):
        super().__init__()
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))
    
    def forward(self, x):
        # 计算均方根
        rms = torch.rsqrt(x.pow(2).mean(dim=-1, keepdim=True) + self.eps)
        return x * rms * self.weight

归一化方法的完整版图

理解归一化方法的关键是搞清楚它们在哪个维度上计算统计量。考虑一个形状为 $(N, C, H, W)$ 的四维张量(图像)或 $(N, L, D)$ 的三维张量(文本):

graph TD
    subgraph Methods["归一化方法分类"]
        A["归一化方法"] --> B["BatchNorm (BN)"]
        A --> C["LayerNorm (LN)"]
        A --> D["InstanceNorm (IN)"]
        A --> E["GroupNorm (GN)"]
        A --> F["RMSNorm"]
        
        B --> B1["跨样本计算<br/>适合大批量视觉任务"]
        C --> C1["跨特征计算<br/>适合NLP/序列任务"]
        D --> D1["跨空间计算<br/>适合风格迁移"]
        E --> E1["分组计算<br/>适合小批量视觉任务"]
        F --> F1["仅缩放<br/>现代LLM首选"]
        
        style B fill:#e6f3ff
        style C fill:#e6ffe6
        style F fill:#fff3e6
    end

Batch Normalization (BN):在 $N$ 维度上计算,对每个通道独立归一化。适合大批量的视觉任务,但对小batch敏感,训练/推理行为不一致。

Layer Normalization (LN):在 $C \times H \times W$ 或 $D$ 维度上计算,对每个样本独立归一化。适合NLP任务,不受batch size影响,训练/推理一致。

Instance Normalization (IN):在 $H \times W$ 维度上计算,对每个样本的每个通道独立归一化。主要用于风格迁移任务。

Group Normalization (GN):将通道分组,在每组内的 $H \times W$ 上计算。Kaiming He和Yuxin Wu在2018年提出,解决了BN在小batch下的问题,在目标检测、分割等任务中表现良好。

RMS Normalization:LayerNorm的简化版本,不计算均值,只计算均方根进行缩放。被LLaMA、Mistral等现代LLM广泛采用。

graph LR
    subgraph Dimensions["各方法归一化维度示意 (图像 tensor: N×C×H×W)"]
        direction TB
        subgraph BN["BatchNorm"]
            BN1["沿 N 轴<br/>每个通道独立"]
        end
        subgraph LN["LayerNorm"]
            LN1["沿 C×H×W 轴<br/>每个样本独立"]
        end
        subgraph IN["InstanceNorm"]
            IN1["沿 H×W 轴<br/>每个样本每个通道独立"]
        end
        subgraph GN["GroupNorm"]
            GN1["分组后沿 H×W 轴<br/>每组独立"]
        end
    end
graph TD
    subgraph Timeline["归一化技术发展时间线"]
        A["2015<br/>BatchNorm<br/>Ioffe & Szegedy"] --> B["2016<br/>LayerNorm<br/>Ba, Kiros & Hinton"]
        B --> C["2017<br/>InstanceNorm用于风格迁移"]
        C --> D["2018<br/>GroupNorm<br/>Wu & He"]
        D --> E["2019<br/>RMSNorm<br/>Zhang & Sennrich"]
        E --> F["2020<br/>Pre-Norm理论<br/>Xiong et al."]
        F --> G["2023<br/>LLaMA采用RMSNorm"]
        G --> H["2025<br/>Dynamic Tanh<br/>Zhu et al."]
    end

Dynamic Tanh:归一化层真的必要吗?

2025年CVPR的一篇论文"Transformers without Normalization"提出了一个惊人的发现:Transformer中的归一化层产生的输入-输出映射类似于tanh函数。

研究者观察到,LayerNorm的输出可以近似表示为:

$$\text{LayerNorm}(x) \approx \tanh(\alpha x)$$
graph TD
    subgraph DyT["LayerNorm vs Dynamic Tanh"]
        A["输入 x"] --> B["LayerNorm"]
        A --> C["Dynamic Tanh"]
        
        B --> D["计算均值 μ"]
        D --> E["计算方差 σ²"]
        E --> F["标准化 (x-μ)/σ"]
        F --> G["缩放平移 γx̂ + β"]
        G --> H["输出 ~ tanh(αx)"]
        
        C --> I["DyT(x) = tanh(αx)"]
        I --> J["输出"]
        
        style H fill:#ffe6e6
        style J fill:#e6ffe6
    end

基于这个观察,他们提出了Dynamic Tanh (DyT):

$$\text{DyT}(x) = \tanh(\alpha x)$$

其中 $\alpha$ 是一个可学习的参数。这个简单的操作可以直接替代LayerNorm或RMSNorm,在图像分类、语言模型、自监督学习等多种任务上取得了与归一化层相当甚至更好的性能。

这个发现挑战了"归一化层是神经网络必不可少的组件"这一共识。它表明,归一化层的核心作用可能只是提供一个S形的非线性变换,限制激活值的范围,防止极端值的出现。

当然,DyT目前还处于研究阶段,大规模工业应用的可行性还需要更多验证。但这个发现无疑加深了我们对归一化层本质的理解。

如何选择归一化方法

在实际应用中,选择哪种归一化方法需要考虑多个因素:

graph TD
    subgraph Decision["归一化方法选择决策树"]
        A["任务类型?"] --> B["视觉任务"]
        A --> C["NLP/序列任务"]
        
        B --> D["Batch Size?"]
        D -->|"大 (32+)"| E["BatchNorm"]
        D -->|"小 (<32)"| F["GroupNorm"]
        
        C --> G["模型规模?"]
        G -->|"超大模型"| H["RMSNorm + Pre-Norm"]
        G -->|"中小模型"| I["LayerNorm + Pre-Norm"]
        
        style E fill:#e6f3ff
        style F fill:#fff3e6
        style H fill:#e6ffe6
        style I fill:#ffe6f3
    end

任务类型:计算机视觉任务通常选择BatchNorm(大批量)或GroupNorm(小批量);NLP和序列建模任务选择LayerNorm或RMSNorm。

Batch Size:大批量(32+)可用BatchNorm;小批量用LayerNorm/RMSNorm/GroupNorm。

序列长度:变长序列必须用LayerNorm/RMSNorm,BatchNorm无法处理。

模型规模:超大模型倾向于RMSNorm,计算效率更高。

训练稳定性:Pre-Norm架构比Post-Norm更稳定,适合深层网络。

一个实用的经验法则:如果你的任务是NLP或使用Transformer架构,默认选择Pre-Norm + RMSNorm;如果任务是计算机视觉且batch size较大,选择BatchNorm;如果batch size较小,选择GroupNorm。

从技术演进看深度学习

归一化层的十年演进,折射出深度学习领域的技术发展规律。

BatchNorm的提出源于对Internal Covariate Shift的理论分析,但后来的研究表明,它有效的真正原因可能更加复杂。LayerNorm的选择最初更多是工程直觉,后来才有了Pre-Norm优于Post-Norm的理论解释。RMSNorm的简化更是直接质疑了"标准做法"的必要性。而Dynamic Tanh的发现则彻底挑战了归一化层的必要性。

graph LR
    subgraph Evolution["认知演进"]
        A["2015<br/>BatchNorm解决<br/>Internal Covariate Shift"] --> B["2018<br/>BatchNorm真正原因<br/>是平滑优化景观"]
        B --> C["2020<br/>Pre-Norm比Post-Norm<br/>梯度更稳定"]
        C --> D["2020<br/>RMSNorm质疑<br/>re-centering必要性"]
        D --> E["2025<br/>Dynamic Tanh质疑<br/>归一化层必要性"]
    end

这个过程说明:深度学习技术往往先在实践中证明有效,理论解释随后跟上,有时甚至会发现最初的解释并不准确。这要求实践者既要理解技术原理,又要保持开放心态,随时准备接受新的发现。

对于今天的模型开发者来说,理解归一化层的原理和权衡,比记住"应该用哪个"更重要。因为正确的选择永远取决于具体场景,而技术的最佳实践也在不断演进。


参考文献

  1. Ioffe, S., & Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. ICML 2015.
  2. Ba, J. L., Kiros, J. R., & Hinton, G. E. (2016). Layer Normalization. arXiv:1607.06450.
  3. Xiong, R., et al. (2020). On Layer Normalization in the Transformer Architecture. ICML 2020.
  4. Zhang, B., & Sennrich, R. (2019). Root Mean Square Layer Normalization. NeurIPS 2019.
  5. Wu, Y., & He, K. (2018). Group Normalization. ECCV 2018.
  6. Santurkar, S., et al. (2018). How Does Batch Normalization Help Optimization? NeurIPS 2018.
  7. Zhu, J., et al. (2025). Transformers without Normalization. CVPR 2025.
  8. Vaswani, A., et al. (2017). Attention Is All You Need. NeurIPS 2017.
  9. Radford, A., et al. (2019). Language Models are Unsupervised Multitask Learners. OpenAI Technical Report.
  10. Touvron, H., et al. (2023). LLaMA: Open and Efficient Foundation Language Models. arXiv:2302.13971.