数学基础:均值与方差的计算
好,咱们进入正题。LayerNorm 的数学基础,说白了就是两个老朋友:均值和方差。你想想看,归一化操作的核心,不就是把数据拉回到一个稳定的分布上吗?那怎么描述分布?均值定中心,方差定范围。这两个概念搞不清楚,后面反向传播推导你肯定晕。
我个人习惯,讲数学之前先问个问题:为什么 LayerNorm 需要均值和方差? 因为神经网络里的数据,经过几层线性变换和激活函数后,分布早就歪了。有的神经元输出特别大,有的特别小。如果不做处理,梯度要么爆炸要么消失。嗯,这里要注意,均值和方差就是用来做「对齐」的尺子。
均值:数据的重心
均值,也叫期望。公式很简单:
μ = (1/N) * Σ x_i
就是把所有数加起来,除以个数。但我在项目中遇到过一个问题:均值对异常值非常敏感。比如你有一批特征,大部分在 0 到 1 之间,突然冒出来一个 1000。这个均值就会被拉得老高,归一化后正常数据反而被压扁了。所以实际工程中,有时候会用截断均值或者中位数替代,但 LayerNorm 里还是用标准均值,因为计算简单,反向传播好求导。
np.mean(x, axis=-1, keepdims=True),框架已经帮你处理好了。
方差:数据的离散程度
方差衡量数据偏离均值的程度。公式有两个版本,你都得记住:
σ² = (1/N) * Σ (x_i - μ)² # 总体方差
σ² = (1/(N-1)) * Σ (x_i - μ)² # 样本方差(无偏估计)
LayerNorm 用的是总体方差,也就是除以 N 而不是 N-1。为什么?因为我们在做归一化,不是做统计推断。你想想看,我们关心的是当前这批数据本身的分布,而不是用它去估计总体的方差。所以直接用 N 除,计算简单,反向传播也干净。
我曾经踩过一个坑:在实现自定义 LayerNorm 时,用了 torch.var 函数,默认是除以 N-1。结果模型训练 loss 死活降不下去。查了半天才发现方差算错了。嗯,这里要提醒你:用框架自带函数时,一定要看清楚参数。PyTorch 里 torch.var 默认无偏,torch.var(unbiased=False) 才是我们要的。
计算中的维度问题
LayerNorm 和 BatchNorm 最大的区别,就是统计量计算的维度不同。BatchNorm 对 batch 维度算,LayerNorm 对特征维度算。举个例子:
假设输入形状是 (batch_size, seq_len, hidden_dim),比如 (2, 3, 4)。
- BatchNorm:对每个特征位置,跨 batch 和 seq_len 算均值和方差。结果形状是 (1, 1, 4)。
- LayerNorm:对每个样本的每个位置,跨 hidden_dim 算均值和方差。结果形状是 (2, 3, 1)。
说白了,LayerNorm 是每个 token 自己做归一化,跟其他样本无关。这在 NLP 任务里特别有用,因为句子长度不一样,batch 里样本之间差异大,BatchNorm 容易不稳定。
代码实现:手写均值与方差
咱们来写个简单的实现,加深理解。假设输入 x 形状是 (batch, seq_len, hidden_dim):
import numpy as np
def layer_norm_stats(x):
# x: (batch, seq_len, hidden_dim)
# 计算均值,沿着最后一个维度
mean = np.mean(x, axis=-1, keepdims=True) # (batch, seq_len, 1)
# 计算方差,注意用总体方差
var = np.mean((x - mean) ** 2, axis=-1, keepdims=True) # (batch, seq_len, 1)
return mean, var
# 测试
x = np.random.randn(2, 3, 4)
mean, var = layer_norm_stats(x)
print("均值形状:", mean.shape) # (2, 3, 1)
print("方差形状:", var.shape) # (2, 3, 1)
你看,输出形状里保留了 seq_len 维度,每个位置都有自己的均值和方差。这就是 LayerNorm 的「逐样本、逐位置」归一化。
反向传播中的均值和方差
这里要提前打个预防针:反向传播时,均值和方差不是常数。它们依赖于输入 x,所以求梯度时,要对均值和方差也求导。很多初学者在这里翻车,以为归一化后的输出对 x 求导就是简单的线性关系。其实不是。
举个例子,假设归一化后的输出是:
y_i = (x_i - μ) / √(σ² + ε)
那么 ∂y_i / ∂x_j 就不是简单的 1/σ,因为 μ 和 σ² 都依赖于 x_j。具体推导我们后面章节会详细讲,但你现在要记住:均值和方差引入了全局依赖,每个输出 y_i 对每个输入 x_j 都有梯度贡献。
数值稳定性:ε 的作用
方差开根号后做分母,如果方差为 0,那就除零了。所以 LayerNorm 里会加一个小常数 ε,通常是 1e-5 或 1e-6。这个 ε 不能太大,否则归一化效果变差;也不能太小,否则数值不稳定。
我建议:ε 用 1e-5 起步。如果训练过程中出现 NaN,再调大。在混合精度训练(FP16)时,ε 可能需要调到 1e-3 甚至 1e-2,因为半精度浮点数的表示范围更小。
总结一下
均值和方差是 LayerNorm 的基石。你需要掌握:
- 均值:定中心,对异常值敏感
- 方差:定范围,用总体方差(除以 N)
- 维度:在最后一个特征维度上计算
- 反向传播:均值和方差也是变量,需要求导
- 数值稳定性:加 ε,注意精度
下一章,我们会把这些数学公式串起来,推导 LayerNorm 的完整前向和反向传播。准备好了吗?