模型采样投机解码是一种采样方式先来看模型是如何采样的模型的最后一层输出是一个长度等于词典大小的向量表示下一个token是词典中每个词的概率。采样就是根据这个概率向量选出来下一个token也就是不会改变模型的推理架构。最简单的采样方式就是谈心采样每一步都选向量中概率最大的token。也投机解码投机解码是想要优化这个采样过程思想是原来的解码方法每次只能解码一个token是严格串行的一个自然的想法就是能不能并行这个过程一次预测多个token。投机解码的做法是让一个小模型预测草稿连续调用这个小模型预测多步一次性输出多个token然后让大模型并行验证每一个预测是不是对的如果对的则接受不对则根据策略来接受或修改。这里的巧妙之处在于小模型预测多次是串行的但是小模型参数量很少比大模型推理要快很多。大模型只负责检验检验由于是在已有的基础上做的通过类似训练时的因果掩码可以同时预测多个前缀的下一个token也就是检验阶段可以并行。整体下来时间是比大模型串行推理多个token要快的。找到大模型结果和小模型结果对比第一个验证失败的token这个位置用大模型的预测结果替代小模型前面的预测结果接受后面的丢掉。验证阶段验证最简单的就是对比大模型预测和小模型预测的最大概率token是不是同一个但这有点过于苛刻了。实际预测采取的是一个更灵活的方法。小模型连续预测了多个位置大模型并行检验也预测了相同数量的位置。此时对于每个位置我们手上有两组概率小模型的概率q ( x ) q(x)q(x)—— 小模型生成这些词时的自信度。大模型的概率p ( x ) p(x)p(x)—— 大模型认为这些词应该出现的概率。大模型会从第一个草稿 Tokenx 1 x_1x1​开始逐个验证如果大模型觉得小模型猜得很好p ( x 1 ) ≥ q ( x 1 ) p(x_1) \ge q(x_1)p(x1​)≥q(x1​)也就是说大模型自己算出来的概率比小模型还要高或者相等。直接接受小模型的预测继续看下一个位置。如果大模型觉得小模型在瞎猜p ( x 1 ) q ( x 1 ) p(x_1) q(x_1)p(x1​)q(x1​)这意味着小模型太自信了但大模型觉得这个词没那么靠谱。这时候大模型不会一棒子打死而是会计算一个接受概率接受概率 p ( x 1 ) q ( x 1 ) \text{接受概率} \frac{p(x_1)}{q(x_1)}接受概率q(x1​)p(x1​)​大模型会采样一个0到1的随机数看是否坐落在[ 0 , p ( x 1 ) q ( x 1 ) ] [0,\frac{p(x_1)}{q(x_1)}][0,q(x1​)p(x1​)​]内如果在则接受小模型的预测继续看下一个如果不接受后面的预测不用看了都作废。一旦一个位置的预测被大模型拒绝了这个位置之后的丢掉这个位置会使用大模型的预测结果作为替代推理策略推理时选择的小模型也有讲究。一种策略是选择一个独立的预测模型这样的优点是预测模型可以很小推理快部署需要的资源少且可以对这个小模型做单独训练。缺点是小模型和大模型可能预测出的概率分布不一样很容易被拒绝被拒绝太多就相当于小模型预测一个大模型预测一个没有加速效果了。另一种策略是直接使用验证模型本身进行预测但对验证模型做一些裁剪比如下图4层注意力只运行2层就输出了降低推理时间这被称为自投机解码。这样的优点是本质上是相同模型的小参数版本预测和验证时分布更接近预测更容易被接受且只需要维护一个模型更简单。缺点是验证模型裁剪后推理速度可能还是不如小模型快加速效果不明显且不能对预测模型做独立训练MTP另一个和投机解码有点类似的概念是MTP多token预测。和投机解码一样也可以一次预测多个token但区别在于投机解码本身是一种后处理不懂模型结构是拿到概率后的操作但MTP是在模型层面就设计成一次输出多个token最早MTP由meta提出思路是在注意力层结束后设置多个并行的分类头同时输出多个token的概率分布分别作为接下来第一个第二个第三个……第k个token这样的缺点是并行的头不好训练MTP第一次在工业生产中被大规模使用是DeepSekk V3此时为了使模型更好训练把并行预测多个token改成串行预测了如下图进行多个注意力层最后几个注意力层每层预测一个新token。这样虽然牺牲了一些并行度但梯度爆炸减少了更好训练。注意不要搞混串行MTP看起来也是运行一步输出一个token和非MTP很像。但仔细看的话会发现输出多个token都是模型一次前向里做的相当于把原本最后几层注意力拿出来每层接上一个分类头。而非MTP架构一次前向传播只输出一个token还是不一样的。