前言
归一化技术在深度学习模型训练中扮演着至关重要的角色。在 LLaMA 等大规模语言模型中,原始 Transformer 架构中的 LayerNorm 逐渐被 RMSNorm 取代。本文将系统梳理归一化的核心逻辑,对比 LayerNorm 与 RMSNorm 的原理差异,并分析代码实现细节。
归一化的基本逻辑
归一化的核心目的是消除数据间的量纲差异,使数据分布不受极端值影响,同时保持原始数据的拓扑结构不变。在深度学习中,它主要有以下作用:
- 稳定数值范围,避免极大或极小值干扰
- 加速模型收敛过程
- 有效缓解梯度消失和梯度爆炸问题
- 间接降低内存占用(配合低精度训练时)
梯度与参数更新的稳定性
归一化之所以能提升优化稳定性,本质是通过统一数据数值范围,解决了梯度计算与参数更新中的'量级失衡'问题。未归一化数据的'大数值输入'会导致'梯度幅值异常',进而破坏参数更新的平稳性。
以简单的线性映射 y = Wx + b 为例,MSE 损失函数对权重 W 的梯度公式显示,梯度的幅值与输入 xi 的幅值成正比。若输入是未归一化的大数值,即使预测误差不大,梯度也会被放大,导致参数更新步长过大,引发模型震荡。
此外,不同特征维度量级不一致也会导致梯度失衡。例如收入(万级)和年龄(十级)作为输入时,高量级特征对应的参数梯度会远大于低量级特征,使模型过度关注高量级特征。归一化后各维度数值范围统一,参数梯度量级趋于平衡。
激活函数的梯度饱和也是关键因素。Sigmoid、Tanh 等函数在输入数值过大或过小时导数趋近于 0。归一化将输入限制在合理范围,确保激活函数处于线性区,梯度能有效传递。
总结:归一化稳定优化的逻辑链
简言之,归一化的核心价值是通过'数值校准',让梯度计算与参数更新的'尺度匹配',从根源上解决了深度学习优化中'量级失衡'导致的不稳定问题。
LayerNorm 详解
Transformer 中 LayerNorm 的核心原理是按'单个样本的特征维度'做归一化,而非按'批次维度'。这与 BatchNorm 有本质区别。
核心原理
LayerNorm 的本质是对单个样本的最后一维(特征维度)做归一化,将特征分布拉至均值为 0、方差为 1,再通过可学习的缩放/偏移参数恢复特征表达能力。
公式如下: μ = (1/d) * Σxi (特征维度均值) σ² = (1/d) * Σ(xi - μ)² (特征维度方差) x̂ = (x - μ) / √(σ² + ε) (归一化,ε防除 0) y = γ · x̂ + β (缩放 + 偏移,γ/β可学习)
其中 d 为特征维度,γ 和 β 是可训练参数,ε 是极小值(如 1e-12)。
代码实现细节
下面是标准 Layer Normalization 的核心逻辑实现,适配了工程上的精度需求:
class DebertaLayerNorm(nn.Module):
def __init__(self, size, eps=1e-12):
super().__init__()
# 初始化可学习的缩放参数γ(weight):初始值全 1,维度=特征维度 size
self.weight = nn.Parameter(torch.ones(size))
# 初始化可学习的偏移参数β(bias):初始值全 0,维度=特征维度 size
self.bias = nn.Parameter(torch.zeros(size))
# 防除零的极小值ε
self.variance_epsilon = eps
def forward(self, hidden_states):
input_type = hidden_states.dtype
hidden_states = hidden_states.()
mean = hidden_states.mean(-, keepdim=)
variance = (hidden_states - mean).().mean(-, keepdim=)
hidden_states = (hidden_states - mean) / torch.sqrt(variance + .variance_epsilon)
hidden_states = hidden_states.to(input_type)
y = .weight * hidden_states + .bias
y


