深入篇 15 / Transformer 逐步拆解 · 2026-11-08

从一个 token 到一个词表:先把形状算对

独立画出 Qwen3 的 token → embedding → decoder → logits,并算出 Q/K/V 的真实宽度。

核心阅读 12–18 分钟练习另需 10–20 分钟前置:会读 PyTorch 张量形状;可从这里开始

本课只拿下这一件事

独立画出 Qwen3 的 token → embedding → decoder → logits,并算出 Q/K/V 的真实宽度。

token 到 logits 的六个检查点。这是概念形状;框架常将变长 batch 压平为 [总 token 数,H]。
这是概念形状;框架常将变长 batch 压平为 [总 token 数,H]。

符号先固定,后面才不会混

B 是请求数,T 是当前输入长度,H 是 hidden size,Hq 是 query 头数,Hkv 是 KV 头数,d 是每头维度,F 是 MLP 中间宽度,Vocab 是词表大小。token ID 是查表索引,不是词的语义向量;embedding 权重 E 的形状是 [Vocab,H],输入 [B,T] 得到 [B,T,H]。分词边界也不等于汉字或单词边界,本文的小 token 示例只为展示数组索引。

2017 年 Transformer 同时有 encoder、decoder 和 cross-attention;这里沿着本地 Qwen3 的 decoder-only 路径学习:只含因果 self-attention,没有给 encoder 输出准备的 cross-attention。原论文看 §3,工程结构以本地 decoder 源码为准。

不要把 H 和 Hq × d 当成同一个量

X [B,T,H]
Q = X Wq → [B,T,Hq·d]
K = X Wk → [B,T,Hkv·d]
V = X Wv → [B,T,Hkv·d]
concat(heads) Wo → [B,T,H]

在数学行向量约定下 Wq 为 [H,Hq·d];PyTorch Linear.weight 存的是 [out_features,in_features],forward 实际做 x @ weight.T。不要因为权重转置误判公式。Qwen3-0.6B 的公开 config:H=1024、Hq=16、Hkv=8、d=128、F=3072、L=28,所以 fused QKV 的末维是 2048+1024+1024=4096。它在 qkv.split 之后才变成三个张量。

logits 为什么不是概率

每个位置的 logits 是 Vocab 个未归一化分数;softmax 才把它们变成概率。因果模型中位置 t 的 logits 预测位置 t+1。prefill 虽计算很多位置的 hidden states,生成时通常只需要各请求最后一个有效位置的 logits;本地 ParallelLMHead 根据 cu_seqlens_q 选择这些位置,避免给所有 prompt token 做大词表投影。

tie_word_embeddings=true 表示 embedding 与 LM head 共享权重,不意味着 logits 等于输入 embedding。最后 hidden state 已经经过整叠 decoder;共享的只是矩阵参数。本课涉及的具体形状见 Qwen 官方 config(核验于 2026-11-08)与以下固定源码。

把维度变化拆到每一步

  1. 投影先沿H乘加,输出宽度是(Hq+2Hkv)·d。
  2. split按Q/K/V各自宽度切片;分头才是下一次reshape。
QKV 投影与不等宽 split。用完整 X[3,4] 和 W[4,8] 计算 Y[3,8],将 Q 的4列、K的2列、V的2列分别标色,解释收缩轴和 Linear.weight 的转置约定。
用完整 X[3,4] 和 W[4,8] 计算 Y[3,8],将 Q 的4列、K的2列、V的2列分别标色,解释收缩轴和 Linear.weight 的转置约定。打开原图放大 ↗

打开元素级图解:矩阵、轴、索引与可点击反例 →

Qwen3-0.6B 的投影宽度。数值来自模型 config 与 nano-vllm 的 Qwen3Attention;不使用 H/Hq 猜 head_dim。
数值来自模型 config 与 nano-vllm 的 Qwen3Attention;不使用 H/Hq 猜 head_dim。

数值练习:先算,再核对

令 B=2、T=3、H=8、Hq=4、Hkv=2、d=4。先写出 Q、K、V reshape 后的形状,再算 fused QKV 的末维。最后说明 Wo 为什么是 16→8。

看完整推导

Q=[2,3,4,4],K/V=[2,3,2,4];fused 末维=16+8+8=32。每头输出 4 个数,4 个头拼成16维;Wo 将其投回8维才能接残差。

闭卷检索

不要回看正文。答错后先解释原因,再重新打开这一课。

把结论落到源码

  1. 在 Qwen3Attention 中标出 q_size、kv_size 与 o_proj 三处,说明它们如何约束 split 与 flatten。
  2. 在 ParallelLMHead.forward 找到 cu_seqlens_q - 1 的索引;用长度 [2,3] 写出取哪两行。
  3. 在 Qwen3ForCausalLM 找到 tied weight 的赋值,并说明共享的是存储。

以下行号由本地 vendor 文件生成;上游链接固定完整 commit,离线摘录可直接打开。

优先阅读:Attention Is All You Need §3.1–3.4,再读本地 Qwen3Attention。

速查:形状与公式 · 三框架映射 · 术语表 · 复习与实战路线 · 4070 Ti本地实验

记录你此刻能做到什么

只在当前浏览器保存自评;不会自动写成已掌握的 learning record。

随时追问老师。把“第 15 课 + 哪个公式 / 哪个张量 / 哪一行 + 你的推导”发给我,我们可以继续拆到每一步。