3、LayerNorm原理剖析:数学公式、与BatchNorm的核心区别、对序列长度的适应性

好,咱们进入正题。这一节我打算把LayerNorm(层归一化)彻底讲透。你可能会问,Transformer里为什么非它不可?BatchNorm不也挺香的吗?别急,我们一步步拆解。

3.1 数学公式:到底在归一化什么?

先看公式,别怕,其实很简单。对于一个输入向量 \( x \in \mathbb{R}^d \),LayerNorm的计算是:

μ = (1/d) * Σ(x_i)
σ² = (1/d) * Σ((x_i - μ)²)
y_i = (x_i - μ) / sqrt(σ² + ε) * γ + β

说白了,就是对每个样本的所有特征维度,算一个均值和方差,然后做标准化。最后再通过可学习的参数γ(缩放)和β(偏移)恢复一下表达能力。

嗯,这里要注意:均值和方差是沿着特征维度算的,不是沿着batch维度。这一点和BatchNorm有本质区别。

核心记忆点:LayerNorm是对每个样本自身做归一化,不依赖batch中的其他样本。

3.2 与BatchNorm的核心区别:一个靠兄弟,一个靠自己

BatchNorm(批归一化)是怎么做的?它是对每个特征维度,跨batch算均值和方差。你想想看,这意味着什么?

  • BatchNorm依赖batch size。 batch太小,统计量不稳定,训练容易崩。我在项目中遇到过,batch size设为2的时候,BN层直接让loss震荡到飞起。
  • BatchNorm对序列长度敏感。 NLP里句子长度不一,padding的存在让统计量变得很脏。你算均值的时候,把一堆0 padding也算进去了,这合理吗?
  • LayerNorm没有这些烦恼。 它只看当前样本自己的特征,batch size是1还是1024,对它没影响。

我个人的习惯是:在NLP任务里,无脑选LayerNorm。CV任务里BN还是主流,但到了Transformer时代,LN才是王道。

对比维度 BatchNorm LayerNorm
归一化方向 跨样本(batch维度) 跨特征(特征维度)
依赖batch size 是,小batch不稳定 否,单样本即可
对序列长度适应性 差,受padding影响 好,天然适配变长序列
训练与推理一致性 训练用batch统计,推理用全局统计 训练和推理完全一致
NLP中的表现 较差,已被淘汰 优秀,Transformer标配

我曾经踩过的坑: 有一次在文本分类任务里,我尝试用BatchNorm替换LayerNorm,想着能不能加速收敛。结果训练时loss降得挺快,但一到验证集上就崩了。后来排查发现,是因为推理时BN用的全局统计量和当前样本分布不匹配。从那以后,NLP任务我再也没碰过BN。

3.3 对序列长度的适应性:为什么LN是NLP的天选之子?

这个问题很关键。你想想看,NLP里句子长度是变化的。一个batch里可能有“你好”这种2个token的短句,也有“今天天气真不错,我们一起去公园散步吧”这种十几个token的长句。

如果用BatchNorm,它会怎么做?它会跨所有样本、所有时间步去算均值和方差。但padding的位置怎么办?你不得不搞一个mask机制,告诉BN“这些位置是填充的,别算进去”。麻烦不说,还容易出错。

LayerNorm就聪明多了。它对每个时间步(每个token)单独做归一化。也就是说,对于序列中的第t个位置,它只看这个位置的特征向量,自己算均值和方差。

# 伪代码示意
# 输入形状: [batch_size, seq_len, hidden_dim]
# LayerNorm对每个样本的每个时间步独立操作
for b in range(batch_size):
    for t in range(seq_len):
        x = input[b, t, :]  # 形状: [hidden_dim]
        mean = mean(x)
        var = var(x)
        output[b, t, :] = (x - mean) / sqrt(var + eps) * gamma + beta

你看,每个时间步都是独立的。长句子和短句子,在LayerNorm眼里没有区别。它根本不关心序列长度是多少,只关心当前这个token的特征分布。

一个小技巧: 在实际实现中,PyTorch的LayerNorm是支持多维输入的。你只需要指定归一化的维度即可。比如对于形状为[batch, seq_len, hidden_dim]的输入,设置normalized_shape=[hidden_dim]就行。它会自动对最后那个维度做归一化,非常方便。

我个人觉得,LayerNorm对序列长度的适应性,是它能在NLP领域大放异彩的根本原因。你想想看,Transformer要处理各种长度的句子,如果归一化层还跟序列长度强相关,那设计起来得多痛苦?

说白了,LayerNorm让模型不再关心“这个句子有多长”,只关心“这个token是什么”。这种解耦,正是NLP任务所需要的。

好,这一节就到这里。下一节我们聊聊LayerNorm在Transformer中的具体位置,以及为什么放在那里效果最好。