自回归范式:一步一步预测未来
自回归范式的核心思想非常直观,就像我们人类说话或写作一样:基于已经说出或写下的所有内容,来决定下一个要说的词或写的字。
模型的目标是学习一个条件概率分布 P(token_t | token_1, ..., token_{t-1}),即预测在已知前面所有Token的条件下,下一个Token是什么。
流程一:概念上的“朴素”自回归流程(无KV Cache)
这个流程在概念上是正确的,但计算效率较低。它清晰地展示了自回归的本质。
前提:模型已经训练完毕,我们拥有一个完整的词典(Vocabulary)和模型的权重。
-
第0步:初始化
- 输入: 提供一个特殊的起始符(Start Token),通常是
<BOS>(Begin of Sequence) 或[CLS]。这是生成过程的起点。 - 序列:
[<BOS>]
- 输入: 提供一个特殊的起始符(Start Token),通常是
-
第1步:生成第一个词(Token 1)
- 输入: 将当前序列
[<BOS>]送入Transformer模型。 - 计算: 模型对整个序列进行前向传播。通过多层自注意力机制,在序列的最后一个位置(即
<BOS>的位置)生成一个包含了所有上下文信息的最终隐藏状态h_0。 - 预测: 将
h_0通过一个线性层映射到词典大小的维度,然后用Softmax函数将其转换为概率分布。 - 选择: 从概率分布中选择一个词作为预测结果(例如,选择概率最高的词),我们称之为
token_1。 - 更新序列: 将新生成的词加入序列末尾。现在的序列是
[<BOS>, token_1]。
- 输入: 将当前序列
-
第2步:生成第二个词(Token 2)
- 输入: 将更新后的完整序列
[<BOS>, token_1]再次送入Transformer模型。 - 计算: 模型从头开始处理这整个序列。在最后一个位置(
token_1的位置)生成一个新的、融合了新上下文的最终隐藏状态h_1。 - 预测: 使用
h_1进行Softmax预测。 - 选择: 选出
token_2。 - 更新序列:
[<BOS>, token_1, token_2]。
- 输入: 将更新后的完整序列
-
第
t步:生成第t+1个词- 输入: 将长为
t+1的完整序列[<BOS>, token_1, ..., token_t]送入模型。 - 计算: 模型再次从头开始处理整个序列,在最后一个位置得到隐藏状态
h_t。 - 预测: 使用
h_t预测出token_{t+1}。 - 更新序列: 序列继续增长。
- 输入: 将长为
这个过程会一直重复,直到模型生成一个特殊的终止符 <EOS> (End of Sequence) 或达到预设的最大长度。
此流程的痛点:在生成第1000个词时,模型需要重新处理前面999个词,这造成了巨大的计算冗余和性能瓶颈。
流程二:高效的自回归流程(使用KV Cache)
为了解决上述痛点,实际应用中都采用KV Cache(键值缓存)技术。
什么是KV Cache?
在Transformer的自注意力机制中,每个输入的Token都会被映射成三个向量:查询(Query, Q)、键(Key, K) 和 值(Value, V)。
- Q:代表当前Token发出的“查询”,想知道自己应该关注哪些其他的Token。
- K:代表每个Token的“可被查询”的属性,像一个标签。
- V:代表每个Token实际包含的信息,像标签后面的内容。
一个Token的Q会和序列中所有Token的K进行计算,来决定从哪些Token的V中汲取信息。关键点在于:对于一个已经存在的Token,它的K和V向量是固定的,在后续的步骤中不会改变。 KV Cache正是利用了这一点。
使用KV Cache的自回归流程
前提:除了模型,我们还需要一个空的缓存区,用来存储每一层Transformer的K和V向量。
-
第0步:初始化
- 输入:
[<BOS>] - KV Cache: 为每一层都创建一个空的缓存,
KV_cache_layer_i = []。
- 输入:
-
第1步:生成第一个词(Token 1)
- 输入:
[<BOS>]。 - 计算: 模型处理
<BOS>,为它计算出Q, K, V向量。 - 缓存: 将
<BOS>的K和V向量存入每一层的KV Cache中。 - 预测: 基于计算结果,用Softmax预测出
token_1。 - 更新序列:
[<BOS>, token_1]。
- 输入:
-
第2步:生成第二个词(Token 2)
- 输入: 只需将新生成的
[token_1]作为输入! - 计算: 模型为
token_1计算出新的Q, K, V。 - 缓存: 将
token_1的K和V向量追加(append)到KV Cache的末尾。 现在缓存中包含了<BOS>和token_1的(K, V)对。 - 自注意力: 当计算
token_1的注意力时,它的Q向量会和KV Cache中所有的K向量(来自<BOS>和token_1)进行交互。这样,它就看到了完整的历史上下文,而无需重新输入<BOS>。 - 预测: 基于计算结果,预测出
token_2。 - 更新序列:
[<BOS>, token_1, token_2]。
- 输入: 只需将新生成的
-
第
t步:生成第t+1个词- 输入: 只需输入最新的
[token_t]。 - 计算: 为
token_t计算Q, K, V。 - 缓存: 将
token_t的(K, V)对追加到缓存中。此时缓存已存储了从<BOS>到token_t的所有历史K, V。 - 自注意力:
token_t的Q与缓存中全部t+1个K进行交互,获取完整的上下文信息。 - 预测: 预测出
token_{t+1}。
- 输入: 只需输入最新的
总结与对比
| 特性 | 朴素自回归流程 | 使用KV Cache的优化流程 |
|---|---|---|
| 每步的输入 | 完整的历史序列 [token_1, ..., token_t] | 仅当前新生成的 [token_t] |
| 计算量 | 随着序列增长,计算量平方级增长(O(t²)) | 每一步的计算量基本恒定(O(t),因为注意力计算仍需遍历缓存) |
| 核心思想 | 每次都从头回顾全部历史原文 | 只读新的一页,同时查阅之前做好的“历史笔记”(KV Cache) |
| 效率 | 非常低,仅用于教学和理解 | 非常高,是所有大型语言模型(如GPT)实际部署的标准方法 |
通过KV Cache,模型实现了高效的增量式生成,完美地平衡了自回归范式“需要完整历史信息”的需求和“避免重复计算”的工程现实。

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



