深度学习的数学原理(三十九)—— Transformer 数学全景图

本文是"代码实战三部曲"(第 36-38 篇)的收官之作,也是第 23-38 篇共 16 篇文章的数学全景总结。前 16 篇文章分别拆解了 Transformer 的各组件原理、数值计算和代码实现,本文将这些碎片拼接为一幅完整的信号流全景图------展示一条数据("我爱深度学习")从进入 Transformer 到最终驱动参数更新的完整旅程,并标注每一步的张量形状、数学公式和对应文章。

建议读者先略读本文的"大图"概览,再针对不熟悉的环节回看对应文章。


一、引言:为什么需要一张全景图?

经过 16 篇文章的漫长旅程,我们完成了:

  • 第 23-32 篇:Transformer 各组件的数学原理拆解(注意力机制、FFN、LayerNorm、嵌入等)
  • 第 33-34 篇:编码器与解码器的前向数值实例手算
  • 第 35 篇:完整一轮训练流程(前向→损失→反向→更新→再前向)的数值计算
  • 第 36 篇:编码器的代码实现与手动验证
  • 第 37 篇:解码器的代码实现与交叉注意力验证
  • 第 38 篇:完整 Transformer 训练实战与参数演化分析

但问题是:这些知识是碎片化的 。读者可能知道自注意力的数学公式,但不清楚它在前向传播中处于哪个位置、输入输出是什么形状、梯度如何回传。这正是本文要解决的问题------提供一张"数学全景图",将所有碎片拼合为一个完整的信号流

本文的组织方式

本文不引入任何新概念,而是用统一的视角展示整个 Transformer 的信号流:

  1. 一张大图:从数据到参数的完整信号流概览(第二节)
  2. 维度追踪:每个操作的输入输出张量形状(第三节)
  3. 前向传播全景:每个组件的数学运算(第四节)
  4. 反向传播全景:梯度如何回传(第五节)
  5. 参数更新全景:从梯度到参数变化的桥梁(第六节)
  6. 系列索引:16 篇文章的交叉对照表(第七节)
  7. 数学原理速查:核心公式一览(第八节)

二、一张大图:Transformer 完整信号流

下面是本文的核心------Transformer 完整信号流图。它展示了一条数据从原始字符输入,经过编码器、解码器、输出投影,最终以梯度形式回传并更新所有参数的全过程。

复制代码
╔══════════════════════════════════════════════════════════════════════════════════╗
║                TRANSFORMER 完整信号流(从数据到参数)                             ║
╚══════════════════════════════════════════════════════════════════════════════════╝

┌─────────────────────────────────────────────────────────────────────────────────┐
│  一、数据准备                                                                                                             │
│                                                                                                                                    │
│  Source: "我爱深度学习"  ──→ 字符级分词 ──→ [2, 15, 1, 374, 153, 306, 422, 3]  │
│  Target: "i love deep learning" ──→ 字符级分词 ──→ [2, 9, 12, ... , 3]                     │
│                           词表: 中文 1106 字 / 英文 54 字符                                                    │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  二、编码器前向(Encoder Forward)             形状变化: (8,) → (8, 32)                   │
│                                                                                                                                    │
│  src_ids (8 tokens)                                                                                                      │
│      │                                                                                                                           │
│      ▼                                                                                                                         │
│  ┌─ Embedding ──┐  (8, 32)     lookup + scale: x * √d_model                                │
│  │  形状: 1106×32 │                                                                                                  │
│  └──────┬───────┘                                                                                        │
│         ▼                                                                                                                      │
│  ┌─ PositionalEncoding ──┐  (8, 32)    PE(pos,2i)=sin(pos/10000^{2i/d})              │
│  └──────┬───────────────┘              PE(pos,2i+1)=cos(pos/10000^{2i/d})      │
│         ▼         ← 编码器层 × 3                                                                                   │
│  ┌──────────────────────────┐                                                        │
│  │  EncoderLayer 0          │                                                                                      │
│  │  ┌──────────────────┐   │  自注意力: Q=K=V (8,32)                           │
│  │  │ Self-Attention   │   │  Q/K/V投影 → 分4头 → scores=QK^T/√8                      │
│  │  │ (MultiHead, h=4) │   │  → softmax → 加权V → 合并4头 → WO投影             │
│  │  └────────┬─────────┘   │  attn_weights: (4, 8, 8)                              │
│  │           ▼             │                                                                                               │
│  │  LayerNorm(x + attn)   │  残差连接 + LN                                                            │
│  │           ▼             │                                                    │
│  │  ┌──────────────────┐   │  FFN: Linear(32→128) → ReLU → Linear(128→32)     │
│  │  │ FeedForward      │   │                                                                                    │
│  │  └────────┬─────────┘   │                                                    │
│  │           ▼             │                                                    │
│  │  LayerNorm(x + ffn)   │  每层输出范数稳定在 √32 ≈ 5.657                      │
│  └──────────┬───────────────┘                                                   │
│             ▼                                                                   │
│  ┌──────────────────────────┐                                                   │
│  │  EncoderLayer 1, 2      │  (形状与第0层完全一致)                              │
│  └──────────┬───────────────┘                                                   │
│             ▼                                                                   │
│  enc_output: (8, 32)   ← 编码器输出(作为解码器交叉注意力的 K,V)               │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  三、解码器前向(Decoder Forward)           形状变化: (19,) → (19, 32) → (19, 54)│
│                                                                                 │
│  tgt_ids (19 tokens: <sos> + "ilovedeeplearning" + <eos>)                     │
│      │                                                                         │
│      ▼                                                                         │
│  ┌─ Embedding ──┐  (19, 32)  × √d_model                                        │
│  └──────┬───────┘                                                              │
│         ▼                                                                      │
│  ┌─ PositionalEncoding ──┐  (19, 32)                                           │
│  └──────┬───────────────┘                                                      │
│         ▼         ← 解码器层 × 3                                                  │
│  ┌──────────────────────────┐                                                   │
│  │  DecoderLayer 0          │                                                   │
│  │  ┌──────────────────┐   │  因果自注意力: Q=K=V (19,32)                        │
│  │  │ Masked Self-Attn │   │  上三角 masked_fill(-inf)                          │
│  │  │ (causal=True)    │   │  attn_weights: (4, 19, 19), 上三角=0              │
│  │  └────────┬─────────┘   │                                                    │
│  │           ▼             │                                                    │
│  │  LayerNorm(x + attn)   │                                                    │
│  │           ▼             │                                                    │
│  │  ┌──────────────────┐   │  交叉注意力: Q(19,32)←解码器, K=V(8,32)←编码器      │
│  │  │ Cross-Attention  │   │  scores = Q_dec · K_enc^T / √8                    │
│  │  │ (Q←dec, KV←enc)  │   │  形状: (4, 19, 8)  ← 矩形而非方阵                 │
│  │  └────────┬─────────┘   │                                                    │
│  │           ▼             │                                                    │
│  │  LayerNorm(x + cross)  │                                                    │
│  │           ▼             │                                                    │
│  │  ┌──────────────────┐   │  FFN: 32→128→32                                   │
│  │  │ FeedForward      │   │                                                    │
│  │  └────────┬─────────┘   │                                                    │
│  │           ▼             │                                                    │
│  │  LayerNorm(x + ffn)   │                                                    │
│  └──────────┬───────────────┘                                                   │
│             ▼                                                                   │
│  ┌──────────────────────────┐                                                   │
│  │  DecoderLayer 1, 2      │  (形状一致,但注意力分布随层变化)                      │
│  └──────────┬───────────────┘                                                   │
│             ▼                                                                   │
│  ┌─ OutputProj (54×32) ─┐  Linear(32→54), 输出 logits                           │
│  └──────────┬────────────┘  (19, 54)                                            │
│             ▼                                                                   │
│  logits: (19, 54)  ← 每个解码位置对 54 个 token 的得分                            │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  四、损失计算(Loss)                              L = cross_entropy(logits, tgt) │
│                                                                                 │
│  logits (19, 54) ──→ Softmax ──→ P (19, 54)                                    │
│  P[位置p, token j] = exp(logit_j) / Σ_k exp(logit_k)                            │
│                                                                                 │
│  L = (1/19) Σ_p -log(P[p, tgt_p])                                              │
│                                                                                 │
│  初始: L ≈ 3.89 (uniform over 54 tokens ≈ ln(54))                              │
│  训练后: L → 0.41 (过拟合), 验证损失 → 7.25 (严重过拟合)                          │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  五、反向传播(Backpropagation)                    链式法则: ∂L/∂θ = ∂L/∂y · ∂y/∂θ│
│                                                                                 │
│  梯度从 Loss 出发,反向穿过每条路径:                                               │
│                                                                                 │
│  ∂L/∂logits (19, 54)  ← 第一步:dL/d(logit_j) = P_j - 𝟙(j==target)              │
│      │                                                                         │
│      ▼                                                                         │
│  ∂L/∂W_out (54, 32)    ∂L/∂D (19, 32)  ← 同时计算                               │
│      │                     │                                                    │
│      │         ┌───────────┼───────────┐                                       │
│      │         ▼           ▼           ▼                                       │
│      │    ∂L/∂W_FFN2  ∂L/∂CrossAttn  ∂L/∂SelfAttn                              │
│      │    ∂L/∂W_FFN1                                                           │
│      │         ▼                                                               │
│      │    ∂L/∂X_cross  ──→ 梯度回传至编码器                                      │
│      │         ▼                                                               │
│      │    ∂L/∂W_V_cross  ∂L/∂W_K_cross  ∂L/∂W_Q_cross                          │
│      │         ▼                                                               │
│      │    ∂L/∂X_self                                                           │
│      │         ▼                                                               │
│      │    ∂L/∂W_V_self  ∂L/∂W_K_self  ∂L/∂W_Q_self  ← 自注意力梯度              │
│      │         ▼                                                               │
│      │    ∂L/∂X_enc (8, 32)  ← 梯度回传到编码器                                  │
│      │         ▼                                                               │
│      │    ∂L/∂enc_FFN2  ∂L/∂enc_FFN1  ∂L/∂enc_Attn  ∂L/∂Embedding              │
│      ▼                                                                         │
│  每个参数 θ 获得梯度 ∂L/∂θ ← 用于下一节的参数更新                                  │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  六、参数更新(SGD / Adam)                        θ = θ - η · ∂L/∂θ            │
│                                                                                 │
│  参数组            | 数量      | 典型梯度范数 | 更新后效果                         │
│  ───────────────────────────────────────────────────────────                    │
│  Embedding (中)   | 41,856    | 中等        | 语义向量空间重构                    │
│  W_Q / W_K        | 各 1,024  | 小→中       | 注意力对齐模式学习                  │
│  W_V / W_O        | 各 1,024  | 中          | 值空间和输出空间调整                │
│  FFN W1 (32→128)  | 4,096     | 中          | 特征升维变换学习                    │
│  FFN W2 (128→32)  | 4,096     | 大          | 过拟合中增长最快 (+60%)             │
│  OutputProj (32→54)| 1,728    | 大          | 词表映射学习                        │
│  LayerNorm γ/β    | 各 32     | 小          | 缩放/偏移微调                       │
│                                                                                 │
│  Adam 维护一阶/二阶动量矩,自适应调整每个参数的学习率                                │
└─────────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│  七、迭代循环                               重复 1-6 步直至收敛 / 过拟合               │
│                                                                                 │
│  第 38 篇实验: 800 句对, 3000 步训练, 损失 4.09→0.41                             │
│  → 训练损失降 90%, 验证损失先降后升, 清晰展示过拟合全过程                          │
│  → Embedding 从随机→有序, 注意力从均匀→聚焦, 参数范数差异化增长                    │
└─────────────────────────────────────────────────────────────────────────────────┘

三、维度追踪:每一处的张量形状

理解 Transformer 信号流最快捷的方式是追踪张量形状的变化。下面给出从原始数据到最终输出的完整维度链。

3.1 整体维度链

以 d_model=32, h=4, d_k=8, batch=1 为例:

复制代码
原始文本               →  token IDs            →  Embedding          →  + PE
"我爱深度学习"          →  (8,)                 →  (1, 8, 32)         →  (1, 8, 32)
"i love deep learning" →  (19,)                →  (1, 19, 32)        →  (1, 19, 32)

编码器层 (×3)          →  解码器层 (×3)         →  Output Projection  →  Logits
(1, 8, 32)            →  (1, 19, 32)          →  (1, 19, 54)        →  (1, 19, 54)

Softmax → Loss (标量)  →  反向梯度              →  参数更新
(1, 19, 54) → ( )     →  每参数与形状一致       →  所有参数形状不变

3.2 编码器逐操作维度表

操作 输入形状 输出形状 关键变换
Embedding lookup (1, S) (1, S, 32) token id → 32维向量
× √d_model (1, S, 32) (1, S, 32) 缩放至标准方差
+ PE (S, 32) (1, S, 32) (1, S, 32) 叠加位置编码
W_Q linear (1, S, 32) (1, S, 32) Q 投影
Reshape for heads (1, S, 32) (1, 4, S, 8) 拆分为 4 个头
Q × K^T / √8 (1, 4, S, 8) × (1, 4, 8, S) (1, 4, S, S) 注意力得分
Softmax (1, 4, S, S) (1, 4, S, S) 归一化为权重
Weights × V (1, 4, S, S) × (1, 4, S, 8) (1, 4, S, 8) 加权上下文
Merge heads (1, 4, S, 8) (1, S, 32) 4头拼接
W_O linear (1, S, 32) (1, S, 32) 输出投影
Residual + LN (1, S, 32) (1, S, 32) 残差连接 + 归一化
FFN W1 (32→128) (1, S, 32) (1, S, 128) 升维
ReLU (1, S, 128) (1, S, 128) 非线性(~46% 置零)
FFN W2 (128→32) (1, S, 128) (1, S, 32) 降维
Residual + LN (1, S, 32) (1, S, 32) 每层输出范数 ≈ √32

S = 源序列长度(本例中为 8)

3.3 解码器逐操作维度表

操作 输入形状 输出形状 关键变换
Embedding + PE (1, T) (1, T, 32) 与编码器相同
因果自注意力
Q/K/V 投影 (1, T, 32) → 3×(1, T, 32) (1, 4, T, 8) 三分量独立投影
Scores (因果掩码) (1, 4, T, T) (1, 4, T, T) 上三角 = -inf
Softmax + × V (1, 4, T, T) → (1, 4, T, 8) (1, T, 32) 合并输出
交叉注意力
Q 投影(来自解码器) (1, T, 32) (1, 4, T, 8) ---
K 投影(来自编码器) (1, S, 32) (1, 4, S, 8) 形状不同!
V 投影(来自编码器) (1, S, 32) (1, 4, S, 8) 形状不同!
Scores = Q·K^T/√8 (1, 4, T, 8) × (1, 4, 8, S) (1, 4, T, S) 矩形矩阵
Softmax + × V (1, 4, T, S) × (1, 4, S, 8) (1, T, 32) 融合源语言信息
Residual + LN (1, T, 32) (1, T, 32) ---
FFN (1, T, 32) (1, T, 32) 32→128→32
Output Projection (1, T, 32) (1, T, 54) 32→54 (词表大小)

T = 目标序列长度(本例中为 19),S = 源序列长度(本例中为 8)

3.4 维度对比速查表

以下是一组核心对比,帮助理解不同组件的维度行为:

对比项 编码器自注意力 解码器因果自注意力 解码器交叉注意力
Q 来源 编码器自身 解码器自身 解码器(目标语言)
K,V 来源 编码器自身 解码器自身 编码器输出(源语言)
得分矩阵形状 (4, S, S) 方形 (4, T, T) 方形 (4, T, S) 矩形
掩码类型 padding mask 因果掩码(上三角) 无特殊掩码
矩阵是否有对角线 有(自注意力) 有(自注意力) 无对角线

一个关键洞察 :交叉注意力的得分矩阵形状为 (T, S) 而非 (S, T)(T, T)。这意味着目标语言的每个 token 都会对源语言的所有 token 计算一个注意力分布,这是"序列到序列"对齐的核心机制。


四、前向传播全景

本节将 Transformer 前向传播的所有数学运算汇总到一个统一的框架中。

4.1 总览:前向传播的数学链

复制代码
输入 x         ← 离散 token 序列
  │
嵌入 + 缩放    ← x = Embedding(src) · √d_model
  │
+ 位置编码      ← x = x + PE(pos)
  │
编码器 × N     ← x = EncoderLayer(x)
  │               ├── Self-Attention: x = LN(x + Attn(x, x, x))
  │               └── FFN:           x = LN(x + FFN(x))
  │
enc_output     ← 编码器的最终输出
  │
解码器 × N     ← x = DecoderLayer(x, enc_output)
  │               ├── Masked Self-Attn: x = LN(x + Attn(x, x, x, causal))
  │               ├── Cross-Attn:      x = LN(x + Attn(x, enc, enc))
  │               └── FFN:             x = LN(x + FFN(x))
  │
输出投影       ← logits = x · W_out^T + b_out
  │
Softmax        ← P = softmax(logits)
  │
损失           ← L = -log(P[tgt])

4.2 各组件数学公式全集

位置编码

PE(pos,2i)=sin⁡(pos100002i/dmodel),PE(pos,2i+1)=cos⁡(pos100002i/dmodel)\text{PE}(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right), \quad \text{PE}(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)PE(pos,2i)=sin(100002i/dmodelpos),PE(pos,2i+1)=cos(100002i/dmodelpos)

  • 低维高频(编码相对位置),高维低频(编码绝对位置)
  • 与 embedding 相加而非拼接,语义+位置在同一空间
  • 对应文章:第 36 篇第三节
多头自注意力

MultiHead(Q,K,V)=WO⋅Concat(head1,...,headh)\text{MultiHead}(Q, K, V) = W_O \cdot \text{Concat}(\text{head}_1, ..., \text{head}_h)MultiHead(Q,K,V)=WO⋅Concat(head1,...,headh)

headi=softmax(QiKi⊤dk+M)Vi\text{head}_i = \text{softmax}\left(\frac{Q_i K_i^\top}{\sqrt{d_k}} + M\right) V_iheadi=softmax(dk QiKi⊤+M)Vi

其中 Qi=WQ(i)QQ_i = W_Q^{(i)} QQi=WQ(i)Q, Ki=WK(i)KK_i = W_K^{(i)} KKi=WK(i)K, Vi=WV(i)VV_i = W_V^{(i)} VVi=WV(i)V

  • dk=dmodel/hd_k = d_{\text{model}} / hdk=dmodel/h
  • MMM 是掩码矩阵(padding mask 或因果掩码)
  • 对应文章:第 36 篇第四节
前馈网络(FFN)

FFN(x)=W2⋅max⁡(0,W1x+b1)+b2\text{FFN}(x) = W_2 \cdot \max(0, W_1 x + b_1) + b_2FFN(x)=W2⋅max(0,W1x+b1)+b2

  • 升维:dmodel→dffd_{\text{model}} \to d_{ff}dmodel→dff(通常 dff=4×dmodeld_{ff} = 4 \times d_{\text{model}}dff=4×dmodel)
  • ReLU 非线性:max⁡(0,⋅)\max(0, \cdot)max(0,⋅)
  • 降维:dff→dmodeld_{ff} \to d_{\text{model}}dff→dmodel
  • 对应文章:第 36 篇第五节
残差连接 + LayerNorm

output=LN(x+Sublayer(x))\text{output} = \text{LN}(x + \text{Sublayer}(x))output=LN(x+Sublayer(x))

LN(x)=γ⋅x−μσ+ϵ+β,μ=1d∑i=1dxi,σ2=1d∑i=1d(xi−μ)2\text{LN}(x) = \gamma \cdot \frac{x - \mu}{\sigma + \epsilon} + \beta, \quad \mu = \frac{1}{d}\sum_{i=1}^d x_i, \quad \sigma^2 = \frac{1}{d}\sum_{i=1}^d (x_i - \mu)^2LN(x)=γ⋅σ+ϵx−μ+β,μ=d1i=1∑dxi,σ2=d1i=1∑d(xi−μ)2

  • 残差连接确保梯度可直接回传绕过子层
  • LN 确保输出范数稳定(≈ √d_model),防止深层网络数值爆炸
  • 对应文章:第 36 篇第六节
交叉注意力

与自注意力公式完全相同,区别仅在于 Q、K、V 的来源:

CrossAttn(Qdec,Kenc,Venc)=softmax(QdecKenc⊤dk)Venc\text{CrossAttn}(Q_{\text{dec}}, K_{\text{enc}}, V_{\text{enc}}) = \text{softmax}\left(\frac{Q_{\text{dec}} K_{\text{enc}}^\top}{\sqrt{d_k}}\right) V_{\text{enc}}CrossAttn(Qdec,Kenc,Venc)=softmax(dk QdecKenc⊤)Venc

  • Q 形状:(T, d_k),K/V 形状:(S, d_k),得分矩阵形状:(T, S)
  • 使用因果掩码------解码器每个位置可关注编码器所有位置
  • 对应文章:第 37 篇第四节
输出投影层

Logits=D⋅Wproj⊤+bproj\text{Logits} = D \cdot W_{\text{proj}}^\top + b_{\text{proj}}Logits=D⋅Wproj⊤+bproj

  • D∈RT×dmodelD \in \mathbb{R}^{T \times d_{\text{model}}}D∈RT×dmodel:解码器输出
  • Wproj∈Rvocab×dmodelW_{\text{proj}} \in \mathbb{R}^{\text{vocab} \times d_{\text{model}}}Wproj∈Rvocab×dmodel:投影矩阵
  • 将 d_model 维向量映射到词表大小,每个 token 获得一个 logit 分数
Softmax 与交叉熵

Pp[j]=exp⁡(Logits[p,j])∑k=1vocabexp⁡(Logits[p,k])P_p[j] = \frac{\exp(\text{Logits}[p, j])}{\sum_{k=1}^{\text{vocab}} \exp(\text{Logits}[p, k])}Pp[j]=∑k=1vocabexp(Logits[p,k])exp(Logits[p,j])

L=1T∑p=1T−log⁡(Pp[tp])\mathcal{L} = \frac{1}{T} \sum_{p=1}^T -\log(P_p[t_p])L=T1p=1∑T−log(Pp[tp])

其中 tpt_ptp 是位置 ppp 的目标 token ID。

  • 对应文章:第 35 篇第二节

五、反向传播全景

反向传播是 Transformer 训练的"隐藏一半"------前向传播告诉我们模型输出了什么,反向传播告诉我们应该如何调整参数。

5.1 核心公式:损失对 Logits 的梯度

反向传播的第一步是计算损失对 logits 的梯度。这是整个梯度流的源头:

∂L∂Logits[p,j]=1T(Pp[j]−1[tp=j])\frac{\partial \mathcal{L}}{\partial \text{Logits}[p, j]} = \frac{1}{T} \left( P_p[j] - \mathbb{1}[t_p = j] \right)∂Logits[p,j]∂L=T1(Pp[j]−1[tp=j])

这个公式的意义非常直观:

  • 当目标 token 为 j 时:∂L∂Logits[p,j]=1T(Pp[j]−1)<0\frac{\partial \mathcal{L}}{\partial \text{Logits}[p, j]} = \frac{1}{T}(P_p[j] - 1) < 0∂Logits[p,j]∂L=T1(Pp[j]−1)<0 → 需要提高这个 logit
  • 当目标 token 不为 j 时:∂L∂Logits[p,j]=1TPp[j]>0\frac{\partial \mathcal{L}}{\partial \text{Logits}[p, j]} = \frac{1}{T} P_p[j] > 0∂Logits[p,j]∂L=T1Pp[j]>0 → 需要降低这个 logit

5.2 输出投影层梯度

∂L∂Wproj[j,k]=1T∑p=1T(Pp[j]−1[tp=j])⋅D[p,k]\frac{\partial \mathcal{L}}{\partial W_{\text{proj}}[j, k]} = \frac{1}{T} \sum_{p=1}^T \left( P_p[j] - \mathbb{1}[t_p = j] \right) \cdot D[p, k]∂Wproj[j,k]∂L=T1p=1∑T(Pp[j]−1[tp=j])⋅D[p,k]

这是整个反向传播中唯一需要"从头计算"的梯度------其余所有梯度都通过链式法则从这层向后传递。

对应文章:第 35 篇第三节(完整手算过程)

5.3 梯度回传路径全景

复制代码
Loss (标量)  ← 交叉熵
  │
  │ 公式: ∂L/∂Logit[j] = P[j] - 𝟙(j==target)
  ▼
Logits (T, vocab)
  │
  ├──→ ∂L/∂W_proj (vocab, d_model)     ← 直接计算(见 5.2 节)
  │                      ↓
  └──→ ∂L/∂D (T, d_model)              ← 沿输出投影层回传
         │
         │ 公式: ∂L/∂D[p,k] = Σ_j (∂L/∂Logit[p,j]) · W_proj[j,k]
         │
         ▼
    Decoder Layer 2  ← 3层解码器 → Decoder Layer 0
         │
         ├──→ FFN梯度
         │      ∂L/∂W_2 = (relu(W_1 x))^T · ∂L/∂y       ← 降维层
         │      ∂L/∂W_1 = x^T · (relu'(W_1 x) ⊙ (∂L/∂y · W_2^T))  ← 升维层
         │
         ├──→ 交叉注意力梯度
         │      ∂L/∂Q = (∂L/∂S) · K / √d_k               ← Q 梯度
         │      ∂L/∂K = (∂L/∂S)^T · Q / √d_k             ← K 梯度
         │      ∂L/∂V = Attn^T · ∂L/∂Context             ← V 梯度
         │       其中 ∂L/∂S = ∂L/∂Attn · V^T ⊙ softmax'(S)
         │      (S = QK^T / √d_k 为得分矩阵)
         │
         ├──→ 因果自注意力梯度(公式同上,但 Q=K=V)
         │
         ▼
    ∂L/∂X_enc (T, d_model)  ← 梯度跨过编码器-解码器边界
         │
         ▼
    Encoder Layer 2 → ... → Encoder Layer 0
         │
         ├──→ 自注意力梯度(公式同上)
         │
         ├──→ FFN梯度(公式同上)
         │
         └──→ ∂L/∂Embedding (vocab, d_model)  ← 词嵌入梯度
                │
                ▼
          ∂L/∂Embedding[token_id, :] = Σ_p ∂L/∂X_enc[p, :]  ← 只有被用到的 token 有梯度

5.4 交叉熵→Softmax梯度:以第35篇数值为例

第 35 篇的手算展示了梯度的一个关键特性------梯度竞争

以 token "i"(WprojW_{\text{proj}}Wproj 的第 3 行)为例,其梯度为三个位置上梯度的加权和:

位置 p δp[i]\delta_p[i]δp[i] D[p,0] D[p,1] D[p,2] D[p,3] 含义
0 -0.804 (目标,需提高) 1.0 0.0 1.0 0.0 位置 0 需要更多 "i"
1 +0.134 (非目标,需降低) 0.0 1.0 0.0 1.0 位置 1 需要更少 "i"
2 +0.151 (非目标,需降低) 1.0 1.0 0.0 0.0 位置 2 需要更少 "i"

最终梯度:

  • ∂L/∂W[3,0] = (-0.804×1.0 + 0.134×0.0 + 0.151×1.0) / 3 = -0.218 → 增加
  • ∂L/∂W[3,1] = (-0.804×0.0 + 0.134×1.0 + 0.151×1.0) / 3 = +0.095 → 减小

梯度竞争:同一个 token 的权重在不同位置受到方向相反的拉力------位置 0 让"i"变高,位置 1、2 让"i"变低。这是多任务学习的微观体现。


六、参数更新全景

有了梯度,参数就沿负梯度方向更新。本文汇总所有参数组的更新特征。

6.1 更新公式

SGD
θt+1=θt−η⋅∂L∂θt\theta_{t+1} = \theta_t - \eta \cdot \frac{\partial \mathcal{L}}{\partial \theta_t}θt+1=θt−η⋅∂θt∂L

Adam (实际使用的优化器):
mt=β1mt−1+(1−β1)gtm_t = \beta_1 m_{t-1} + (1-\beta_1) g_tmt=β1mt−1+(1−β1)gt
vt=β2vt−1+(1−β2)gt2v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2vt=β2vt−1+(1−β2)gt2
m^t=mt/(1−β1t),v^t=vt/(1−β2t)\hat{m}_t = m_t / (1-\beta_1^t), \quad \hat{v}t = v_t / (1-\beta_2^t)m^t=mt/(1−β1t),v^t=vt/(1−β2t)
θt+1=θt−η⋅m^tv^t+ϵ\theta
{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}θt+1=θt−η⋅v^t +ϵm^t

Adam 为每个参数自适应调整学习率------梯度变化剧烈的参数获得较小步长,梯度平缓的参数获得较大步长。

6.2 参数组更新特征(第 38 篇 3000 步训练数据)

参数组 数量 初始范数 最终范数 增长 训练中的作用
Embedding (中) 41,856 --- --- --- 构建语义向量空间
W_Q (单层) 1,024 3.22 4.10 +27% 学习如何"提问"
W_K (单层) 1,024 3.26 4.12 +27% 学习如何"应答"
W_V (单层) 1,024 3.32 4.25 +28% 学习提取"值"信息
W_O (单层) 1,024 3.34 4.30 +29% 学习合并多头输出
FFN W1 4,096 6.60 8.24 +25% 高维特征提取
FFN W2 4,096 3.25 5.20 +60% 增长最快------过拟合中记忆训练模式
OutputProj 1,728 --- --- --- 词表映射
LN γ/β 各 32 1.0/0.0 --- --- 缩放/偏移微调

6.3 学习阶段转移:从注意力到 FFN

第 38 篇最重要的发现之一是学习重点的阶段转移

训练阶段 步数 增长最快的参数 含义
早期(欠拟合) 0-125 W_Q, W_K 注意力机制先被优化
后期(过拟合) 500-3000 W_2(FFN输出) FFN开始记忆训练模式

这个转移的数学解释:

  • 早期梯度通过注意力路径(W_Q, W_K)回传效率最高------调整注意力就能快速降低损失
  • 后期损失主要由 token 级别的预测错误驱动------调整 FFN 输出投影(W2)能更精确地"记住"每个输入对应的输出

七、系列文章对照索引

下面是本专栏第 23-38 篇共 16 篇文章的对照索引,按功能维度组织。读者可根据需要快速跳转。

7.1 按组件索引

组件 数学原理 数值实例 代码实战
位置编码 第 24 篇 第 33 篇 2.1 节 第 36 篇第三节
自注意力 第 25 篇 第 33 篇 2.2 节 第 36 篇第四节
多头注意力 第 26 篇 --- 第 36 篇第四节
前馈网络 FFN 第 31 篇 第 33 篇 2.3 节 第 36 篇第五节
层归一化 LN 第 30 篇 --- 第 36 篇第六节
残差连接 第 30 篇 --- 第 36 篇第六节
交叉注意力 --- 第 28 篇 第 37 篇第四节
因果掩码 第 32 篇 --- 第 37 篇第三节
输出投影层 --- 第 35 篇第二节 第 37 篇第五节

7.2 按文章索引

文章 标题 核心内容 前置依赖
24 位置编码 正弦-余弦编码原理 ---
25 缩放点积注意力 Attention(Q,K,V) 公式 ---
26 多头注意力 并行注意力头机制 第 26 篇
20 层归一化 LN 公式与性质 ---
30 残差连接 梯度高速公路 ---
31 前馈网络 升维→ReLU→降维 ---
32 因果掩码 自回归生成中的掩码 第 26 篇
33 编码器前向数值 手算"我爱深"过编码器 25-30
34 解码器前向数值 手算解码器 + 交叉注意力 25-31
35 训练流程数值 前向→损失→反向→更新→再前向(一篇顶五篇) 23-34
36 编码器代码实战 PyTorch 实现 + 逐步骤手算验证 33
37 解码器代码实战 因果掩码 + 交叉注意力 + 自回归推理 34, 36
38 训练代码实战 完整训练 + 3000 步参数演化分析 35, 36, 37

加粗的 33-38 篇构成了"从手算数值到代码实现"的完整实践闭环。

7.3 "三部曲"内部对照

第 36-38 篇构成"代码实战三部曲",其内部关系可以概括为:

第 36 篇(编码器) 第 37 篇(解码器) 第 38 篇(训练)
核心问题 编码器如何将字符序列编码为上下文向量? 解码器如何利用编码器输出逐步生成目标序列? 参数如何从随机走向有序?
模型状态 随机初始化 随机初始化 训练中(3000 步)
关键验证 手算 vs 代码(误差 10^{-8}) 因果掩码前后对比 8 个检查点纵向对比
注意力特点 4 头自注意力,初现分化 因果自注意力 + 交叉注意力 注意力聚焦度持续变化
输出形式 enc_output (8, 32) 随机字符序列 "itisnevero"(有进步但未收敛)
与下一篇的关系 输出作为第 37 篇 K,V 引出训练需求 三部曲终章

八、数学原理速查索引

本节以"一句话公式 + 一句话直觉"的方式,汇总核心数学概念,作为快速参考。

注意力机制

概念 公式 一句话直觉
缩放点积注意力 Attn(Q,K,V)=softmax(QK⊤dk)V\text{Attn}(Q,K,V) = \text{softmax}(\frac{QK^\top}{\sqrt{d_k}})VAttn(Q,K,V)=softmax(dk QK⊤)V 用 Q 和 K 的相似度做权重,加权求和 V
多头注意力 MultiHead=WO⋅Concat(head1,...,headh)\text{MultiHead} = W_O \cdot \text{Concat}(\text{head}_1, ..., \text{head}_h)MultiHead=WO⋅Concat(head1,...,headh) 多组 QKV 并行,获取不同视角
因果掩码 Mij=0 (i≥j), −∞ (i<j)M_{ij} = 0\ (i \ge j),\ -\infty\ (i < j)Mij=0 (i≥j), −∞ (i<j) 预测第 t 步时不能看到第 t+1 步及以后
交叉注意力 QdecKenc⊤Q_{\text{dec}} K_{\text{enc}}^\topQdecKenc⊤ 目标语言向源语言"提问"

前馈与归一化

概念 公式 一句话直觉
FFN FFN(x)=W2⋅max⁡(0,W1x+b1)+b2\text{FFN}(x) = W_2 \cdot \max(0, W_1 x + b_1) + b_2FFN(x)=W2⋅max(0,W1x+b1)+b2 每个位置独立地升维提取特征再降维
LayerNorm LN(x)=γ⋅x−μσ+β\text{LN}(x) = \gamma \cdot \frac{x-\mu}{\sigma} + \betaLN(x)=γ⋅σx−μ+β 在每个样本内部做标准化
残差连接 x+Sublayer(x)x + \text{Sublayer}(x)x+Sublayer(x) 梯度可以从旁路直接通过,防止深层退化

位置编码

概念 公式 一句话直觉
正余弦 PE PE(pos,2i)=sin⁡(pos100002i/d)\text{PE}(pos,2i)=\sin(\frac{pos}{10000^{2i/d}})PE(pos,2i)=sin(100002i/dpos), PE(pos,2i+1)=cos⁡(pos100002i/d)\text{PE}(pos,2i+1)=\cos(\frac{pos}{10000^{2i/d}})PE(pos,2i+1)=cos(100002i/dpos) 低维高频编码相对位置,高维低频编码绝对位置

训练相关

概念 公式 一句话直觉
交叉熵损失 L=−1T∑plog⁡Pp[tp]\mathcal{L} = -\frac{1}{T}\sum_p \log P_p[t_p]L=−T1∑plogPp[tp] 让正确 token 的概率最大化
Softmax Pj=ezj∑kezkP_j = \frac{e^{z_j}}{\sum_k e^{z_k}}Pj=∑kezkezj 将 logits 转换为概率分布(和为 1)
链式法则 ∂L∂θ=∂L∂y⋅∂y∂θ\frac{\partial \mathcal{L}}{\partial \theta} = \frac{\partial \mathcal{L}}{\partial y} \cdot \frac{\partial y}{\partial \theta}∂θ∂L=∂y∂L⋅∂θ∂y 梯度沿计算图逐层回传
SGD θt+1=θt−ηgt\theta_{t+1} = \theta_t - \eta g_tθt+1=θt−ηgt 沿最陡的下坡方向走一小步
Adam θt+1=θt−ηmtvt+ϵ\theta_{t+1} = \theta_t - \eta \frac{m_t}{\sqrt{v_t}+\epsilon}θt+1=θt−ηvt +ϵmt 自适应步长------陡峭处慢走,平坦处快走

九、总结:三部曲的闭环

9.1 从松散组件到完整系统的认知路径

回顾本专栏从第 23 篇到第 39 篇的旅程,我们经历了四层认知跃迁:

复制代码
第 1 层:概念                                    第 23-32 篇
  └── 逐个学习 Transformer 组件的数学原理
       (注意力、FFN、LN、Adam 等 10 个独立概念)

第 2 层:数值                                    第 33-35 篇
  └── 用极小型模型(d_model=4)手算每个组件的输入输出
       (从 10 个概念到 3 个完整流程:编码器→解码器→训练)

第 3 层:代码                                    第 36-38 篇
  └── 用 PyTorch 实现完整 Transformer(d_model=32)
       (从手算到代码,逐步骤验证,13 万参数训练实战)

第 4 层:全景 ← 本文                               第 39 篇
  └── 将全部碎片拼接为一张大图
       (展示一条数据从进入系统到驱动参数更新的完整信号流)

9.2 "随机到有序"的数学本质

第 38 篇用 3000 步训练直观展示了参数从随机走向有序。现在,站在全景视角,我们可以给出更本质的数学描述:

训练前 :参数 θ\thetaθ 服从随机分布(均匀或正态),模型输出基本是噪声,损失接近 ln⁡(vocab)\ln(\text{vocab})ln(vocab)。

训练后 :参数 θ\thetaθ 收敛到损失曲面的某个局部极小点附近,各参数组呈现出差异化的增长模式:

  • Embedding 矩阵:从各向同性 → 语义聚类(t-SNE 可视化验证)
  • 注意力投影:WQ/WK 增长 27%,注意力分布从均匀 → 聚焦(KL 散度增加)
  • FFN 投影:W2 增长 60%,成为最大变动参数组(过拟合阶段主导)
  • 输出投影:正确 token 的 logit 从淹没在噪声中 → 显著高于其他

用数学语言说:训练将参数从高熵的随机状态驱动到了低熵的有序状态 ,使得模型的条件概率分布 P(y∣x;θ)P(y|x;\theta)P(y∣x;θ) 逼近训练数据 Pdata(y∣x)P_{\text{data}}(y|x)Pdata(y∣x)。

9.3 信号流全景:一个统一的视角

如果只从本文带走一个概念,应该是这个统一的信号流视角

复制代码
数据 ──→ 嵌入 ──→ 编码器(S→S) ──→ 解码器(S→T) ──→ 投影 ──→ 损失 ──→ 梯度 ──→ 更新
  ↑                                                                              │
  └──────────────────────────── 循环迭代 ──────────────────────────────────────────┘

每个箭头都是一组数学运算,每个方块都是一个可微模块,整个系统由链式法则无缝连接。无论 Transformer 的规模如何增大(d_model=32 或 512 或 1024),这个信号流框架完全不变:

操作 小模型(d_model=32) 大模型(d_model=512) 是否变化
Embedding (V, 32) (V, 512) 维度放大
注意力 Q·K^T / √8 Q·K^T / √64 缩放因子变化
FFN 32→128→32 512→2048→512 维度放大
残差LN 范数 = √32 ≈ 5.66 范数 = √512 ≈ 22.63 数值变大
梯度公式 1T(P−1)\frac{1}{T}(P - \mathbb{1})T1(P−1) 完全相同 不变
SGD/Adam θ←θ−η∇\theta \leftarrow \theta - \eta \nablaθ←θ−η∇ 完全相同 不变

这就是数学抽象的威力:理解小模型的完整信号流,就理解了大模型的一切本质

相关推荐
MacroZheng6 小时前
让 Claude Code 成本爆降 89%,这个开源工具有点猛...
java·人工智能·后端
南屹川6 小时前
【消息队列】Kafka深度解析:从原理到生产环境实战
人工智能
szxinmai主板定制专家6 小时前
基于ZYNQ MPSOC ARM+FPGA的超高清实时图像采集与压缩系统设计
linux·运维·服务器·arm开发·人工智能·嵌入式硬件·fpga开发
cyyt6 小时前
深度学习周报(5.18~5.24)
人工智能·深度学习
互联网江湖6 小时前
AI云计算时代:腾讯“搞钱”、阿里“撒币”、百度“登山”
人工智能·百度·云计算
晚烛6 小时前
CANN 大模型推理优化实战:FlashAttention、推测解码与连续批处理的工程实现
开发语言·人工智能·python·深度学习·数据挖掘
@蔓蔓喜欢你6 小时前
CSS Container Queries:响应式设计的新突破
人工智能·ai
共绩算力6 小时前
无服务器冷启动:HF 缓存与预计算哈希
人工智能·缓存·serverless·哈希算法·共绩算力
weixin_553654486 小时前
Claude 4.7 的“逻辑美学” vs GPT-5 的“暴力推理”:2026 核心业务代码审计该用谁?
人工智能·gpt·ai·大模型·token