大模型推理 · 实例化全程

从「我爱」到「你」
大模型训练推理全过程·矩阵向量完全实例化

本文构造一个 极小但完整 的 Transformer 语言模型, 把 每一个公式、每一个矩阵、每一个向量、每一次乘法和加法的中间结果 全部展开, 让你能用一支笔在纸上跟着把整个「下一个 token」的推理过程从头算到尾,然后再看清训练时梯度从哪里产生、权重如何更新。

词表大小 V=6 嵌入维度 d=2 注意力头数 h=1 层数 L=1 所有数值手算可复现
6
词表中的字符
2
输入 token 长度
12
主要计算阶段
100%
数值可手算复现

§0实验设置:一个能完整手算的迷你模型

大型语言模型 (GPT-4, Llama, Qwen…) 在结构上和这里的迷你模型 本质上完全一致,只是数字更多、层数更深。把这里的过程算明白,就掌握了所有大模型最底层的「计算物理」。

0.1 我们要做的事

给模型输入两个汉字 我爱,让它输出 下一个最有可能的字。期望的正确答案是

「我爱」
分词
嵌入
位置编码
自注意力
残差+LN
FFN
残差+LN
LM Head
Softmax
采样
「你」

0.2 超参数 (Hyperparameters)

表 0-1 · 极简超参数
符号含义数值
V词表大小 (vocab size)6
d嵌入维度 / 隐藏维度 (d_model)2
h注意力头数 (n_heads)1
d_k每个头的维度 (=d/h)2
d_ffFFN 隐藏维度4
LTransformer 层数1
T输入序列长度2

0.3 模型的全部可学习参数

真实大模型有几十亿到上万亿参数,我们这个迷你模型的全部参数清单如下:

表 0-2 · 全部可训练矩阵 (合计 38 个标量参数)
名称形状用途参数数
EV × d = 6×2词嵌入(Token Embedding),输入和输出共享(权重绑定)12
W_Qd × d = 2×2把隐藏向量投影成 Query4
W_Kd × d = 2×2把隐藏向量投影成 Key4
W_Vd × d = 2×2把隐藏向量投影成 Value4
W_1, b_12×4, 4FFN 第一层线性变换12
W_2, b_24×2, 2FFN 第二层线性变换10
注: 位置编码使用 固定的正弦余弦(无可学参数),LayerNorm 的 γ=1、β=0 也固定。 实际的 GPT 类模型会把这些也设成可学习,但本文为了能完全手算就先取最简版本。

§1词表:从汉字到整数 ID

所有大模型的第一步,就是把人类的字符变成机器能算的数字。这个映射表叫做「词表」(Vocabulary)。

我们手工设计一个包含 6 个 token 的词表 (真实 GPT 的词表是 ~10 万级别)。

表 1-1 · 我们的迷你词表 V = 6
Token ID字符含义
0<pad>填充符
1<bos>句首标记
2
3
4这是我们希望模型预测的字
5
关于 Tokenizer 的真实情况: 真实大模型用的是 BPE / SentencePiece 等子词分词算法, 会把「不」这种常见字拆成 1 个 token,而「鹅」这种生僻字可能拆成 2~3 个字节级 token。 但本质上输出依然是一串整数 ID — 这一节的思想完全适用。

§2分词:字符串 → 整数序列 → one-hot 矩阵

现在我们把输入字符串「我爱」交给 tokenizer,看它如何变成机器可以矩阵乘法的形式。

2.1 字符串切分,查表得到 ID 序列

ID = 2
ID = 3
输入 token 序列 $$ \text{tokens} = [\,2,\;3\,] \in \mathbb{Z}^{T=2} $$

2.2 ID 序列 → one-hot 矩阵

One-hot 编码:每个 token ID 变成一个长度为 V 的向量,只有对应位置为 1,其余为 0。整个输入序列就是 T × V = 2 × 6 的矩阵 Xoh

表 2-1 · One-hot 矩阵 X_oh ∈ ℝ^(2×6)
pad(0)bos(1)我(2)爱(3)你(4)他(5)
位置 t=0(我)001000
位置 t=1(爱)000100
实践中: 真实代码不会真正构造 one-hot 矩阵 — 那太浪费内存了。但 嵌入层在数学上等价于 $X_{oh} \cdot E$,只是工程上用「查表」(E[token_id])直接取出对应行而已。 所以,把它当作概念上的「向量化」第一步,非常重要。

§3嵌入层:从离散 ID 到稠密向量

每个 token ID 需要变成一个 d 维的实数向量(嵌入向量),这样模型才能在连续空间里做几何变换。

3.1 嵌入矩阵 E

嵌入矩阵 E 的形状为 V × d = 6 × 2,第 i 行就是 token ID = i 的嵌入向量。下面这些数值是 随机初始化的具体值(真实训练中由优化器逐步学习得到):

表 3-1 · 嵌入矩阵 E ∈ ℝ^(6×2)
Tokendim 0dim 1
0 <pad>0.00.0
1 <bos>0.10.2
2 我0.50.8
3 爱0.70.3
4 你0.20.9
5 他0.60.4

3.2 查表 / 矩阵乘法:得到嵌入序列 X

公式 $$ X = X_{oh} \cdot E \;\in\; \mathbb{R}^{T \times d} = \mathbb{R}^{2\times 2} $$

由于 Xoh 的每一行是 one-hot,矩阵乘法的效果就是 「挑出 E 的第 2 行和第 3 行」:

第 0 个位置(token=我,ID=2):

x0 = E[2] = (0.5, 0.8)

第 1 个位置(token=爱,ID=3):

x1 = E[3] = (0.7, 0.3)
表 3-2 · 嵌入后的序列 X ∈ ℝ^(2×2)
位置dim 0dim 1
t=0 (我)0.50.8
t=1 (爱)0.70.3

§4位置编码:让模型知道「谁在前谁在后」

单看嵌入,「我爱」和「爱我」是同一组向量集合 — Transformer 不知道顺序。所以要给每个位置加一个独特的「位置签名」。

4.1 正弦位置编码公式

Transformer (Vaswani 2017) 原始位置编码 $$ \mathrm{PE}(pos, 2i) = \sin\!\left(\tfrac{pos}{10000^{2i/d}}\right),\quad \mathrm{PE}(pos, 2i+1) = \cos\!\left(\tfrac{pos}{10000^{2i/d}}\right) $$

4.2 代入 d=2 的具体数值

当 d=2,只有一对 (sin, cos):i=0,所以分母 = 100000/2 = 1。

位置 pos = 0:

PE0 = (sin(0/1), cos(0/1)) = (0.000, 1.000)

位置 pos = 1:

PE1 = (sin(1/1), cos(1/1)) = (0.841, 0.540)
说明:sin(1 rad) ≈ 0.8415,cos(1 rad) ≈ 0.5403。

4.3 把位置编码加到嵌入上

$$ H^{(0)} = X + \mathrm{PE} $$

位置 0:

h0(0) = (0.5 + 0.000, 0.8 + 1.000) = (0.500, 1.800)

位置 1:

h1(0) = (0.7 + 0.841, 0.3 + 0.540) = (1.541, 0.840)
表 4-1 · 进入 Transformer 第一层的输入 H⁽⁰⁾
位置dim 0dim 1
t=0 (我)0.5001.800
t=1 (爱)1.5410.840

这个 H⁽⁰⁾ 就是 Transformer 第一层的真正输入。下面进入核心 — 自注意力。

§5自注意力:Transformer 的灵魂

这一节我们把 Q、K、V 怎么算、注意力分数怎么算、Softmax 怎么算、为什么要除以 √d_k、因果掩码怎么加 — 全部用数字走一遍。

5.1 三个投影矩阵 W_Q、W_K、W_V

权重矩阵都是 d × d = 2×2,数值是我们提前指定的(代表训练中某个时刻的状态):

W_Q
0.30.4
0.50.2
W_K
0.20.6
0.40.1
W_V
0.10.5
0.70.3

5.2 计算 Q、K、V

$$ Q = H^{(0)} W_Q,\quad K = H^{(0)} W_K,\quad V = H^{(0)} W_V $$

Query 的逐元素计算

对于 h0 = (0.500, 1.800):

q0,0 = 0.500 × 0.3 + 1.800 × 0.5 = 0.150 + 0.900 = 1.050
q0,1 = 0.500 × 0.4 + 1.800 × 0.2 = 0.200 + 0.360 = 0.560

对于 h1 = (1.541, 0.840):

q1,0 = 1.541 × 0.3 + 0.840 × 0.5 = 0.4623 + 0.4200 = 0.882
q1,1 = 1.541 × 0.4 + 0.840 × 0.2 = 0.6164 + 0.1680 = 0.784
表 5-1 · Q ∈ ℝ^(2×2)
位置q dim 0q dim 1
t=01.0500.560
t=10.8820.784
表 5-2 · K(同样算法,跳过中间步骤)
位置k dim 0k dim 1
t=00.8200.480
t=10.6441.009
表 5-3 · V
位置v dim 0v dim 1
t=01.3100.790
t=10.7421.023

5.3 注意力分数 (Attention Score)

$$ S = \frac{Q K^{\top}}{\sqrt{d_k}} \;\in\; \mathbb{R}^{T\times T} $$

每个分数 Si,j 是「位置 i 的 Query 与位置 j 的 Key 的点积」,代表「位置 i 想从位置 j 那里拿走多少信息」。

逐对计算 (除以 √2 ≈ 1.4142 之前):

q0 · k0 = 1.050×0.820 + 0.560×0.480 = 0.861 + 0.269 = 1.130
q0 · k1 = 1.050×0.644 + 0.560×1.009 = 0.676 + 0.565 = 1.241
q1 · k0 = 0.882×0.820 + 0.784×0.480 = 0.723 + 0.376 = 1.099
q1 · k1 = 0.882×0.644 + 0.784×1.009 = 0.568 + 0.791 = 1.359

再除以 √d_k = √2 ≈ 1.4142:

S0,0 = 1.130 / 1.4142 ≈ 0.799
S0,1 = 1.241 / 1.4142 ≈ 0.878
S1,0 = 1.099 / 1.4142 ≈ 0.777
S1,1 = 1.359 / 1.4142 ≈ 0.961
为什么除以 √d_k ? 当 d_k 很大时,点积的方差也变大,Softmax 会变成「赢者通吃」(只关注一个位置)。 除以 √d_k 把方差拉回 1 量级,保证梯度稳定。这是 Transformer 最重要的工程细节之一。

5.4 因果掩码 (Causal Mask):语言模型不能偷看未来

语言模型(GPT)是 自回归 的 — 预测第 i 个 token 时只能看 ≤ i 的位置。所以把 S 矩阵的上三角(包括严格上三角)设为 -∞,这样 Softmax 之后这些位置的权重就是 0。

表 5-4 · 应用因果掩码后的注意力分数 S'
看 t=0看 t=1
t=0 query0.799-∞ (masked)
t=1 query0.7770.961

5.5 Softmax 得到注意力权重

$$ A_{i,j} = \mathrm{softmax}(S'_{i,:})_j = \frac{\exp(S'_{i,j})}{\sum_{k}\exp(S'_{i,k})} $$

第 0 行:只有 t=0 可见

A0,0 = exp(0.799) / exp(0.799) = 1.000,A0,1 = 0.000

第 1 行:t=0 和 t=1 都可见

exp(0.777) ≈ 2.175
exp(0.961) ≈ 2.614
归一化分母 = 2.175 + 2.614 = 4.789
A1,0 = 2.175 / 4.789 ≈ 0.454
A1,1 = 2.614 / 4.789 ≈ 0.546
含义:在预测下一个 token 时,「爱」这个位置花了 45.4% 注意力看「我」、54.6% 看自己「爱」。
表 5-5 · 注意力权重矩阵 A
权重在 t=0权重在 t=1
t=0 query1.0000.000
t=1 query0.4540.546

5.6 用注意力权重对 V 加权求和

$$ \mathrm{Attn} = A V \;\in\; \mathbb{R}^{T \times d} $$

t=0 输出:

attn0 = 1.000 × v0 + 0.000 × v1 = (1.310, 0.790)

t=1 输出:

attn1 = 0.454 × (1.310, 0.790) + 0.546 × (0.742, 1.023)
         = (0.595, 0.359) + (0.405, 0.559)
         = (1.000, 0.917)
表 5-6 · 自注意力输出
位置dim 0dim 1
t=01.3100.790
t=11.0000.917
到此为止我们做了什么? 让每个位置的「新表示」= 自己原始 V 和其他可见位置 V 的加权平均。 权重由谁决定? 当前位置的 Q 与其他位置 K 的「点积相似度」。 这就是「Attention is All You Need」的核心思想。

§6残差连接 + LayerNorm(第一次)

注意力的输出不能直接送进下一层,要先加回原输入(残差),再做归一化(LayerNorm)。这两个技巧让深层网络得以训练。

6.1 残差连接:把输入加回来

$$ H' = H^{(0)} + \mathrm{Attn} $$
h'0 = (0.500, 1.800) + (1.310, 0.790) = (1.810, 2.590)
h'1 = (1.541, 0.840) + (1.000, 0.917) = (2.541, 1.757)

6.2 LayerNorm:沿特征维度做标准化

$$ \mathrm{LN}(h)_j = \gamma_j \cdot \frac{h_j - \mu}{\sqrt{\sigma^2 + \varepsilon}} + \beta_j,\quad \mu = \frac{1}{d}\sum_j h_j,\quad \sigma^2 = \frac{1}{d}\sum_j (h_j - \mu)^2 $$

我们设 γ = (1, 1), β = (0, 0), ε = 10⁻⁵。

t=0,h' = (1.810, 2.590):

μ = (1.810 + 2.590) / 2 = 2.200
σ² = ((1.810-2.200)² + (2.590-2.200)²)/2 = (0.1521 + 0.1521)/2 = 0.1521
σ = √0.1521 ≈ 0.390
LN(h'0) = ((1.810-2.200)/0.390, (2.590-2.200)/0.390) = (-1.000, 1.000)

t=1,h' = (2.541, 1.757):

μ = (2.541 + 1.757) / 2 = 2.149
σ² = ((2.541-2.149)² + (1.757-2.149)²)/2 ≈ 0.1537
σ ≈ 0.392
LN(h'1) = ((2.541-2.149)/0.392, (1.757-2.149)/0.392) = (1.000, -1.000)
表 6-1 · 第一次残差 + LN 之后的 H_ln1
位置dim 0dim 1
t=0-1.0001.000
t=11.000-1.000
巧合提醒: d=2 时 LN 输出永远是 (-1, 1) 或 (1, -1) 这种对称的形式(因为两个数减去均值后总是大小相等符号相反)。 真实大模型 d 通常是 4096~16384,LN 后值会分布在更复杂的范围里。

§7前馈网络 FFN:逐位置的非线性变换

注意力让 token 之间 交换信息;FFN 让 每个 token 自己 经过一个非线性「思考」。它通常占 Transformer 一半以上的参数。

7.1 FFN 公式

$$ \mathrm{FFN}(h) = \mathrm{ReLU}(h W_1 + b_1)\,W_2 + b_2 $$

7.2 权重数值

W_1 ∈ ℝ^(2×4)
0.30.1-0.20.4
0.2-0.30.50.1
b_1 ∈ ℝ⁴
0.10.10.10.1
W_2 ∈ ℝ^(4×2)
0.30.5
0.4-0.2
-0.10.6
0.20.3
b_2 ∈ ℝ²
0.00.0

7.3 第一层线性 + ReLU

t=0:输入 (-1.000, 1.000)

z = (-1.000, 1.000) · W_1 + b_1
z0 = -1×0.3 + 1×0.2 + 0.1 = 0.000
z1 = -1×0.1 + 1×(-0.3) + 0.1 = -0.300
z2 = -1×(-0.2) + 1×0.5 + 0.1 = 0.800
z3 = -1×0.4 + 1×0.1 + 0.1 = -0.200
ReLU(z) = max(z, 0) = (0.000, 0.000, 0.800, 0.000)

t=1:输入 (1.000, -1.000)

z0 = 1×0.3 + (-1)×0.2 + 0.1 = 0.200
z1 = 1×0.1 + (-1)×(-0.3) + 0.1 = 0.500
z2 = 1×(-0.2) + (-1)×0.5 + 0.1 = -0.600
z3 = 1×0.4 + (-1)×0.1 + 0.1 = 0.400
ReLU(z) = (0.200, 0.500, 0.000, 0.400)

7.4 第二层线性

t=0:ReLU 输出 (0, 0, 0.8, 0) → W_2

ffn0 = 0×(0.3,0.5) + 0×(0.4,-0.2) + 0.8×(-0.1,0.6) + 0×(0.2,0.3)
         = (-0.080, 0.480)

t=1:ReLU 输出 (0.2, 0.5, 0, 0.4) → W_2

ffn1,0 = 0.2×0.3 + 0.5×0.4 + 0×(-0.1) + 0.4×0.2 = 0.06 + 0.20 + 0 + 0.08 = 0.340
ffn1,1 = 0.2×0.5 + 0.5×(-0.2) + 0×0.6 + 0.4×0.3 = 0.10 - 0.10 + 0 + 0.12 = 0.120
ffn1 = (0.340, 0.120)
表 7-1 · FFN 输出
位置dim 0dim 1
t=0-0.0800.480
t=10.3400.120

§8残差 + LayerNorm(第二次)

和 §6 完全同样的操作,只是这次加在 FFN 输出上。

8.1 残差

h''0 = H_ln10 + ffn0 = (-1.000, 1.000) + (-0.080, 0.480) = (-1.080, 1.480)
h''1 = (1.000, -1.000) + (0.340, 0.120) = (1.340, -0.880)

8.2 LayerNorm

t=0,h'' = (-1.080, 1.480):

μ = 0.200,σ² = ((-1.28)² + (1.28)²)/2 = 1.6384,σ = 1.280
LN(h''0) = (-1.28/1.28, 1.28/1.28) = (-1.000, 1.000)

t=1,h'' = (1.340, -0.880):

μ = 0.230,σ² = (1.11² + (-1.11)²)/2 = 1.2321,σ = 1.110
LN(h''1) = (1.11/1.11, -1.11/1.11) = (1.000, -1.000)
表 8-1 · 最终隐藏表示 Hfinal
位置dim 0dim 1
t=0-1.0001.000
t=1 ← 这一行用于预测!1.000-1.000
关键观察: 我们要预测的是「我爱」后面的字,所以只用 最后一个位置 t=1 的最终向量 h_final = (1.000, -1.000) 来产生 logits。 训练时则会用所有位置同时算 loss(每个位置预测它自己的下一个 token)。

§10最终 Softmax:logits → 概率分布

logits 可以是任意实数;Softmax 把它们压成 (0, 1) 之间且加起来等于 1 的概率分布。

$$ p_i = \frac{\exp(\text{logit}_i)}{\sum_{j=1}^{V}\exp(\text{logit}_j)} $$

10.1 分子:取自然指数

exp(0.000) = 1.000
exp(-0.100) = 0.905
exp(-0.300) = 0.741
exp(0.400) = 1.492
exp(-0.700) = 0.497
exp(0.200) = 1.221

10.2 分母:求和

Z = 1.000 + 0.905 + 0.741 + 1.492 + 0.497 + 1.221 = 5.856

10.3 归一化得到概率

表 10-1 · 下一个 token 的概率分布
Tokenlogitexp(logit)p (=exp / 5.856)百分比
pad0.0001.0000.17117.1%
bos-0.1000.9050.15515.5%
-0.3000.7410.12712.7%
0.4001.4920.25525.5%
你 (目标)-0.7000.4970.0858.5%
0.2001.2210.20920.9%

10.4 概率分布可视化

pad
17.1%
bos
15.5%
12.7%
爱 (greedy预测)
25.5%
你 (目标)
8.5%
20.9%

§11采样:从概率分布到一个具体的汉字

有了 6 个字的概率分布,现在要选一个作为输出。不同采样策略会带来不同风格。

11.1 贪心 (Greedy) — 永远选概率最大的

argmax = 「爱」(p = 0.255)
输出字符 ← 词表[3] = 「爱」   ❌ 错误!(目标是「你」)
未训练的模型用 greedy 会犯错。这个错误正好被训练的 loss 捕捉,产生梯度去修正。

11.2 温度采样 (Temperature) — 平滑/锐化分布

$$ p_i^{(T)} = \frac{\exp(\text{logit}_i / T)}{\sum_j \exp(\text{logit}_j / T)} $$

T=1 是原始 softmax;T > 1 让分布更平、更随机;T < 1 让分布更尖、更确定。

表 11-1 · 不同温度下「你」的概率(目标)
温度 Tp(爱)p(你)p(他)分布特征
T = 0.50.3960.0450.266更尖锐(强化最大值)
T = 1.0(默认)0.2550.0850.209原始分布
T = 2.00.2050.1180.187更平(增加随机性)
T → ∞0.1670.1670.167均匀分布

11.3 Top-k 与 Top-p (Nucleus) 采样

Top-k=3: 保留概率最高的 3 个 token (爱 25.5%、他 20.9%、pad 17.1%) 重新归一化为 (0.405, 0.332, 0.272),再从这 3 个采样。

Top-p=0.5: 按概率从大到小累加,直到累计 ≥ 0.5,只在这部分采样。我们这里前两个累计 0.464,加上第三个达到 0.635,所以从前三个里采样。

11.4 从概率到字符:最后一公里

假设采样返回 token ID = 4,我们查 §1 的词表:

$$ \text{词表}[4] = \text{「你」} $$

把这个字符追加在原文后面,得到 「我爱你」。如果是连续生成(autoregressive),把它再喂回模型,重新算 §1~§11,得到下一个字…直到出现 <eos> 或达到长度上限。

这就是 ChatGPT「一个字一个字往外蹦」背后的全部计算 — 只不过把它放大了 N 个数量级。

§12训练过程:从错误中学习

推理是用「冻结」的权重往前算;训练是 同样的前向 + 计算 Loss + 反向传播梯度 + 更新权重。我们用刚刚的预测结果当作训练样本走一遍。

12.1 训练样本与标签

监督信号 $$ \text{输入: } [\,\text{我, 爱}\,]\quad\quad \text{目标下一个 token: } \text{你 (ID=4)} $$

12.2 交叉熵 Loss (Cross-Entropy)

$$ \mathcal{L} = -\log p_{\text{target}} = -\log p_{\text{「你」}} $$
p(你) = 0.085
ln(0.085) ≈ -2.465
Loss = 2.465 (越大说明模型越「错得离谱」)
理想情况下,完美训练后 p(你) → 1,loss → 0。

12.3 反向传播:从 Loss 算 logits 的梯度

交叉熵 + Softmax 组合有一个非常优雅的导数:

$$ \frac{\partial \mathcal{L}}{\partial \text{logit}_i} = p_i - y_i $$

其中 y 是 one-hot 标签 (这里 y4=1,其他都是 0)。

表 12-1 · 输出层 logits 的梯度
Tokenpiyi梯度 ∂L/∂logiti = pi - yi
pad0.1710+0.171
bos0.1550+0.155
0.1270+0.127
0.2550+0.255
你 (目标)0.0851-0.915
0.2090+0.209
直觉: 目标 token「你」得到一个 负梯度 -0.915 — 因为我们 希望它的 logit 变大。 其他 token 都得到正梯度 — 表示要把它们 压低。Softmax 的归一化天然保证了「此消彼长」。

12.4 进一步:嵌入矩阵 E 的梯度

由于权重绑定,logiti = hfinal · Ei,因此:

$$ \frac{\partial \mathcal{L}}{\partial E_i} = (p_i - y_i) \cdot h_{\text{final}} $$

取 hfinal = (1.000, -1.000):

表 12-2 · 对 E 各行的梯度 (lr 之前)
Token∂L/∂E (dim 0)∂L/∂E (dim 1)
pad+0.171-0.171
bos+0.155-0.155
+0.127-0.127
+0.255-0.255
你 (目标)-0.915+0.915
+0.209-0.209

12.5 梯度下降:更新嵌入「你」

学习率 η = 0.1 $$ E_{\text{你}} \;\leftarrow\; E_{\text{你}} - \eta \cdot \frac{\partial \mathcal{L}}{\partial E_{\text{你}}} $$
Eold = (0.200, 0.900)
∂L/∂E = (-0.915, +0.915)

Enew = (0.200, 0.900) - 0.1 × (-0.915, +0.915)
            = (0.200 + 0.0915, 0.900 - 0.0915)
            = (0.292, 0.809)

12.6 验证:更新后 logit(你) 升高了吗?

新 logit(你) = hfinal · Enew = 1.000 × 0.292 + (-1.000) × 0.809
                = -0.517
旧 logit(你) = -0.700

↑ 升高了 0.183(向正确方向迈出一步!)
这就是大模型训练的核心循环:
① 前向算 logits → ② Softmax 算概率 → ③ 交叉熵算 Loss → ④ 反向传播求所有权重的梯度 → ⑤ 优化器 (SGD / Adam) 更新权重 → ⑥ 重复几百亿次。
梯度同样会向后传播到 W_1、W_2、W_V、W_K、W_Q、以及每个位置的嵌入,只不过链式法则更长一些 — 但每一步都是上面那种「乘法+加法」。

12.7 完整反向传播链(概念示意)

对每个参数 θ,梯度通过链式法则一层一层往回传:

L
∂/∂logits
logits
∂/∂h_final
h_final
∂/∂LN, ∂/∂FFN
FFN 输入
∂/∂W_1, W_2, b_1, b_2
attn 输出
∂/∂A, ∂/∂V
A, V
∂/∂Q, ∂/∂K, ∂/∂V
Q,K,V
∂/∂W_Q, W_K, W_V
H⁽⁰⁾
∂/∂E
E

PyTorch 的 loss.backward() 一行就完成了上面整条链,内部就是反向遍历每一步,把上一步的梯度乘以这一步的雅可比矩阵。

§13全过程总结

一图回顾「我爱」→「你」这场完整的数学之旅。

表 13-1 · 推理路径全程一览
步骤输入操作输出形状核心数值(t=1 位置)
§2 分词"我爱"查词表[2] (T)[2, 3]
§3 嵌入[2, 3]E 查行2×2(0.7, 0.3)
§4 位置编码X+ PE2×2(1.541, 0.840)
§5 自注意力H⁽⁰⁾Q·Kᵀ/√d → softmax → ·V2×2(1.000, 0.917)
§6 残差+LNH⁽⁰⁾, Attn加,归一化2×2(1.000, -1.000)
§7 FFNH_ln1线性→ReLU→线性2×2(0.340, 0.120)
§8 残差+LNH_ln1, FFN加,归一化2×2(1.000, -1.000)
§9 LM Headh_final·Eᵀ6 (V)[0.0,-0.1,-0.3,0.4,-0.7,0.2]
§10 Softmaxlogits归一化指数6 (V)p(你)=0.085
§11 采样pargmax / 温度1(未训练) 选到「爱」

13.1 真实大模型与本文的差异 — 仅在「规模」

表 13-2 · 数量级对比
维度本文迷你模型GPT-4 级别倍数
词表 V6~100,000~17,000×
嵌入维度 d2~12,288~6,000×
层数 L1~120120×
注意力头数 h1~9696×
总参数38~1.8 万亿~10¹¹×
训练 token 数1(教学样本)~13 万亿
数学公式完全相同完全相同
所以下次当你听到「GPT-5 用了 5 万亿参数训练 30 万亿 token」时,记住:
它内部的每一次「下一个 token」生成,都是把本文 §1~§11 的步骤,在更大的矩阵上重复 一遍 而已。
你已经掌握了大模型计算的全部底层物理。

13.2 延伸学习地图

13.3 真正动手

把本文的所有公式用 Python + NumPy 写出来,把所有数字对上 — 100 行代码不到。然后:

pip install torch
git clone https://github.com/karpathy/nanoGPT
# 用 200 行 PyTorch 跑一个会写莎士比亚的 GPT