本节摘要:自回归解码是串行的,每个 token 等前一个。投机解码打破这条链:便宜模型起草 N 个 token,昂贵模型一次前向验证全部 N 个——起草对了,你为 N 个生成只付一次大模型前向。70B LLM 在 H100 上采一个 token 约 30 ms,3B 草稿模型约 3 ms;让 3B 草稿前看 5 个 token、再跑一次 70B 验证全部 5 个,总耗时
5×3 + 30 = 45 ms可换最多 5 个被接受的 token,而直推生成要5×30 = 150 ms。这就是投机解码的全部卖点:用一点额外显存(草稿模型)换 2~4 倍更低的解码延迟。关键在于必须保持分布——Leviathan 等(2023)和 Chen 等同时引入的投机采样,保证输出序列与「大模型自己从头采」同分布,零质量损失,只是更快。2026 推理有四类草稿-验证对:原生投机(独立草稿模型)、Medusa(验证者上多个解码头并行预测,无独立草稿)、EAGLE(轻量草稿复用验证者隐状态,接受率最高,典型 3~4 倍加速)、Lookahead(Jacobi 迭代自投机,无需草稿)。本节带你实现投机采样的核心(拒绝步 + 残差分布),并验证输出分布与直采在卡方检验下一致。
阅读完本节,你应当能够:
(q-p)_+ 归一化为何能精确保持验证者的分布(Leviathan 定理)。(1-α^(N+1))/(1-α) 个 token,α=0.75, N=5 时约 3 倍大模型调用减少。自回归解码串行,投机解码打破它:便宜模型起草 N 个 token,昂贵模型一次前向验证全部。技巧必须保持分布——投机采样保证输出序列与大模型自己采同分布,零质量损失。
给定验证者 M_q 和更便宜的草稿 M_p:
x_1..x_k 是已解码前缀。M_p 自回归提议 d_{k+1}..d_{k+N},带草稿概率 p_1..p_N。M_q 对 x_1..x_k, d_{k+1}..d_{k+N} 跑一次,得到位置 k+1..k+N+1 的验证概率 q_1..q_{N+1}。i,以 min(1, q_i(d_i)/p_i(d_i)) 的概率接受。j 拒绝:从「残差」分布 (q_j - p_j)_+ 归一化后采 t_j,丢弃 j 之后所有草稿。q_{N+1} 多采一个 t_{N+1}(免费奖励 token)。残差分布技巧是保持输出精确按 M_q 从头采那样分布的数学洞见。
设 α = 每草稿 token 的期望接受率,c = 草稿对验证者的成本比。每步:
α 高时每 (1 - α^(N+1)) / (1 - α) ≈ 1/(1-α) 个 token 一次大模型调用。经验法则:α=0.75, N=5 时大模型调用少 3 倍,草稿成本是 5 倍便宜,总墙钟降约 2.5 倍。
α 取决于:
Medusa 用验证者上的额外输出头替代草稿模型。位置 t:
共享主干 → 隐状态 h_t ├── head_0: 预测 t+1 的 token(标准 LM 头) ├── head_1: 预测 t+2 ├── head_2: 预测 t+3 ├── head_3: 预测 t+4
每个头出自己 logits,推理时从每个头采样得到候选序列,再用树注意力方案一次前向考虑所有候选续写。优点:无第二模型;缺点:加可训练参数,需监督微调阶段(约 10 亿 token),接受率比带好草稿的原生投机略低。
EAGLE-1/2/3(Li 等,2024~2025)把草稿模型做成一个微型 Transformer(通常 1 层),摄入验证者最后一层隐状态。因为草稿看到验证者的特征表示,其预测与验证者输出分布强相关,接受率从约 0.6(原生)爬到 0.85+。EAGLE-3(2025)加了候选续写的树搜索,vLLM 和 SGLang 把 EAGLE-2/3 作为 Llama 3/4 和 Qwen 3 的默认投机路径。
验证一次前向把 N 个草稿 token 喂进验证者,把它的 KV 缓存扩展 N 项;若有草稿被拒,必须把缓存回滚到已接受前缀长度。生产实现(vLLM 的 --speculative-model、TensorRT-LLM 的 LookaheadDecoder)用 scratch KV 缓冲处理:先写,接受时提交。概念上不难,但繁琐。
💡 残差分布为何保持分布:朴素想,「接受 q≥p 的、拒绝 q<p 的」会偏向高概率 token。残差分布
(q-p)_+归一化精确补偿了这个偏置——拒绝时从「q 比 p 多出来的概率」里采,数学上等价于直接从 q 采。这是 Leviathan 定理的核心,也是投机解码零质量损失的根基。
完整代码见原课程 phases/07-transformers-deep-dive/16-speculative-decoding/code/main.py。用手工分布的确定性 softmax 当「大模型」(便于解析验证接受数学)、用大模型的扰动当「草稿模型」、用产出与直采同边际分布的接受/拒绝循环,实现核心投机采样算法。
def accept_or_reject(q_prob, p_prob, draft_token, u): ratio = q_prob / p_prob if p_prob > 0 else float("inf") return u < min(1.0, ratio)
u 是均匀随机数,q_prob 是验证者对草稿 token 的概率,p_prob 是草稿模型的概率。Leviathan 定理保证:这个伯努利决策加上拒绝时从残差采样,精确保持验证者分布。
def residual_dist(q, p): raw = [max(0.0, qi - pi) for qi, pi in zip(q, p)] s = sum(raw) return [r / s for r in raw]
q 逐元素减 p、负值截零、归一化,任何拒绝时从中采样。
def spec_step(prefix, q_model, p_model, N, rng): drafts, p_probs, ctx = [], [], list(prefix) for _ in range(N): # 草稿自回归起草 N 个 p_dist = p_model(ctx) d = sample(p_dist, rng) drafts.append(d); p_probs.append(p_dist[d]); ctx.append(d) q_dists = [q_model(prefix + drafts[:i]) for i in range(N + 1)] # 并行验证 for i, d in enumerate(drafts): # 左到右接受/拒绝 q_prob = q_dists[i][d]; p_prob = p_probs[i] if rng.random() < min(1.0, q_prob / p_prob if p_prob > 0 else float("inf")): prefix = prefix + [d] else: # 首次拒绝:残差采样,丢弃之后 res = residual_dist(q_dists[i], p_model(prefix)) return prefix + [sample(res, rng)] return prefix + [sample(q_dists[N], rng)] # 全接受:奖励 token
五个接受 + 一个奖励 = 一次验证者 pass 产出六个 token。
在不同草稿质量水平下跑 1 万步投机,画接受率 vs 草稿与验证者分布的 KL 散度,应见干净的单调关系。
经验上:投机循环产出的 token 直方图应与从验证者直采的直方图匹配——这是 Leviathan 定理的实践,卡方检验在采样误差内确认。
设计要点:全接受时的「奖励 token」是投机解码的隐形红利——即使草稿全对,验证者的最后一次前向还顺带算出了下一位置的概率分布,白送一个 token,所以最理想情况是 N 个草稿 + 1 个奖励 = N+1 个 token 一次 pass。
生产:
# vLLM 配 EAGLE vllm serve meta-llama/Llama-3.1-70B-Instruct \ --speculative-model /models/llama-3.1-eagle-70b \ --speculative-draft-tensor-parallel-size 1 \ --num-speculative-tokens 5 # vLLM 配原生草稿模型 vllm serve meta-llama/Llama-3.1-70B-Instruct \ --speculative-model meta-llama/Llama-3.2-1B-Instruct \ --num-speculative-tokens 5
TensorRT-LLM 有 2026 年中最快的 Medusa 路径;faster-whisper 给 Whisper-large 配小草稿包了投机解码。
选草稿:
| 策略 | 何时选 | 加速 |
|---|---|---|
| 原生草稿(1B/3B Llama 家族) | 快速原型,不训练 | 1.8~2.3× |
| Medusa 头 | 能微调验证者 | 2~3× |
| EAGLE-2/3 | 生产,最大速度 | 3~4× |
| Lookahead | 无草稿、无训练、无额外参数 | 1.3~1.6× |
何时不投机解码:
原课程产出 outputs/skill-spec-decode-picker.md:一个选择器 Skill,为新推理负载选投机解码策略(原生/Medusa/EAGLE/Lookahead)和调参(N、草稿温度)。
code/main.py,确认 5 万 token 上投机 token 分布与验证者直采分布在卡方 p>0.05 内一致。N 的函数,α=0.5, 0.7, 0.85,找出每个 α 的最优 N(提示:每次验证产出 (1-α^(N+1))/(1-α))。min(1, q/p))→ 首次拒绝从残差采 → 丢弃之后 → 全接受送奖励 token。(q-p)_+ 归一化精确保持分布(Leviathan 定理):拒绝时从「q 比 p 多的概率」采,数学等价直采 q——零质量损失。(1-α^(N+1))/(1-α) ≈ 1/(1-α) token;α=0.75, N=5 时大模型调用少 3 倍、墙钟降约 2.5 倍。本章到此结束。从第 01 节的「为什么需要 Transformer」到这里的投机解码,你已经走完了现代 Transformer 的完整图景——注意力、位置编码、编码器/解码器、BERT/GPT/T5、ViT、Whisper、MoE、KV 缓存与 Flash Attention、缩放定律、注意力变体、投机解码。下一章,我们将把这些积木带上新的战场。