从 Bit 到 AGI第五章:Transformer

Residual 连接

从 Bit 到 AGI · 第五章:Transformer · 残差如何让 12 层网络可训练

作者 David更新于 第 70 篇(共 186 篇)

12 层 Transformer 若纯堆叠非线性变换,梯度反向传播时要连乘 12 次 Jacobian,极易梯度消失或爆炸。ResNet 的残差连接(Residual Connection)被原论文直接借用:子层输出加上输入本身,让梯度至少有一条「高速公路」直通浅层。

直觉:改错题而不是重写

子层 FF 不必从零学会完整映射 H(x)H(\mathbf{x}),只需学修正量 Δ(x)=H(x)−x\Delta(\mathbf{x}) = H(\mathbf{x}) - \mathbf{x}:

y=x+F(x)\mathbf{y} = \mathbf{x} + F(\mathbf{x})

若最优映射接近恒等,令 F(x)→0F(\mathbf{x}) \to 0 即可;比让 FF 直接拟合恒等映射容易得多。

定义

Transformer 每个子层(Attention、FFN)外都包一层残差:

x′=LayerNorm(x+Sublayer(x))(Post-Norm)\mathbf{x}' = \text{LayerNorm}(\mathbf{x} + \text{Sublayer}(\mathbf{x})) \quad \text{(Post-Norm)}

或 Pre-Norm 变体(先 Norm 再子层,见 Pre-Norm 与 Post-Norm):

x′=x+Sublayer(LayerNorm(x))\mathbf{x}' = \mathbf{x} + \text{Sublayer}(\text{LayerNorm}(\mathbf{x}))

BERT-base 原版用 Post-Norm;GPT-2/3、LLaMA 等多用 Pre-Norm。

例子

例 1:形状不变

  • 输入 x\mathbf{x}:(n,768)(n, 768),如 n=128n=128
  • Attention 输出:(128,768)(128, 768)
  • 残差相加:逐元素加,维度必须完全一致

例 2:梯度路径

设损失 LL,残差块 y=x+F(x)\mathbf{y} = \mathbf{x} + F(\mathbf{x}):

∂L∂x=∂L∂y(I+∂F∂x)\frac{\partial L}{\partial \mathbf{x}} = \frac{\partial L}{\partial \mathbf{y}}\left(\mathbf{I} + \frac{\partial F}{\partial \mathbf{x}}\right)

恒等项 I\mathbf{I} 保证梯度至少以 1 倍传回,不会因 ∂F/∂x\partial F/\partial \mathbf{x} 连乘而趋零。

图表加载中…

量化

  • 额外参数:0(纯加法)
  • 额外 FLOPs:n⋅dmodeln \cdot d_{\text{model}} 次加法;n=512,d=768n=512, d=768 时约 3.9×1053.9 \times 10^5,相对 attention 可忽略
  • 内存:训练需存 x\mathbf{x} 供 backward,激活内存随层数线性增;12 层 BERT 激活是显存大头之一
层数无残差(典型)有残差
12 层可训练性困难稳定
梯度直达浅层否是(+恒等路径)

常见误区

  1. 残差 = Skip Connection 仅用于 CNN:Transformer 每个子层都有,是标配而非可选。
  2. 相加前不用对齐维度:Multi-Head 输出投影后必须回到 dmodel=768d_{\text{model}}=768 才能与输入加。
  3. 残差能无限加深:有帮助但非万能;极深(100+ 层)还需 Pre-Norm、初始化、学习率 warmup 等配合。

动手试一试

import torch
import torch.nn as nn

class ResidualBlock(nn.Module):
    def __init__(self, sublayer: nn.Module):
        super().__init__()
        self.sublayer = sublayer
        self.norm = nn.LayerNorm(768)

    def forward(self, x):
        return self.norm(x + self.sublayer(x))  # Post-Norm

x = torch.randn(128, 768)
block = ResidualBlock(nn.Linear(768, 768))
y = block(x)
assert y.shape == x.shape

小结

残差 x+F(x)\mathbf{x} + F(\mathbf{x}) 让深层 Transformer 可训练,无额外参数。每个 Attention 与 FFN 子层外各包一层。下一篇讲残差后的 LayerNorm 做什么。

下一篇:LayerNorm

本页目录