完整版 · 分步教学

编码器解码器与残差归一化

同一块 Transformer Block,为什么 BERT 能读懂却不能写文章、GPT 却反过来?为什么 96 层网络还能训得起来?答案藏在「能不能看未来」和「梯度能不能传回去」这两件事里。

目标实验目标

分两段:先看清编码器与解码器只差一件事——当前位置能不能看见未来;再拆开残差连接与层归一化这两个稳定器,理解深度网络为什么需要它们。

课堂问题「猫追狗」和「狗追猫」用同一批词。如果模型不知道谁在前谁在后,它怎么区分这两句话?
1双向 vs 单向:注意力能不能看见未来

下面是一张掩码注意力表。行 = 当前正在处理的词,列 = 它能看见的词。点上方按钮切换编码器与解码器。

续写「它 最 爱 晒太阳」

■ 可看 ■ 遮住 ■ 当前行

当前:编码器

—
2三种结构,三种工作方式
仅编码器

双向理解

代表模型:BERT
训练方式:完形填空(挖掉一个词,用左右两边猜回来)
擅长:分类 · 问答 · 提取

仅解码器

掩码生成

代表模型:GPT · Claude
训练方式:根据左侧内容预测下一个词
擅长:写作 · 对话 · 代码

编码器 + 解码器

先理解,再生成

代表模型:原始 Transformer · T5
编码器读题、解码器答题,中间用交叉注意力衔接
擅长:翻译 · 摘要

为什么今天偏爱解码器因为很多任务都能改写成「续写」——情感分析 = 这条评论是正面还是负面?答:负面;翻译 = 把这句话翻成英文:…;写代码本来就是续写。一套架构、一个训练目标,就能覆盖大部分任务。
396 层网络,梯度能传回第一层吗

损失在最后一层算出,梯度要一路反向传回第 1 层。每穿一层就要乘一次那层的导数——连乘这件事,要么把梯度碾成零,要么把它吹上天。

没有残差连接

梯度 ∝ 0.9⁹⁶ ≈ 0.00006

第 1 层收到的梯度只有原来的万分之零点六——几乎为零,参数得不到有效更新。

若每层导数 1.1:1.1⁹⁶ ≈ 12000

梯度爆炸、数值溢出,训练当场崩盘。

有残差连接

∂y/∂x = ∂f/∂x + 1

那个孤零零的「+1」就是命根子。哪怕 ∂f/∂x 小到 0.01,这层的总梯度也是 1.01——稳稳压在 1 附近。

1.01⁹⁶ ≈ 2.6

既没碾成零,也没吹爆。96 层网络,相当于给梯度铺了一条直通第 1 层的高速路。

4量级为什么会滚雪球,LayerNorm 怎么救

残差那条「只进不减」的高速路,每过一块就往上加一截。拿几个块首尾叠起来看,量级越滚越大。

LayerNorm 三步

① μ = mean(x), σ = std(x) ② x̂ = (x − μ) / σ ③ output = γx̂ + β

对每一个词向量单独做。把一条量级乱飞的向量拉成均值 0、标准差 1。γ、β 是可学习参数,既享受稳定,又不丢灵活。

手算一遍:x = [8, 2, 2, 4]

均值 μ4.00
方差6.00
标准差 σ≈ 2.45
归一化 x̂≈ [1.63, −0.82, −0.82, 0]
一条原本「参差不齐」的向量,被拉成了「整齐」的标准向量。后面层的权重才能稳定工作,不被某个异常大的值带偏。
5Norm 放前还是放后,决定训不训得起来

Post-LN(原始 2017)

y = LN( x + f(x) )

LayerNorm 压在残差主路之后——等于在高速路上设了个收费站,深层时梯度仍不稳,得靠脆弱的「学习率预热」哄着训。

Pre-LN(现代 GPT)

y = x + f( LN(x) )

Norm 挪到子层之前的支路上,残差主路全程畅通。这才是 GPT 能稳稳堆到几十上百层的关键。

还能更省LLaMA 等模型用 RMSNorm:干脆连均值都不减,只把向量除以它自己的均方根来定量级。少算一步、参数更少,效果却几乎一样。

挑战实验课挑战

挑战 1 · 遮住未来的理由
解码器训练时如果偷看标准答案,会出什么问题?说出「作弊」具体指什么。
挑战 2 · 没有那个 +1
把残差去掉,96 层、每层导数 0.9。第 1 层的梯度还剩百分之几?
挑战 3 · 手算 LayerNorm
把 x 换成 [10, 0, 0, 0],自己算出 μ、σ 和归一化后的四个值。
挑战 4 · Pre 与 Post
同一套参数下,为什么 Pre-LN 的残差主路「干净」?用式子说明 x 有没有被 Norm 碰过。