先记住一句话
Token 是模型处理的离散符号,embedding 是符号对应的可学习向量;自回归训练把序列右移一位,让模型在每个位置根据过去预测下一个 token。
0. 先看完整计算顺序
1. Tokenization:字符串怎样变成符号
神经网络不能直接对字符串做矩阵乘法。Tokenizer 先把文本切成有限词表中的符号。为了能完整手算,我们定义一个只有 6 项的玩具词表:
例 1:一个玩具 tokenizer
| Token | <BOS> | I | love | robot | s | <EOS> |
|---|---|---|---|---|---|---|
| ID | 0 | 1 | 2 | 3 | 4 | 5 |
"I love robots" → [<BOS>, I, love, robot, s, <EOS>] → [0, 1, 2, 3, 4, 5]robots 不在词表里,所以被拆成 robot + s。真实 tokenizer 会用 BPE、Unigram 等方法学习子词词表;这里的切法只为说明计算。
BPE 的“学习”不是神经网络训练
BPE 先在大量文本上统计相邻符号组合,反复合并最常见的组合,最后保存词表和有顺序的合并规则。它没有神经网络、loss、反向传播或梯度下降。
例 1A:从 low, low, lower 手算两轮 BPE
初始先把每个词看成基本符号:
l o w | l o w | l o w e r| 相邻组合 | l + o | o + w | w + e | e + r |
|---|---|---|---|---|
| 出现次数 | 3 | 3 | 1 | 1 |
若并列时规定先选 l + o,第一轮得到:
l + o → lo 得到:lo w | lo w | lo w e r重新统计后,lo + w 出现 3 次,于是第二轮得到:
lo + w → low 得到:low | low | low e r以后编码 lower 时,tokenizer 按已经保存的优先级执行:l o w e r → lo w e r → low e r。因此歧义不是模型临场猜测,而是由固定算法和固定规则确定。
先保证任何 UTF-8 文本都能退回到基础字节,再把语料中常见的字节序列合并成 token。中文、英文、emoji 可以共享同一套词表;一个 token 可能是一个英文子词、一个汉字、多个汉字,也可能只是某个字符的一部分。OpenAI 公开的 tiktoken 使用模型相关的 encoding,不同 GPT 模型不必采用完全相同的词表和切分。
因此实际训练通常分为两个不同阶段:
token 不等于单词。它可以是子词、字节、图像 patch、视觉 code 或离散动作。词表大小是在两种成本之间折中:
- 词表大:序列较短,但 embedding/output matrix 更大。
- 词表小:覆盖灵活,但同一内容被切得更长,attention 与生成更贵。
若把 robot 的 ID 从 3 改成 500,同时把它的 embedding 搬到矩阵第 500 行,模型语义不变。ID 只是数组索引,不是“robot = 3.0”这个连续数值。
2. Embedding lookup:ID 怎样变成向量
设词表大小 $V=6$、模型宽度 $d=3$。模型维护可训练矩阵 $E\in\mathbb R^{6\times3}$。这里假设当前参数是:
| ID / token | 维度 1 | 维度 2 | 维度 3 |
|---|---|---|---|
0 / <BOS> | 0.10 | −0.20 | 0.00 |
1 / I | 0.40 | 0.10 | −0.30 |
2 / love | −0.20 | 0.70 | 0.50 |
3 / robot | 0.80 | 0.10 | −0.40 |
4 / s | 0.05 | 0.60 | 0.20 |
5 / <EOS> | −0.50 | 0.20 | 0.30 |
例 2:查表与 one-hot 乘法是同一件事
robot 的 ID 是 3,所以直接取 $E$ 的第 3 行:
若写成 one-hot,结果完全相同:
于是训练输入 [<BOS>, I, love, robot, s] 变成 $5\times3$ 矩阵:
[[ 0.10, -0.20, 0.00], # <BOS>
[ 0.40, 0.10, -0.30], # I
[-0.20, 0.70, 0.50], # love
[ 0.80, 0.10, -0.40], # robot
[ 0.05, 0.60, 0.20]] # s
位置也必须进入表示
仅做 token lookup 时,robot love 与 love robot 只是同两行向量换序;模型还需要明确位置。用最简单的加法式位置向量举例,假设位置 3 的向量是 $P_3=[0.05,-0.10,0.20]$:
现代模型也常使用 RoPE,不一定把位置向量直接加到输入;但“token 内容”和“它位于哪里”仍是两个不同信号。
Input embedding
由 token ID 查表得到;同一个 token 的起始向量相同。
Contextual hidden state
经过 attention 后得到;同一个 robot 在不同上下文中会变成不同向量。
Embedding 的“大小”可能指两个不同数字
| 符号 | 含义 | 例子 |
|---|---|---|
| $V$ | 词表大小,也就是有多少行 | 100,000 个 token |
| $d$ | 每个 token 向量的宽度,也就是有多少列 | 4,096 维 |
此时 embedding matrix 的形状是 $100{,}000\times4{,}096$,共有 409,600,000 个可训练参数。词表越大,行数越多;模型宽度越大,每一行越长。
3. 自回归:把联合概率拆成一步一步
自回归是一种概率分解,不等于 Transformer,也不要求输出一定是文字:
对我们的序列,模型要估计五个条件概率:
例 3:整句概率、NLL 与 perplexity
| 已知过去 | 正确下一个 token | 假设模型概率 | $-\ln p$ |
|---|---|---|---|
<BOS> | I | 0.80 | 0.22314 |
<BOS> I | love | 0.70 | 0.35667 |
… I love | robot | 0.60 | 0.51083 |
… love robot | s | 0.90 | 0.10536 |
… robot s | <EOS> | 0.50 | 0.69315 |
整句概率:$0.80\times0.70\times0.60\times0.90\times0.50=0.1512$
总 NLL:$-\ln(0.1512)=1.8892$,也等于右列相加后的结果(存在末位舍入)。
平均 loss:$1.8890/5=0.3778$。
Perplexity:$e^{0.3778}\approx1.459$。
整句很长时,许多小于 1 的概率相乘会非常小,所以实际计算用 log:乘法变加法,数值也更稳定。
4. Teacher forcing:一条序列怎样变成五道题
训练时完整正确序列已经在磁盘里。输入和标签只需错开一位:
<BOS>Iloverobots
Iloverobots<EOS>
love 结尾,标签是 robot。所有位置可在一次 forward 中同时算出。Teacher forcing 的意思是:训练位置 $t$ 时,前缀使用数据中的真实 token,而不是模型刚才猜出的 token。这样训练稳定且可以并行;推理时没有未来真值,才必须使用自己的输出。
5. Causal mask:为什么并行训练没有偷看答案
虽然五个位置一起进入 Transformer,但 attention mask 禁止每个 query 读取未来 key。下面行是 query 位置,列是它想读取的位置:
robot 和位置 4 的 s。实现中被屏蔽的 attention score 会在 softmax 前加上 $-\infty$。例 4:mask 在 softmax 中怎样生效
假设位置 2 对五个 key 的原始 attention score 是:
[1.2, 0.3, 0.8, 2.0, −0.1]位置 3、4 属于未来,mask 后变成:
[1.2, 0.3, 0.8, −∞, −∞]对前三项 softmax:$e^{1.2}=3.320$,$e^{0.3}=1.350$,$e^{0.8}=2.226$,总和 $6.896$,所以权重约为:
[0.482, 0.196, 0.323, 0, 0]未来位置严格得到 0 权重,而不是“很小的权重”。
6. Hidden state、logits、softmax 与 loss
口语里常说“Transformer 输出 logits”,但严格地说,Transformer 主体先为每个位置输出一个连续 hidden state;LM Head(也叫输出层或 unembedding)再把它投影成 logits:
例 5A:hidden state 怎样经过输出矩阵变成 logits
假设 hidden state 为 $h=[1,2,-1]$,输出词表只有四项。先忽略 bias,每一项 logit 都是 $h$ 与对应输出权重的点积:
| 候选 | 输出权重 | 点积计算 | logit |
|---|---|---|---|
I | [0.2, 0.1, 0.0] | 1×0.2 + 2×0.1 + (−1)×0.0 | 0.4 |
love | [0.0, 0.5, 0.2] | 1×0.0 + 2×0.5 + (−1)×0.2 | 0.8 |
robot | [0.6, 0.4, −0.2] | 1×0.6 + 2×0.4 + (−1)×(−0.2) | 1.6 |
<EOS> | [−0.1, 0.0, 0.3] | 1×(−0.1) + 2×0.0 + (−1)×0.3 | −0.4 |
于是 $[1,2,-1]$ 经过这个 $4\times3$ 输出矩阵后,得到 logits [0.4, 0.8, 1.6, −0.4]。Logit 可以是任意实数,并不是离散类别或概率。
若词表大小为 $V=100{,}000$,每个位置就产生 100,000 个 logits,标准 Softmax 也在这 100,000 项上归一化。训练一个长度为 $T$ 的序列会得到 $T\times V$ 的 logits;生成时通常只使用最新位置的 $V$ 项。Top-k 和 top-p 通常是在完整 logits 算出之后筛选,数学上没有把输出词表变小。
Softmax 把 logits 转成总和为 1 的概率;cross-entropy 只取正确 token 的概率来计算这个位置的 loss:
例 5B:从四个 logits 手算一个位置的 loss
位置 2 的正确标签是 robot。为简化,只展示四个候选:
| 候选 | I | love | robot | <EOS> |
|---|---|---|---|---|
| logit $z$ | 0 | 1 | 2 | −1 |
| $e^z$ | 1.000 | 2.718 | 7.389 | 0.368 |
| 概率 | 0.087 | 0.237 | 0.644 | 0.032 |
分母为 $1+2.718+7.389+0.368=11.475$,所以:
0.440 不是 44% 错误率。它表示模型对正确答案的“意外程度”。robot 虽然已经排名第一,但模型只给它 64.4% 的概率,仍有 35.6% 的概率质量放在错误答案上,所以 loss 还不为 0。
| 正确 token 概率 | $-\ln(p)$ | 直觉 |
|---|---|---|
| 1.00 | 0.000 | 完全确信正确答案 |
| 0.90 | 0.105 | 很有把握 |
| 0.644 | 0.440 | 答案排第一,但还不够确信 |
| 0.50 | 0.693 | 只有一半把握 |
| 0.10 | 2.303 | 几乎没想到正确答案 |
| 0.01 | 4.605 | 非常自信地预测错了 |
若一次更新后 robot logit 从 2 增加到 2.6,其他不变:
新的指数值:$e^{2.6}=13.464$。
新的分母:$1+2.718+13.464+0.368=17.550$。
正确概率:$p(\text{robot})=13.464/17.550=0.767$。
新的 loss:$-\ln(0.767)=0.265$。
训练达成了目标:正确 token 的 logit 增大,概率从 64.4% 升到 76.7%,因此 loss 从 0.440 降到 0.265。负对数还会对“非常自信地犯错”给出很大惩罚,并把整句概率的连乘转成各位置 loss 的相加。
梯度究竟更新什么
Loss 会通过输出层、Transformer、位置模块一路反向传播到 embedding。用一个标量说明 SGD:若 robot embedding 第一维当前为 $0.80$,梯度为 $\partial L/\partial E_{3,1}=0.30$,学习率 $\eta=0.10$:
真实训练会同时更新数十亿个参数,并通常使用 AdamW,而不是这个单变量 SGD;但“沿着降低 loss 的方向改变参数”就是同一件事。
7. 推理:为什么必须一个 token 一个 token 地生成
训练时标签已知,所以所有位置能并行;推理时第 2 步输入依赖第 1 步刚生成的 token。下面这个动画使用预先写好的玩具概率,演示 greedy decoding 的信息流:
例 6:Greedy、sampling 与 temperature
若某一步分布是 robot: 0.60, AI: 0.25, <EOS>: 0.15:
- Greedy 永远选概率最大的
robot。 - Sampling 按概率抽样;重复很多次,约 60% 选
robot、25% 选AI。 - Temperature 使用 $\operatorname{softmax}(z/T)$。$T<1$ 放大 logit 差异,使分布更尖;$T>1$ 让分布更平。
训练
输入真实前缀;一次 forward 计算所有位置;模型的早期错误不会改写本样本后面的输入。
生成
输入自己的历史输出;通常逐步生成;一个错误会改变后续所有条件,这就是 exposure bias 的来源。
8. 为什么 next-token prediction 能学到结构
目标本身简单,但要把正确 token 的概率持续推高,模型必须利用数据中可预测的规律。看一个极小语料:
Paris is the capital of France
Tokyo is the capital of Japan
Ottawa is the capital of Canada
若只记局部二元组,看到 capital of 后无法确定国家;要进一步降低 loss,模型必须利用更早出现的城市。类似地,代码需要变量和括号对应,长文本需要人物与论点一致。规模扩大后,大量任务共享同一预测接口。
但这个目标只奖励“符合训练分布”,不直接奖励真实、因果、安全或有帮助。错误事实和表面捷径也能降低 loss,所以还需要数据治理、后训练、检索和工具。
9. 同一个逻辑怎样进入机器人动作模型
若观测 $o$ 包含图像、语言和本体状态,离散动作也可自回归:
例 7:把连续位移量化成 action token
假设末端 $\Delta x$ 范围是 $[-0.05,0.05]$ 米,用 256 个等宽 bin。真实动作 $\Delta x=0.012$ 米:
归一化位置:$(0.012-(-0.05))/0.10=0.62$。
Token ID:$\lfloor0.62\times256\rfloor=158$。
若用 bin 中心解码:$-0.05+(158.5/256)\times0.10\approx0.01191$ 米。
仅量化带来的误差约 $0.00009$ 米,也就是 $0.09$ mm。
维度更多、范围更大或 bin 更少时,量化误差会增加;逐维自回归还会引入延迟。因此现代机器人策略也常直接生成连续 action chunk,或使用 diffusion / flow matching。
“自回归”描述概率怎样分解和样本怎样依次产生。它不等于语言、不等于离散输出,也不等于 Transformer;连续变量同样可以自回归建模。
自测:最好先拿纸算,再展开答案
1. 词表大小 10,000、embedding width 512,embedding matrix 有多少参数?
$10{,}000\times512=5{,}120{,}000$ 个参数;若用 fp16,仅该矩阵权重约占 10.24 MB,不含梯度和 optimizer state。
2. ID 序列是 [2, 4, 2],embedding 输出的三行有什么关系?
第 1、3 行都查 $E[2]$,所以 input embedding 相同;加入不同位置并经过 attention 后,hidden state 通常不同。
3. 正确 token 概率从 0.25 提升到 0.50,cross-entropy 各是多少?
$-\ln0.25=1.386$,$-\ln0.50=0.693$,loss 减少 0.693。
4. 为什么 causal mask 允许训练并行,却没有泄漏未来?
所有 query 同时计算,但每个位置在 softmax 前把未来 key 的 score 设为 $-\infty$,对应权重严格为 0。
5. Teacher forcing 与 greedy decoding 的输入差别是什么?
Teacher forcing 的下一位置总拿真实历史;greedy decoding 拿模型自己上一轮选出的最高概率 token。
6. BPE 的学习为什么不属于神经网络训练?
它通过统计相邻符号频率并反复合并来产生词表和规则,没有可微网络、反向传播或梯度下降;规则确定后,编码也是确定性的。
7. 词表大小为 50,000 时,一个位置会得到多少个 logits?
标准语言模型会得到 50,000 个连续 logits,Softmax 在这 50,000 项上归一化,最后才选择一个离散 token ID。
原始资料
Generative Pre-Training 展示了语言建模预训练再迁移的路线;OpenAI 的 tiktoken 示例 展示了文本如何变成 token、不同模型如何对应不同 encoding(该页面已归档,模型列表应视为历史示例)。下一篇会把这里暂时当作黑箱的 Transformer 拆开,逐项计算 Q、K、V 与 attention。