Chapter 56
自回归采样
- 大模型推理妙招—投机采样(Speculative Decoding): https://zhuanlan.zhihu.com/p/651359908
为了解决推理速度慢的问题,已经进行了许多针对推理的工程优化,例如改进的计算核心实现、多卡并行计算、批处理策略等等。然而,这些方法并没有从根本上解决LLM解码过程是受制于访存带宽的问题。
投机采样是一种可以从根本上解码计算访存比的方法,保证和使用原始模型的采样分布完全相同。
它使用两个模型:一个是原始目标模型,另一个是比原始模型小得多的近似模型。
近似模型用于进行自回归串行采样,而大型模型则用于评估采样结果。
解码过程中,某些token的解码相对容易,某些token的解码则很困难。因此,简单的token生成可以交给小型模型处理,而困难的token则交给大型模型处理。这里的小型模型可以采用与原始模型相同的结构,但参数更少,或者干脆使用n-gram模型。 小型模型不仅计算量较小,更重要的是减少了内存访问的需求。
自回归采样
先科普一下LLM解码时采用的自回归采样,其过程如下:
模型使用前缀作为输入,将输出结果处理+归一化成概率分布后,采样生成下一个token。 将生成的token和前缀拼接成新的前缀,重复执行1,直到生成EOS或者达到最大token数目。
第1步中,将模型输出logits的转换成概率,有几种常用的采样方法,包括argmax、top-k和top-n等。 自回归采样中生成的token一个一个地蹦出来,因为每次只对序列长度为1的部分进行有效计算,但是却需要对全部前缀对应位置的activations进行访问,因此计算访存比很低。
投机采样
投机采样过程如下:
用小模型Mq做自回归采样连续生成 y 个tokens。
把生成的 y 个tokens和前缀拼接一起送进大模Mp执行一次forwards。
使用大、小模型logits结果做比对,如果发现某个token小模型生成的不好,重新采样这个token。重复步骤1。
如果小模型生成结果都满意,则用大模型采样下一个token。重复步骤1。
第2步,将y个tokens和前缀拼成一起作为大模型输入,和自回归相比,尽管计算量一样,但是 y 个tokens可以同时参与计算,计算访存比显著提升。
第3步,如何评价一个token生成的不好?如果q(x) > p(x)(p,q表示在大小模型采样概率,也就是logits归一化后的概率分布) 则以一定1-p(x)/q(x)为概率拒绝这个token的生成,从一个新的概率分布p’(x) = norm(max(0, p(x) − q(x)))中重新采样一个token。
为什么投机采样和自回归采样等价
p(x’) > q(x’)说明大模型在token x’上概率大于小模型,则大模型对生成token x’更有把握,说明小模型生成的问题不大可以保留x’。
如果p(x’) ≤ q(x’)则小模型更有把握,大模型就以1-p(x)/q(x)为概率概率拒绝,并重新采样。因为接收的概率更偏向q(x)大的位置,重新采样的概率应该更偏向p(x)大的位置,所以是norm(max(0, p(x)-q(x))。
加速效果
投机采样相比自回归采样之所以有加速效果,因为它减少了对原始模型串行调用的次数。这里规定一次迭代可以接收小模型的tokens数为#generated tokens。
