
Introduction to Generative AI 2024 Spring
文章目录
1、第16講:可以加速所有語言模型生成速度的神奇外掛 — Speculative Decoding(24.05.17)
觉得现在语言模型还不够快吗?
+Speculative Decoding 后能提升 2~3 倍
预言家,预判接下来会说什么
eg:用原来只能输出一个 token 的时间,输出三个 token
不对啊,如果预言家可以准确预研接下来要生成的内容,给预言家生成就好了啊?
预言家可能会犯错
模型真正输出的结果,比对预言家的结果,一致保留,不一致也不亏,因为预言家很快
即使预言3个,错了2个,也仅仅损失预言家的时间,运算资源无谓的耗损
用运算资源换取运算时间
可以让 non-autoregressive model 当预言家,这样 speculative decoding 就是 AR 和 NAR 的结合
还可以用大模型压缩后的小模型来当预言家
预言家一定要是语言模型吗?搜索引擎也可以是预言家
也可以有多个预言家
2、Speculative Decoding
👉 Speculative Decoding(猜测解码) 就是:
🤖 让一个“小模型先帮你猜答案”,
🧠 再让“大模型快速检查对不对”,
👉 对的就直接用,错的再重算
👉 这样就能更快!
🍔 用生活例子理解
想象你在写作业:
- 👶 小朋友(小模型)先快速写一版答案(猜)
- 👨🏫 老师(大模型)来检查
两种情况:
✅ 猜对了
老师看了一眼:
👉 “对的!”
✔ 不用重新写
✔ 直接通过
👉 省时间!
❌ 猜错了
老师说:
👉 “不对,重写”
✔ 只改错的地方
👉 比从头写快很多
⚡ 为什么能加速?
正常大模型是这样工作的:
一个字一个字慢慢生成
👉 很慢 ❗
用了 Speculative Decoding:
小模型:一次猜 5 个字
大模型:一次检查 5 个字
👉 就变成:
✔ 少调用大模型
✔ 一次处理更多内容
👉 速度直接提升 2~5 倍(甚至更多)
原来:
N tokens = N 次 forward
现在:
N tokens ≈ N/K 次 forward
👉 如果 K=4:
👉 理论加速 ≈ 4 倍(实际 2~3 倍)
🔥 autoregressive 不是一次只能出一个 token 吗?
❓ autoregressive 不是一次只能出一个 token 吗?
👉 对,但只对“生成”成立,不对“验证”成立
🟢 1. 生成(必须一步一步)
P(x1)
P(x2 | x1)
P(x3 | x1,x2)
👉 必须按顺序
👉 因为不知道下一个 token
🔵 2. 验证(可以并行!)
现在我们已经有小模型给的:
y1, y2, y3, y4
👉 注意:
👉 这些 token 已经“已知”了!
🎯 关键点来了!
大模型可以这样做:
👉 把整段一起喂进去:
[x0, y1, y2, y3]
👉 一次 forward 输出:
P(y1 | x0)
P(y2 | x0,y1)
P(y3 | x0,y1,y2)
P(y4 | x0,y1,y2,y3)
⚡ 为什么可以“一次算出来”?
因为 Transformer 本质是:
👉 并行计算所有位置的概率(teacher forcing)
🧠 Transformer 的秘密(核心理解)
在训练时,模型就是这样算的:
输入:我 爱 吃 苹果
输出:
P(爱 | 我)
P(吃 | 我爱)
P(苹果 | 我爱吃)
👉 一次 forward 全算出来!
🧠 一个“最关键理解”(很多人卡这里)
👉 autoregressive 的限制在“未知 token”,一旦 token 已知,就可以并行算概率
🔧 实际中怎么用?
在 AI 系统里一般这样做:
🟢 Step 1:小模型先生成
比如:
输入:今天天气很好,我想去
小模型:公园散步玩耍
🟡 Step 2:大模型验证
大模型会:
👉 一个字一个字检查:
公 ✔
园 ✔
散 ✔
步 ✔
玩 ✔
耍 ❌(不太合适)
🔴 Step 3:修正
👉 前面正确的直接用
👉 错的地方重新生成
🎯 怎么判断“预言家(小模型)靠不靠谱”?
主要看 3 件事:
🧩 1. 看通过率(命中率)
👉 小模型猜的内容:
- 90%都被接受 ✅ → 很靠谱
- 50%被打回 ❌ → 不靠谱
🧩 2. 看概率(置信度)
大模型会算:
这个词出现的概率高不高?
👉 如果:
- 概率高 → 接受
- 概率低 → 拒绝
🧩 3. 连续接受长度
👉 一次能连续通过多少个 token:
- 连续通过很多 👉 小模型很强
- 经常被打断 👉 小模型很弱
🎯 什么时候效果最好?
👉 Speculative Decoding 最适合:
- 📚 自然语言(连续性强)
- 🧠 小模型和大模型“风格接近”
- 🔁 长文本生成
👉 效果差的情况:
- 🧮 数学推理(容易分歧)
- 🎯 精确生成(代码、符号)
- 🤯 小模型太弱
⚙️ 工程里的关键优化点
🟢 1. 一次验证多个 token(核心加速点)
👉 不是一个一个算,而是:
一次 forward = 验证 K 个 token
👉 这就是为什么快
🟡 2. KV Cache 复用
👉 大模型不会重复计算历史:
只算新增 token
👉 极大降低计算量
🔵 3. 动态调整 K(很关键)
👉 如果小模型很准:
K = 8 / 16
👉 如果不准:
K = 2 / 4
👉 自动平衡速度和浪费
🔴 4. 提前终止(Early Stop)
一旦发现错误:
立即停止验证后面的 token
👉 避免浪费计算
🚀 GPU 上真实执行时间线(工程版)
先看没有 Speculative Decoding时:
时间 →
┌────────┬────────┬────────┬────────┐
│ forward│ forward│ forward│ forward│
│ token1 │ token2 │ token3 │ token4 │
└────────┴────────┴────────┴────────┘
👉 每次 forward(大模型推理)
👉 只生成 1 个 token
❗ GPU 利用率其实不高(很多等待)
🚀 加了 Speculative Decoding 后
时间 →
┌──────────────────────┬──────────────────────┐
│ 小模型:生成 K=4 tokens │ 小模型:再生成 K=4 │
└──────────┬───────────┴──────────┬───────────┘
↓ ↓
┌────────────────────────────────────┐
│ 大模型:一次 forward 验证 4 个 token │
└────────────────────────────────────┘
👉 关键变化:
- ❌ 原来:1 次 forward = 1 token
- ✅ 现在:1 次 forward = 验证 K 个 token
👉 GPU 一次干更多活 → 吞吐提升
🧠 核心总结(超简单版)
🎯 所以 Speculative 利用了什么?
👉 把“生成问题”变成“打分问题”
生成(慢) → 验证(快)
👉 Speculative Decoding 就是:
先猜 → 再检查 → 对的直接用 → 错的再改
👉 加速原因:
少用大模型,多用小模型
👉 判断小模型好不好:
看猜对的比例高不高
小模型先猜一串
大模型逐个来审判
通过直接往前走
不对立刻重新算
👉 核心本质:
加速的是“计算路径”,不是“概率结果”
生成:必须串行(因为未知)
验证:可以并行(因为已知)
👉 Speculative 做的就是:
用小模型把“未知 → 变已知”
再让大模型并行处理
3、举个例子
用一个极小的模型先去“猜”后面几个字,再让大模型来一键“批改”。
1. 实际中如何应用(工作流)
在实际部署中,它通常包含两个角色:
- Draft Model(草稿模型/预言家):一个小模型(比如几亿参数),速度极快,但逻辑一般。
- Target Model(目标模型/主官):你想真正使用的大模型(比如几百亿参数),逻辑极强,但速度慢。
具体步骤:
- 小模型连猜 K K K 步:小模型以 AR(自回归)方式快速吐出 K K K 个词(比如 4 个词)。
- 主模型一键审核:主模型拿到这 K K K 个词,进行一次并行推理。
- 结果对比:主模型判断小模型猜的前 N N N 个词是否符合自己的概率分布。
2. 加速的原理:从 AR 变回并行
还记得我们聊过的 AR(自回归) 为什么慢吗?因为它必须一个词一个词地蹦。
Speculative Decoding 的本质是利用了 GPU 的“算力闲置”:
- 算力 vs 带宽:大模型推理通常受限于“显存带宽”而不是“计算算力”。在处理一个词时,GPU 大部分算力其实在“等”显存里的权重数据加载。
- 并行验证:主模型验证小模型猜出来的 K K K 个词,在底层计算上只需要 一次 Forward 过程。
- 数学账单:
- 没有投机:生成 4 个词需要主模型跑 4 次。
- 有投机:如果小模型全猜对了,主模型只跑了 1 次就生成了 4 个词。
- 即便小模型猜得全错,主模型也就跑了 1 次,并不亏多少(因为反正都要跑 1 次)。
3. 如何确定预言家(小模型)是否可靠?
这是这项技术最优雅的部分:拒绝采样(Rejection Sampling) 机制。
我们不需要在生成前判断它可不可靠,而是在生成的瞬间通过概率比对来验证:
- 接受概率:设小模型预测下一个词的概率为 p ( x ) p(x) p(x),主模型的概率为 q ( x ) q(x) q(x)。
- 验证标准:
- 如果 q ( x ) ≥ p ( x ) q(x) \ge p(x) q(x)≥p(x),主模型觉得“你猜的比我想的还要稳”,直接接受。
- 如果 q ( x ) < p ( x ) q(x) < p(x) q(x)<p(x),主模型会以 q ( x ) p ( x ) \frac{q(x)}{p(x)} p(x)q(x) 的概率有条件接受。
- 截断机制:一旦某个词被主模型“毙掉”(判定为不可靠),它后面的词即便全对也会被扔掉,主模型会根据自己的概率分布重新纠正这一个词,然后开始下一轮投机。
4、推测解码验证流程图
推测解码(Speculative Decoding)的核心在于:“小模型(Draft Model)低成本试错,大模型(Target Model)高效率审核”。
eg:当小模型预测出“我”、“爱”、“吃”、“苹果”这四个词后,大模型会通过一次前向传播(Forward Pass)同时算出这四个位置的概率分布。
以下是其验证逻辑的流程图:
1. 并行采样(Parallel Scoring)
大模型不会像小模型那样一个词一个词地蹦。它会将小模型给出的序列 [ x 1 , x 2 , x 3 , x 4 ] [x_1, x_2, x_3, x_4] [x1,x2,x3,x4] 拼接到已知前缀后,作为一个 Batch 输入。
- 输入:
[Prefix, 我, 爱, 吃, 苹果] - 大模型输出(Logits):
- 在“我”的位置,预测下一个词的分布 P 1 P_1 P1
- 在“爱”的位置,预测下一个词的分布 P 2 P_2 P2
- 在“吃”的位置,预测下一个词的分布 P 3 P_3 P3
- 在“苹果”的位置,预测下一个词的分布 P 4 P_4 P4
2. 逐位验证(Token Validation)
大模型会拿自己的 P i P_i Pi 去看小模型选的词是否合理。通常使用拒绝采样(Rejection Sampling):
- 验证 T1 (“我”):看 P 1 P_1 P1 中“我”的概率。如果通过,继续;
- 验证 T2 (“爱”):看 P 2 P_2 P2 中“爱”的概率。如果通过,继续;
- 验证 T3 (“吃”):假设大模型认为这里应该是“喝”,则 P 3 P_3 P3 指向“喝”的概率远高于“吃”。此时验证失败。
3. 截断与修正(Truncation & Correction)
一旦某个位置(如 T3)验证失败:
- 立即截断:即便 T4 (“苹果”) 在语义上没错,但因为它建立在错误的 T3 基础上,大模型也会直接丢弃 T4。
- 修正输出:大模型会直接给出它在 P 3 P_3 P3 位置采样出的正确词(比如“喝”)。
4. 奖励步(The Bonus Token)
如果小模型预测的 k k k 个词全中了,大模型在验证完最后一个词 T k T_k Tk 的同时,其实已经算出了 T k + 1 T_{k+1} Tk+1 的分布。因此,大模型会额外多给一个词。这意味着如果推测全对,一轮可以产出 k + 1 k+1 k+1 个词。
5、参考
- https://speech.ee.ntu.edu.tw/~hylee/genai/2024-spring.php
- https://www.bilibili.com/video/BV18fXbY6Eis/?spm_id_from=333.1387.homepage.video_card.click&vd_source=8e91f8e604278558ec015e749d1a3719











&spm=1001.2101.3001.5002&articleId=160375282&d=1&t=3&u=8f4b13894f9b43569156618889a52a1e)
1316

被折叠的 条评论
为什么被折叠?



