为什么LLM时代都使用RMSNorm和Pre-Norm?

结论:大语言模型的预训练过程中经常会出现不稳定的问题。深度学习方法通常会采用特定的归一化策略来加强神经网络训练过程的稳定性。RMSNorm的训练效果不差且训练更快;Post-Norm很难训练,容易导致梯度消失,而Pre-Norm更稳定。


归一化分类

Batch Normalization (批归一化)

位置:传统 CNN 中卷积层后,LLM 中极少使用。
公式
$$\mu_B = \frac{1}{B}\sum_{i=1}^B x_i, \quad \sigma_B^2 = \frac{1}{B}\sum_{i=1}^B (x_i - \mu_B)^2$$

$$\hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}, \quad y_i = \gamma \hat{x}_i + \beta$$

代码

1
2
batch_norm = nn.BatchNorm1d(dim)
output = batch_norm(x)

优点

  • 加速训练,缓解梯度消失。

缺点

  • 依赖批大小,小批量时不稳定。
  • 不适用于变长序列(如 NLP 任务)。

Layer Normalization (层归一化)

位置:Transformer 的每个子层(自注意力/前馈网络)的输出后,残差连接前(Post-LN),或残差连接后(Pre-LN)。
公式
$$\mu = \frac{1}{d}\sum_{i=1}^d x_i, \quad \sigma^2 = \frac{1}{d}\sum_{i=1}^d (x_i - \mu)^2 $$

$$\hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}}, \quad y_i = \gamma \hat{x}_i + \beta $$
代码

1
2
3
4
# PyTorch 实现
import torch.nn as nn
layer_norm = nn.LayerNorm(dim)
output = layer_norm(x)

优点

  • 对序列长度和批大小不敏感,适合变长文本。
  • 避免 Batch Norm 对小批量的依赖问题。

缺点

  • 对特征维度敏感,可能丢失通道间差异性。

在LayerNorm 的基础上,微软提出的 DeepNorm 在残差连接中对之前的激活值 𝒙 按照一定比例 𝛼 进行放缩。Transformer 的层数可以被成功地扩展至 1000 层,有效提升了模型性能与训练稳定性。公式如下,Sublayer 表示Transformer 层中的前馈神经网络或自注意力模块。

$$DeepNorm(𝒙) = LayerNorm(𝛼 · 𝒙 + Sublayer(𝒙))$$


RMS Normalization (Root Mean Square Layer Normalization均方根归一化)

位置:与 Layer Norm 类似,常用于 LLM(如 LLaMA)的前馈层后。
公式
$$\sigma = \sqrt{\frac{1}{d}\sum_{i=1}^d x_i^2 + \epsilon} $$

$$y_i = \frac{x_i}{\sigma} \cdot \gamma $$

Transformers 代码库中LLaMA 的RMSNorm 实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LlamaRMSNorm(nn.Module):
def __init__(self, hidden_size, eps=1e-6):
super().__init__()
self.weight = nn.Parameter(torch.ones(hidden_size))
self.variance_epsilon = eps

def forward(self, hidden_states):
input_dtype = hidden_states.dtype
hidden_states = hidden_states.to(torch.float32)
variance = hidden_states.pow(2).mean(-1, keepdim=True)
# 计算隐状态的均方根
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
# 将隐状态除以其均方根后重新缩放
return self.weight * hidden_states.to(input_dtype)

优点

  • 计算量小(无需计算均值),训练更快。
  • 在部分任务中表现优于 LayerNorm。

缺点

  • 缺少可学习的偏移参数(β),可能降低灵活性。

总结对比表

类型 计算维度 适用场景 优点 缺点
Layer Norm 特征维度(d) NLP、Transformer 对序列长度不敏感 可能丢失通道差异性
RMS Norm 特征维度(d) LLM(如 LLaMA) 计算高效,无均值中心化 缺少可学习偏移参数
Batch Norm 批维度(B) CNN 加速训练,稳定梯度 依赖批大小,不适合变长数据

归一化模块位置

层后归一化(Post-Layer Normalization, Post-Norm)

位置:Post-Norm 是在原始 Transformer 模型中用的一种归一化技术。被放置于残差计算之后。

公式
$$Post-Norm(𝒙) = Norm(𝒙 + Sublayer(𝒙))$$

优点

  • 加快网络训练收敛速度,减少训练时间。
  • 后向归一化可以降低神经网络对于超参数(如学习率、初始化参数等)的敏感性,使得网络更容易调优,并减少了超参数调整的难度。

缺点

  • 由于在输出层附近存在梯度较大的问题,Post-Norm在训练过程中通常会出现不稳定的现象。因此现有的大语言模型中Post-Norm很少被单独使用,通常是与其他策略相结合应用。例如,GLM-130B 将Post-Norm与DeepNorm 结合使用。

层前归一化(Pre-Layer Normalization, Pre-Norm)

位置将归一化模块应用在每个子层之前。Pre-Norm 在最后一个Transformer层后还额外添加了一个LayerNorm。

公式
$$Pre-Norm(𝒙) = 𝒙 + Sublayer(Norm(𝒙))$$

优点

  • 训练过程中更加稳定

缺点

  • 性能稍逊色于Post-Norm 的模型。当层数很大时,Pre-Norm的计算方式并没有达到有效增加模型网络深度的效果,而是等效于增加模型网络宽度。在神经网络里,同参数下网络的深度比宽度更重要,而Post-Norm的计算方式会有效增加模型深度。所以Pre-Norm 没有 Post-Norm效果好。

夹心归一化(Sandwich-Layer Normalization, Sandwich-Norm)

位置:在残差连接之前增加了额外的LayerNorm。Sandwich-Norm 可以看作是Pre-Norm 和Post-Norm 两种方法的组合。

公式
$$Sandwich-Norm(𝒙) = 𝒙 + Norm(Sublayer(Norm(𝒙)))$$

缺点

  • 有时仍然无法保证大语言模型的稳定训练,甚至会引发训练崩溃的问题。

参考: