归一化层:LayerNorm 与 RMSNorm
为什么每个 transformer 块都要重新缩放激活值,LayerNorm 和 RMSNorm 各自怎么做,以及为什么正是这个不起眼的步骤让深度模型可训练。
每个注意力和前馈子层之间,都夹着一个不做任何推理、也几乎不承载知识的步骤:归一化。它重新缩放流经模型的那些数值。听起来像管道工程,它确实是——但正是这套管道,让几十层 transformer 叠起来这件事成为可能。没有它,深度模型根本训不起来。
它解决的问题
一个向量经过一层又一层,每一层都在往上累加。放任不管,这些数值的量级就会漂移——有的维度膨胀到几千,有的塌向零。而且这种漂移会随深度叠加。
随之而来的是两种失败。数值爆炸让梯度变得极大、训练不稳,损失上下乱跳甚至发散。数值消失让梯度变得极小,于是靠前的层几乎不更新,实际上停止学习。无论哪种,深栈都会变得无法训练。模型越深,漂移越严重,这正是模型变大之后归一化变得不可让步的原因。
归一化在每个块里重置每个 token 向量的尺度,把数值压在稳定区间内,不管栈有多深。
LayerNorm 做什么
层归一化(layer normalization)一次处理一个 token 的向量。对这个向量,它:
- 在向量的各个维度上算出均值和标准差。
- 减去均值、除以标准差——重新中心化到均值 0,重新缩放到方差 1。
- 应用两个可学习参数,一个缩放、一个偏移,让模型在有必要时能够撤销或调整这次归一化。
关键的细节在于归一化作用在什么之上。LayerNorm 的统计量是在单个 token 的特征维度上算的,与序列中其他每个 token 都无关。正是这种独立性让它适配 transformer:不管序列是 10 个 token 还是 10000 个,也不管是生成时跑一个 token 还是训练时跑一整个批次,它的行为完全一致。没有跨 token、跨批次的依赖,训练和推理之间就不会有意外。
RMSNorm 改了什么
RMSNorm(均方根归一化,root mean square normalization)是一个精简版本,在大模型里已经变得常见。它问了一个简单的问题:减去均值这一步真的必要吗?
RMSNorm 把它去掉了。它不做中心化再缩放,只做缩放——把向量除以自身的均方根幅值,再乘一个可学习的缩放系数。不算均值,没有偏移参数,也不重新中心化。
回报是速度。它省掉一次归约操作和一部分参数,而当归一化要在几十层、几十亿 token 上每层跑两次时,这就很要紧。支持这一改动的是经验发现:在这些模型里,重新中心化贡献很小,几乎全部有用功都是缩放做的。同样的稳定效果,更少的计算。这就是近期许多架构采用 RMSNorm 的原因,不过这个选择属于效率上的改良,并没有改变归一化本身的用途。
它放在哪:pre-norm 与 post-norm
归一化在块中的位置,事后证明和归一化本身一样重要。
最早的 transformer 把归一化放在每个子层及其残差相加之后——post-norm。这在浅栈上能用,但随深度增加变得不稳定,往往需要精心设计预热调度才训得起来。
几乎所有大模型都转向了 pre-norm:在输入进入注意力或前馈网络之前先归一化,让残差路径保持干净。原因和残差连接有关。在 pre-norm 里,残差这条高速公路从输入直达输出,上面没有压着归一化,所以梯度能毫无阻碍地一路回传到整个栈。正是这条干净通路让极深的模型稳定训练。从 post-norm 换成 pre-norm,是让「堆很多层」变成常规动作的那些静悄悄的改动之一。
为什么这层「无聊」的层很要紧
人们容易把归一化当成注意力旁边的脚注。但因果链很直接:没有稳定的归一化,就没有深栈;没有深栈,就没有能力强的模型。别处讨论的每一种能力,前提都是几十层在协同工作,而这种协同之所以成立,只因为归一化在每一步都把数值压在范围内。
它同时也是一份便宜的保险。这一层增加的参数可以忽略,也不承担任何表示上的重活,可一旦拿掉,训练就彻底崩掉。这种不对称——成本极小、作用却是承重的——就是它出现在每个现代 transformer 的每一个块里的原因。
要点回顾
- 归一化在每个块里重新缩放每个 token 的向量,防止数值漂移,否则深栈根本训不起来
- LayerNorm 在单个 token 的特征维度上做中心化和缩放,与其他 token、与批次都无关——这正是它干净适配 transformer 的原因
- RMSNorm 去掉中心化步骤,只做缩放,同样的稳定性、更少的计算
- pre-norm(在子层之前归一化)让残差路径保持干净,是极深模型能稳定训练的原因;它取代了最初的 post-norm
- 这一层几乎不承载知识,却是承重的:没有它,任何带来能力的深度都练不出来
下一篇: 输出投影——最终归一化后的向量如何变成词表上的分数。