🧠 图解记忆:LayerNorm 先中心化再缩放,RMSNorm 只按均方根缩放;点击图片可查看原图。
LayerNorm = 对每个样本的每个位置,沿特征维度做标准化;RMSNorm 是其简化版,去掉了均值中心化,只保留归一化。
两者的计算公式对比
LayerNorm(x):
μ = mean(x, dim=-1) # 计算均值
σ² = var(x, dim=-1) # 计算方差
x̂ = (x - μ) / √(σ² + ε) # 标准化
output = γ * x̂ + β # 可学习的缩放+平移
RMSNorm(x):
r = RMS(x) = √(mean(x²) + ε) # 均方根(不含均值中心)
x̂ = x / r # 归一化
output = γ * x̂ # 只有缩放(没有β偏置)关键区别
| 维度 | LayerNorm | RMSNorm |
|---|---|---|
| 均值中心化 | ✅ 减去均值 | ❌ 不减 |
| 参数数量 | 2个/层(γ + β) | 1个/层(仅 γ) |
| 计算量 | 稍大(多一次均值计算) | 更小 |
| 效果 | 几乎相同 | 基本等价甚至略好 |
| 使用现状 | GPT-2, BERT | LLaMA, Qwen, DeepSeek, Claude |
为什么 RMSNorm 更流行?
- 计算更快:省掉均值计算,推理时 Faster
- 参数更少:少一半参数(没有 β),减少过拟合风险
- 数值稳定性足够:对大多数架构,去均值带来的收益极小
- 实验验证:LLaMA 论文实证发现两者效果几乎一致,RMSNorm 略胜
python
# RMSNorm 简洁实现
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):
# x: [batch, seq, hidden]
rms = torch.rsqrt(torch.mean(x ** 2, dim=-1, keepdim=True) + self.eps)
return self.weight * x * rms # γ * (x / RMS(x))面试加分点
- 有些模型采用 混合方案:Attention 层用 RMSNorm,FFN 层用 LayerNorm(如部分 Qwen 变体)
- SwiGLU 激活函数常与 RMSNorm 一起出现,组成现代 Transformer Block 的标准配置:
x -> RMSNorm -> SwiGLU(FFN) -> Residual
面试话术:
"LayerNorm 和 RMSNorm 的核心区别是:LayerNorm 做了均值中心化+方差归一化,RMSNorm 只做 RMS 归一化。实践证明两者效果几乎一样,但 RMSNorm 少算了一步均值、少一半参数,所以现在的主流模型(LLaMA/Qwen/DeepSeek)都切到了 RMSNorm。我在本地跑 llama.cpp 的时候也能感受到微妙的速度提升。"
