Skip to content
kefan.life
Go back

无损投机采样的概率论视角

投机采样(Speculative Sampling)用小模型猜、大模型验,能在不改变输出分布的前提下加速推理。“不改变输出分布”是整个方法的硬约束:外界无论用什么统计检验,都无法区分”大模型自己逐词生成”和”小模型猜测 + 大模型校验”两种模式的输出。

这篇文章只关注一个问题:这个”无损”是怎么在概率层面实现的?

问题的形式化

设词表中任意候选 token xx,在当前已接受前缀条件下,大模型给出的概率为 p(x)p(x),小模型给出的概率为 q(x)q(x)

在某个位置上,小模型以概率 q(x)q(x) 采样出候选 xx,大模型决定是否接受。如果接受,xx 直接输出;如果拒绝,从调整后的分布中重新采样。

目标:让 xx 最终被输出的概率严格等于 p(x)p(x)

执行流程

先看完整的一轮迭代是怎么跑的:

  1. Draft 阶段:小模型(draft model)自回归生成 KK 个候选 token:x1,x2,,xKx_1, x_2, \dots, x_K
  2. Verify 阶段:大模型(target model)对前缀 + 全部 KK 个候选做一次并行 forward,拿到每个位置上大模型自己的概率分布 pip_i
  3. 逐位置接受/拒绝:从位置 1 开始依次判定。一旦在位置 ii 触发拒绝,丢弃 xix_i 及其后所有 draft token,在位置 ii 从调整后的分布中重新采样一个 token,本轮结束
  4. 全部通过的 bonus:如果 KK 个 token 全部被接受,大模型的 forward 已经顺带算出了位置 K+1K+1 的分布,直接从中采样一个额外 token。

因此每轮产出最多 K+1K+1 个 token(全部接受 + bonus),最少 1 个 token(第一个就被拒绝,重采样补一个)。

为什么拒绝后必须立刻停止?一个 token 能被拒绝,前提是 p(xi)<q(xi)p(x_i) < q(x_i)pqp \ge q 时接受概率为 1,不可能触发拒绝)。而调整后的分布中 pqp \le q 的 token 权重为 0,不会被抽中,因此重新采样的结果必然不同于被拒绝的候选。而前缀一旦改变,后续的预测全都作废。

接受/拒绝规则

给定小模型采样出的候选 xx,接受概率为:

A(x)=min(1, p(x)q(x))A(x) = \min\left(1,\ \frac{p(x)}{q(x)}\right)

两种情况:

实际判定:生成均匀随机数 rU[0,1)r \sim U[0,1),当 r<A(x)r < A(x) 时接受,否则拒绝。

联合概率与总接受率

xx 被输出需要两步都成功:先被小模型提出,再通过接受判定。联合概率:

q(x)A(x)=q(x)min(1, p(x)q(x))=min(q(x), p(x))q(x) \cdot A(x) = q(x) \cdot \min\left(1,\ \frac{p(x)}{q(x)}\right) = \min(q(x),\ p(x))

关键性质:每个 token 在第一阶段能拿到的概率上限是 min(q(x),p(x))\min(q(x), p(x))

对所有 token 求和,得到总接受率:

α=xmin(q(x), p(x))\alpha = \sum_x \min(q(x),\ p(x))

α\alpha 是”小模型提出某个 token 且该 token 通过判定”的总概率。当 qpq \ne pα<1\alpha < 1,互补的 1α1 - \alpha 就是拒绝事件的总概率。

此时出现一个问题:

第二类 token 自身永远不会被拒绝(接受概率是 1),但小模型提议它的频率不够高,仅靠第一阶段无法凑满 p(x)p(x)。缺口必须从别处补回来。

调整分布:跨 token 的概率补偿

补偿来自别的 token 被拒绝时触发的重新采样。当小模型提出了一个 p<qp < q 的 token 并被拒绝,系统不会放弃这个位置,而是从调整后的分布中重新采样:

p(x)=max(0, p(x)q(x))1αp'(x) = \frac{\max(0,\ p(x) - q(x))}{1 - \alpha}

这个分布的构造逻辑:

因果链:p<qp < q 的 token 被过度提议 → 按比例拒绝,释放概率空间 → 触发重新采样 → 补偿 p>qp > q 的 token 的概率缺口。

闭环证明

xx 最终被输出的总概率 = 第一阶段直接通过 + 拒绝后从调整分布中被抽中:

Pfinal(x)=min(q(x),p(x))+(1α)p(x)P_{\text{final}}(x) = \min(q(x), p(x)) + (1 - \alpha) \cdot p'(x)

代入 pp' 的定义:

=min(q(x),p(x))+(1α)max(0, p(x)q(x))1α= \min(q(x), p(x)) + (1 - \alpha) \cdot \frac{\max(0,\ p(x) - q(x))}{1 - \alpha} =min(q(x),p(x))+max(0, p(x)q(x))= \min(q(x), p(x)) + \max(0,\ p(x) - q(x))

对任意实数 a,ba, b,恒有 min(a,b)+max(0,ab)=a\min(a, b) + \max(0, a - b) = a。因此:

Pfinal(x)=p(x)P_{\text{final}}(x) = p(x)

对词表中每一个 token 都成立。输出分布与大模型原始分布完全一致。证毕。

案例

假设词表有四个 token,概率如下:

Tokenq(x)q(x)(draft 给出)p(x)p(x)(target 给出)关系
A0.20.5p>qp > q,draft 低估了 A
B0.40.1p<qp < q,draft 高估了 B
C0.30.1p<qp < q,draft 高估了 C
D0.10.3p>qp > q,draft 低估了 D

第一阶段:各 token 被 draft 提出且通过接受判定的联合概率 min(q,p)\min(q, p)

总接受率 α=0.2+0.1+0.1+0.1=0.5\alpha = 0.2 + 0.1 + 0.1 + 0.1 = 0.5

总拒绝率 1α=0.51 - \alpha = 0.5,由所有 p<qp < q 的 token 共同贡献:B 的 0.30.3 和 C 的 0.20.2

调整后的分布:拒绝发生时的重新采样池 p(x)max(0, p(x)q(x))p'(x) \propto \max(0,\ p(x) - q(x))

归一化(除以 0.3+0.2=0.50.3 + 0.2 = 0.5):p(A)=0.6p'(A) = 0.6p(B)=0p'(B) = 0p(C)=0p'(C) = 0p(D)=0.4p'(D) = 0.4

最终概率 = 第一阶段通过 + 总拒绝率 ×\times 调整分布中的份额:

每个 token 精确对齐 target 分布。B 和 C 被拒绝释放出的总共 0.5 概率空间(0.3+0.20.3 + 0.2),被 A 和 D 按各自缺口比例(0.3:0.20.3 : 0.2)瓜分。

为什么必须用随机性

一个自然的疑问:为什么不用确定性阈值(比如 p(x)<q(x)p(x) < q(x) 就直接拒绝)?

因为确定性策略无法维持概率守恒。假设 p(x)=0.1p(x) = 0.1q(x)=0.2q(x) = 0.2。一刀切拒绝的话,xx 在输出中的概率变成 0,大模型原本赋予的 10% 可能性被抹杀。这就是有损解码,输出分布不再等于 pp

而投机采样的做法是:小模型以 0.2 的频率提出 xx,大模型以 0.10.2=0.5\frac{0.1}{0.2} = 0.5 的概率放行。最终 xx 出现的联合概率 =0.2×0.5=0.1= 0.2 \times 0.5 = 0.1,精确等于 p(x)p(x)

小结

投机采样的”无损”本质上是一个概率论问题:对于 qq 超出 pp 的 token,通过拒绝采样按比例拒绝,释放出概率空间;再通过调整分布,将这些空间精确分配给被 qq 低估的 token。由于 p(x)=q(x)=1\sum p(x) = \sum q(x) = 1,被高估 token 释放的概率总量必然等于被低估 token 的缺口总量(都等于 1α1-\alpha),因此补偿刚好闭合,输出分布恒等于 pp

整个机制不要求小模型准确。无论 qqpp 差多远,走完接受-拒绝-重新采样流程,数学保证输出分布与 pp 完全一致。


Share this post on:

Previous Post
FlashAttention 详解(V1 & V2)
Next Post
Roofline 分析:瓶颈的判定与局限