Batch Normalization 和 Layer Normalization 有什么用?

为什么你的网络越深越难训练?
上次聊了优化器——模型怎么知道自己该往哪个方向走。
方向有了,但还有个问题:路平不平?
我第一次训练10层网络的时候,前几轮还能正常收敛,跑到第5轮突然就开始剧烈震荡。学习率设得也不大啊,当时就懵了。查了半天发现,问题出在数据分布上。
深度网络的"多米诺骨牌"—— Internal Covariate Shift
先说个概念:Internal Covariate Shift,简称 ICS。
ICS是什么意思?直白点说:网络越深,每一层的输入数据分布都在飘。
拿个10层网络举例。第一层吃的是原始数据,分布还算稳。但经过第一层变换后,输出的分布就变了。第二层拿到这堆"变了味"的数据,再一变,分布又变了。
就这么一层层传下去,每层都在接收"不同分布"的输入。
这会导致什么?
后层网络得不停地适应前层输出的变化。就像接力赛,每棒运动员都在改变交接棒的规格——重量、形状、速度都在变。刚适应完,第三棒又换了。
反向传播的时候更难受。梯度从后往前传,每过一层都会叠加前面参数变化的影响。前层参数在不断学,后层过来的梯度也在不断变。
运气不好的时候,梯度直接炸了(爆炸),运气更差的时候,梯度直接没了(消失)。
这就是深层网络训练困难的根子。我当年踩过这个坑,debug了好几天才想明白。

Batch Normalization——按"特征"统一度量标准
怎么解决这个问题?
2015年,Sergey Ioffe和Christian Szegedy搞出了Batch Normalization,简称BN。
思路很简单:在每层输出后面,加个"标准化"操作,让数据分布稳下来。
具体怎么搞?
BN是在batch维度上做归一化的。也就是说,它把同一个特征在不同样本上的值拿出来,一起算均值和方差,然后归一化。
来个数值的例子。假设batch有4个样本,某层的某个神经元输出值分别是 [2, 4, 6, 8]。
BN先算均值:μ = (2 + 4 + 6 + 8) / 4 = 5
再算方差:σ² = [(2-5)² + (4-5)² + (6-5)² + (8-5)²] / 4 = 5
然后归一化:(x - μ) / σ = [-3/√5, -1/√5, 1/√5, 3/√5]
处理完之后,这4个样本在该特征上的分布就变成了均值0、方差1的标准分布。

有个关键点要记住:BN保留了什么?
同特征跨样本的大小关系。
就像评委打分的时候,把所有选手的某一轮得分标准化,这样横向一比就知道谁表现更好。BN保留的正是这种"所有学生里谁数学最强"的能力。
BN破坏了什么?
同样本跨特征的相对大小关系。
同一张图里,"眼睛"特征和"鼻子"特征的原始值可能差很多。BN之后,这两个特征的相对大小关系可能就变了。
在图像任务里问题不大,因为像素之间的关系本来就没那么讲究。但在NLP任务里这就麻烦了——词和词之间的相对大小往往承载着语义信息。
还有一点:BN需要足够大的batch size才能稳定估计统计量。batch太小的话,均值方差估计不准,归一化效果就差。我之前用batch=4跑BERT实验,效果烂得不行,后来才知道是这个问题。
所以什么场景适合BN?
大batch的图像分类任务。像ResNet、EfficientNet这些,大batch训起来效果很好。
Layer Normalization——按"个体"归一化,每个样本独立
BN好归好,有个致命问题:它依赖batch。
小batch怎么办?序列任务怎么办?NLP里每个样本长度都不一样,又该怎么办?
Layer Normalization,简称LN,就是来解决这个问题的。
LN的思路完全不同:不对batch维度下手,而是在单个样本的所有特征维度上做归一化。
还是那个例子。假设单个样本的输出向量是 [2, 4, 6, 8]。
LN算均值:μ = (2 + 4 + 6 + 8) / 4 = 5
算方差:σ² = 5
归一化:(x - μ) / σ = [-3/√5, -1/√5, 1/√5, 3/√5]
计算过程看起来一样,区别在哪?
计算范围不同。
BN是把同一个特征在batch里所有样本上的值放一起算均值方差。LN是把同一个样本所有特征的值放一起算均值方差。
这意味着什么?
意味着LN不需要batch,每个样本独立计算,互不影响。
类比一下:对学生各科成绩分别标准化,保留单个人各科目之间的相对优劣。语文强的还是强,数学弱的还是弱。

LN适合什么场景?
时序数据、NLP任务、序列模型。样本内部的结构关系必须保留,不同样本之间也没必要比较。
还有个好处:LN训练和推理行为完全一致,不像BN那样用移动平均来估计全局统计量。
推理的时候BN要用训练期间积累的移动平均均值方差,LN直接用当前样本的统计量,省心多了。
BN vs LN——一张表说清楚核心差异
来对比一下这两种方法。
| 特性 | Batch Normalization | Layer Normalization |
|---|---|---|
| 归一化维度 | batch 维度 | layer 维度 |
| 依赖 batch | 依赖 | 不依赖 |
| 保留关系 | 同特征跨样本关系 | 同样本内特征关系 |
| 小 batch 效果 | 差 | 稳定 |
| 典型应用 | 图像分类 | NLP、序列模型 |

简单说:BN保留的是"横向比较"的能力,LN保留的是"纵向结构"的能力。
BN让你知道所有学生中谁数学最好,LN让你知道每个学生各科之间的相对强弱。两种信息都有价值,关键是任务需要什么。
为什么 RNN 和 Transformer 非用 Layer Norm 不可
说到NLP任务,基本清一色用LN。为什么?
第一个原因:序列长度不一致。
NLP里,每个样本(句子)的长度都不一样。有的句子5个词,有的句子20个词。
BN怎么归一化?把同一位置的词向量放一起算均值方差。但不同句子的第5个词,语义完全不同啊!把"我"和"人工智能"放一起归一化,这不是搞笑吗?
LN就不存在这个问题。每个样本独立计算,短句子用自己的几个词算,长句子用自己的所有词算。不会把语义无关的东西混在一起。
第二个原因:Padding的干扰。
序列一般会padding到固定长度,短的句子用0填充。这些0没有任何语义意义,如果纳入统计会干扰均值方差估计。
LN只看有效内容,忽略padding,不受影响。
第三个原因:样本内特征关系必须保留。
NLP里,词和词之间的顺序和关系是核心信息。"我打你"和"你打我"完全相反。BN归一化可能破坏这种关系,LN则不会。

类比一下:读一篇文章的时候,你不会拿这篇文章的第5个词去跟另一篇文章的第5个词比较。每篇文章内容不同,位置相同的词意思可能完全不一样。
NLP模型学习的正是这种样本内部的依赖关系,这是必须保留的信号。
实战指南——不同场景怎么选
实际用的时候该怎么选?
记住一个原则:先问自己,我需要保留的是什么关系?
需要跨样本比较?选BN。
需要保留样本内部结构?选LN。
具体来说:
图像分类且batch足够大(32以上):优先选BN。ResNet、VGG这些老牌模型,BN是标配。
小batch size:选LN,BN在小batch下效果会明显退化。我之前有个项目batch只能设到8,换成LN之后训练稳了很多。
NLP任务、机器翻译、语音识别:选LN。这个没得商量,序列任务基本都得上LN。
Transformer/BERT类模型:几乎标配Layer Normalization。这个已经是业界共识了。
当然,实际工程中可以混合使用。比如Pre-LN Transformer,把LN放在残差连接外面,性能更好。这种改进型的归一化方式在GPT系列里也用得很多。
还有其他归一化方法:Group Normalization、Instance Normalization、Weight Normalization……工具箱越来越丰富。关键是理解原理,才能选对工具。

归一化选对了,训练就稳了
今天聊了深层网络训练困难的原因:Internal Covariate Shift,每层输入分布不断变化,像多米诺骨牌一样连锁影响。
BN和LN用归一化来打破这个连锁反应,但它们稳定的方向不同:
BN稳定的是特征在不同样本间的分布,适合需要横向比较的场景。
LN稳定的是单个样本内部的特征结构,适合需要保留样本内部依赖的场景。
理解了这一点,你就能在实际项目中做出正确选择。这往往就是"能用"和"好用"的分水岭。
不过,训练稳了只是第一步。模型层数太多、容量太大的时候,还会遇到另一个问题:过拟合。
模型记住了训练数据的细节,却泛化不到新数据上。
下回我们聊Dropout和正则化。
