跳到主要内容
约 14 分钟6 张卡

Transformer 与注意力机制

Transformer 是通过注意力和前馈网络处理序列的神经网络结构。注意力按相关程度汇总不同 Token 的信息,前馈网络再对各个 Token 的表示做变换。Token 是模型处理文本的基本单位,可以是词或更小的片段。

本文先介绍整体结构与位置信息,再解释自注意力怎样计算。随后用 KV Cache 和 FlashAttention 说明推理成本,最后讨论长对话中的信息遗漏。下文以稠密因果自注意力为主:每个位置都可以关注它自身及之前的全部位置。

1. 面试核心​

先记住这几条,再读正文
  • 编码器与解码器。 Transformer 编码器通过双向自注意力读取前后文,因果解码器通过掩码屏蔽未来位置。卡 · 整体结构
  • 自注意力。 自注意力用 Q 与 K 的匹配分数计算权重,再按权重汇总 V,得到融合上下文的表示。卡 · 自注意力的计算
  • KV Cache。 KV Cache 保存每层历史 Token 的 K、V,解码时只新增当前 Token 的投影,再读取缓存计算注意力。卡 · KV Cache 与推理成本
  • 长序列成本。 稠密预填充的注意力计算随序列长度平方增长。卡 · 注意力的局限
  • FlashAttention。 FlashAttention 通过分块降低显存读写,保留精确注意力计算。卡 · FlashAttention

2. 整体结构​

原始 Transformer 用于翻译,由编码器和解码器组成。编码器双向读取源句,解码器则逐个生成译文,并通过交叉注意力读取编码器的输出。交叉注意力指查询来自解码器,而用于匹配和汇总的内容来自编码器。

按是否保留编码器与解码器,可以区分以下三类结构:

结构信息可见范围示例任务代表模型
仅编码器自注意力读取左右上下文分类、检索表示BERT
编码器—解码器解码器读取历史输出与编码结果翻译、摘要T5
仅解码器因果自注意力读取当前及此前位置自回归生成GPT、Llama、Qwen

仅编码器也可用于生成文本嵌入向量和重排序。嵌入向量用一组数表示文本,供相似度检索使用;重排序则对候选文档重新评分。仅解码器模型用预测下一个 Token 的方式完成生成任务,下面沿着它的推理过程理解各层作用:

  1. 嵌入与位置处理:嵌入层把 Token ID 转成向量,模型再引入位置信息。向量表示内容,位置信息则帮助模型区分相同词语在不同位置的作用。
  2. 解码块:向量依次经过多个解码块。每个块包含注意力和前馈网络,并配合残差连接与归一化。注意力在不同位置之间汇总信息,前馈网络则对各位置分别变换。
  3. 词表投影:最后的表示经过线性层,得到词表中每个 Token 的分数。softmax 将分数转成概率,再由采样规则选出下一个 Token。

前馈网络对每个位置使用同一组参数。原始结构先用全连接层扩展维度,经过非线性变换,再用第二层压回原维度。模型也可以采用门控结构,用另一组计算结果调节信息通过的程度。

残差连接把子层输入加回输出,有助于信息和训练梯度传播。归一化则调整数值尺度,使计算更稳定。原始论文在子层之后使用 LayerNorm;Llama 等模型在子层之前使用 RMSNorm。两者都是归一化方法,因此解释具体流程时,要区分采用哪种结构。

训练时,整段已知序列可以并行计算多个位置。为了防止模型提前读到要预测的后文,因果掩码会屏蔽未来位置。生成时,下一个 Token 要等当前 Token 被选出后才能确定,所以自回归解码仍需逐步进行。

2.1 位置表示与 RoPE​

注意力按内容匹配信息,还需要位置信息才能区分词序。原始 Transformer 将位置编码加入输入向量。RoPE 是旋转位置编码,它将位置关系放进 Q 与 K 的计算。

具体做法是按 Token 的位置,旋转 Q 和 K 中成对的向量分量。两个位置旋转角度的差,与它们的相对距离有关。因此,旋转后的 Q、K 点积就带有相对位置信息。Q 与 K 各自的作用会在下一节展开。

超出训练时见过的长度后,模型是否仍能用好位置关系,需要重新验证。位置缩放会调整位置与旋转角度的对应关系,但效果还要用具体任务检验。接口能接收长输入,只说明长度符合接口限制,关键事实提取和任务成功率仍需测试。

3. 自注意力的计算​

自注意力解决的是:当前 Token 应从上下文中的哪些 Token 获取信息。它先计算匹配分数,再将分数转成权重,最后按权重汇总内容。

输入矩阵 X 包含 n 个 Token,每个 Token 用一个 d 维向量表示。三个可学习的投影矩阵分别将 X 转成 Query、Key 和 Value,简称 Q、K、V。这里的投影就是用矩阵乘法,将输入变成适合当前计算的向量表示。

Q = X W_Q
K = X W_K
V = X W_V
Attention(Q, K, V) = softmax(Q Kᵀ / √d_k + mask) V

Q 表示当前位置要查找什么信息,K 用来与查询匹配,V 则是匹配后要汇总的内容。比如,“小明拿起杯子,把它放在桌上”中的“它”,可以通过注意力读取前文“杯子”的信息。这个例子说明指代关系,具体权重仍由训练后的模型计算。

公式中的计算可以拆成匹配、缩放与掩码、归一化、汇总四步:

  1. 匹配:每个位置的 Q 与各位置的 K 做点积。单头的 QKᵀ 形状为 n×n,一行对应一个查询,一列对应一个被关注的位置。
  2. 缩放与掩码:匹配分数除以 √d_k,其中 d_k 是该头中 Q、K 的维度。因果掩码把未来位置的分数设为负无穷,使这些位置在下一步得到零权重。
  3. 归一化:softmax 按行把分数转换为总和为 1 的权重。分数越高的位置,分到的权重越大。
  4. 汇总:权重与 V 相乘,得到各位置 Value 的加权和。结果就是当前位置融合上下文后的表示。

缩放是为了避免维度增大后,分数差异过大。假设向量分量独立、均值为 0、方差为 1,点积的方差就为 d_k。除以 √d_k 后,分数尺度受到控制。否则,softmax 容易给某个位置接近 1 的权重,其余位置接近 0。这称为饱和,会让梯度变小,影响训练。

多头注意力使用多组投影,在不同的向量子空间中分别计算注意力。标准多头注意力将总表示维度分配给 h 个头,各头汇总后再拼接,并经过线性变换。不同头可以学习语法依赖、指代或相邻位置等关系,具体关注什么取决于训练结果。

手写实现时,常见张量形状是 (batch, heads, n, d_head)。它依次表示批量大小、头数、序列长度和每头维度。需要核对分头与拼接是否正确,并确认缩放项使用每头维度,掩码覆盖未来位置。

3.1 MHA、MQA 与 GQA​

多头注意力会产生多组 K、V,保存和读取它们都需要资源。为了减小缓存,可以让多个 Query 头共享 K、V。按共享方式区分三种结构:

  • MHA,即多头注意力,为每个 Query 头配备独立的 K、V 头。
  • MQA,即多查询注意力,让所有 Query 头共享一组 K、V。
  • GQA,即分组查询注意力,将 Query 头分组,每组共享一组 K、V。

共享后,需要保存和读取的 K、V 变少,但各头独立表示信息的能力也会受到影响。因此,这几种结构是在模型表达能力与缓存成本之间做取舍。头数由模型结构决定,应用侧调整采样参数不会改变它。

4. KV Cache 与推理成本​

解码每生成一个新 Token,都需要读取此前 Token 的信息。旧位置在因果掩码下只依赖它自己与之前的内容,所以新增 Token 不会改变旧位置的 K、V。每步重新计算这些结果,就会产生大量重复工作。

KV Cache 将每层已经计算好的 K、V 保存下来。下一步只计算新 Token 的 Q、K、V,将新的 K、V 追加进缓存,再读取缓存完成注意力计算。旧 Q 无需保存,因为后续只需要计算新位置的输出。

为了区分省下了哪些计算,下表固定模型宽度与层数,比较预填充和解码的注意力工作量:

阶段注意力工作量延迟关系
稠密预填充固定头维度时为 O(n²)影响首 Token 延迟
单步解码对长度 t 的缓存做 O(t) 注意力影响逐 Token 延迟
连续解码累积读取增长中的前缀长输出仍有持续成本

预填充一次并行处理整段输入,计算量较大。解码则逐个生成 Token,每步都要读取模型权重和已有的 KV Cache。批量较小时,数据读取容易跟不上计算速度,这时显存带宽就成为瓶颈。它表示单位时间能从显存传输多少数据。

因此,KV Cache 省去了旧 Token 的重复计算,但新 Q 与历史 K、V 的注意力计算仍然存在。前缀越长,每步要读取的缓存越多,逐 Token 延迟和吞吐也会受影响。吞吐指单位时间能处理的请求或生成的 Token 数。实际瓶颈还取决于批量大小、模型结构与硬件。

长上下文和高并发都会增大缓存,KV Cache 因而会占用大量显存。对未量化、等长序列,可以按下式估算容量:

字节数 ≈ 2 × 层数 × KV头数 × 每头维度
× 序列长度 × 批量大小 × 每元素字节数

系数 2 对应 K 与 V,批量大小反映同时保存多少条序列的缓存。序列长度或并发数增加时,缓存随之增长。公式尚未计入分配开销、模型权重和其他中间结果。

减小缓存占用,可以从分配方式、数值精度和头数入手:

  • 分页管理将缓存按块分配,减少连续大块分配造成的碎片和预留浪费。vLLM 的 PagedAttention 使用这种思路。
  • 量化用更少的字节保存每个数值,从而减小缓存体积,同时需要验证精度变化的影响。
  • GQA 从模型结构上减少 KV 头数,所以缓存容量和读取量都随之下降。

前缀缓存将相同前缀的 KV Cache 跨请求复用,省去命中部分的预填充计算。它可以降低首 Token 延迟,托管 API 还可按缓存规则降低输入费用。命中要求与保存期限取决于具体服务。

相同前缀为何能复用,见大语言模型基础。

稳定的系统提示与工具定义放在前面,更有利于命中缓存,具体顺序见上下文管理。

4.1 FlashAttention​

直接计算注意力时,完整的 n×n 分数与权重矩阵会占用大量中间存储。FlashAttention 要解决的就是这些中间结果带来的显存读写开销。

它将 Q、K、V 分块,在速度更快、容量更小的片上存储中计算。在线 softmax 随着分块逐步更新归一化所需的数值,再合并输出。因此,算法无需把完整的 n×n 注意力矩阵写入显存,减少了显存与片上存储之间的数据移动。

FlashAttention 保留精确注意力的数学计算,稠密预填充的算术复杂度仍为 O(n²)。它节省中间存储和显存读写,KV Cache 则复用历史 Token 的 K、V。两者优化不同的开销,可以组合使用。

5. 注意力的局限​

注意力能从上下文提取信息,但长对话会同时带来资源成本和信息利用问题。分析 Agent 的上下文策略时,需要区分以下四类局限:

  • 计算与缓存成本:稠密预填充的注意力计算随长度平方增长,解码缓存则随长度和并发增长。即使用缓存避免了重复计算,每步仍需读取历史,所以长输入和长输出都会增加成本。
  • 信息位置的影响:Lost in the Middle 在所测模型与任务中发现,证据在开头或结尾时效果较好。证据移到中间后,回答准确率下降。这个结果提示应用检查关键约束是否被遗漏,具体影响应在目标模型上验证。
  • 无关内容的干扰:工具日志和无关文档增加后,模型更难找到当前任务的证据。因此,即使长度尚未超限,也需要筛选与当前步骤有关的信息。
  • 跨请求状态:注意力只能读取本次输入,多轮会话由应用或服务端保存并补入历史。窗口外的信息需要重新检索或加载,才能参与本次生成。

这些局限要求应用按当前任务选择上下文。关键约束放在明确的状态区,并测试放在开头或结尾的效果;具体方法见上下文管理。

旧历史可以压缩为结构化摘要,但目标与硬性约束要保留,见上下文压缩。

大段工具输出可以保存到外部,只把结论和引用放回输入;跨会话信息可按需检索,见Agent 记忆。

子任务也可以在独立上下文中执行后,只返回结果与证据,见多 Agent 协作。

6 · 面试题卡片​

本页题目与参考回答

6.1 介绍一下 Transformer 的核心结构与推理流程,Encoder 和 Decoder 有什么区别?​

考察重点:能解释三类结构的注意力方向,并沿嵌入、解码块和词表投影说明推理流程。

相关内容:整体结构、一次生成的过程。

参考回答

Transformer 通过注意力、前馈网络、残差与归一化处理序列,编码器与解码器的主要区别是信息可见范围。

编码器用双向自注意力读取前后文,适合分类、检索表示和重排序。原始解码器用因果自注意力读取当前及此前位置,再通过交叉注意力读取编码结果。仅解码器结构省去编码器与相应的交叉注意力,用预测下一个 Token 完成生成。

Token ID 先经过嵌入和位置处理,再通过多个解码块。注意力汇总不同位置的信息,前馈网络分别变换各位置,残差与归一化帮助稳定计算。最后映射到词表分数,再经 softmax 得到概率。原始结构与 Llama 等模型的归一化位置和前馈结构有所不同,需按具体模型说明。

推理先预填充整段输入,再逐 Token 解码。解码时用 KV Cache 复用旧 K、V,但仍要计算新 Token 对历史的注意力。

6.2 自注意力怎样计算?Q、K、V 分别是什么,为什么要除以 √d?多头注意力有什么作用?​

考察重点:能说明 Q、K、V 的作用、各步矩阵形状,以及缩放、掩码与多头计算的原因。

相关内容:自注意力的计算。

参考回答

自注意力用 Q 与 K 计算匹配权重,再对 V 加权求和,从而汇总上下文信息。

Q、K、V 由输入乘以三个可学习矩阵得到,分别用于查询、匹配和提供内容。单头 QKᵀ 得到 n×n 的匹配分数,除以 √d_k 后加因果掩码。随后按行 softmax,把分数转成和为 1 的权重,再与 V 相乘。

分量独立、均值为 0、方差为 1 时,点积方差为 d_k。维度增大会拉大分数差,让 softmax 趋于饱和、梯度变小。除以 √d_k 可以控制这种尺度变化。

多头在不同子空间独立计算,再拼接并线性变换,让模型学习不同关系。实现时检查 (batch, heads, n, d_head) 形状,以及缩放项是否使用每头维度。未来位置的分数用负无穷填充,softmax 后对应权重为零。

6.3 KV Cache 是什么?为什么能加速推理?前缀缓存与它是什么关系?​

考察重点:能解释历史 K、V 为什么可以复用,并说明显存代价与跨请求前缀缓存的关系。

相关内容:KV Cache 与推理成本、组装顺序与前缀缓存。

参考回答

KV Cache 保存每层已处理 Token 的 K、V,让解码复用旧结果,前缀缓存则把这种复用扩展到多个请求。

因果掩码让旧 Token 只依赖它自身及之前的内容,所以新增 Token 不改变旧 K、V。下一步只计算新 Token 的 Q、K、V,将 K、V 追加后读取缓存做注意力。历史投影的重复计算省去了,但每步仍要与历史 K、V 计算注意力。

缓存大小随层数、KV 头数、每头维度、序列长度和并发增长。分页管理减少分配浪费,量化降低每个数值的存储字节数,GQA 则减少 KV 头数。

两个请求在同一模型下有完全相同的输入前缀时,可以复用该段缓存,省去相应预填充。这样能降低首 Token 延迟,并按服务规则降低输入费用。稳定的系统提示与工具定义放在前面,本轮输入等变化内容放在后面,更有利于命中。缓存命中范围与期限还取决于服务规则。

6.4 在 Agent 多轮对话任务中,注意力机制有哪些局限?工程上怎样应对?​

考察重点:能区分计算成本、信息遗漏与会话状态,并据此说明上下文选择和压缩方法。

相关内容:注意力的局限、上下文压缩。

参考回答

长对话会增加计算与缓存成本,也会带来证据遗漏、无关信息干扰和跨请求状态管理问题。

稠密预填充的注意力计算为平方量级,缓存解码每步仍需读取历史。在长文档任务中,中间证据更容易被遗漏的现象已有实验观察,但应在目标模型上验证。日志和无关文档也会干扰信息提取,所以输入内容要随当前任务筛选。

Agent 每轮保留当前步骤所需的证据、近期状态、目标和硬性约束。旧历史压缩为结构化摘要,大段工具输出只保留结论与引用,原文放在外部按需读取。跨会话信息由应用或服务端保存,再检索到本次输入中。独立子任务也可以分配独立上下文,完成后返回结果与证据。

6.5 RoPE 怎样表达位置,能否直接保证任意长度可用?​

考察重点:能解释旋转如何让点积包含相对位置信息,并说明长度外推需要验证什么。

相关内容:位置表示与 RoPE。

参考回答

RoPE 按位置旋转 Q、K,使点积带有相对位置信息,但有效长度仍需要验证。

旋转角度由位置决定,两个位置的角度差反映它们的相对距离。模型因此能在匹配内容时利用位置关系。超出训练长度后,效果还取决于位置缩放等处理方式。

接口接受超长输入后,仍要测试关键事实提取和任务成功率,确认模型能用好远处的证据。

6.6 FlashAttention 和 KV Cache 分别节省什么?​

考察重点:能区分中间矩阵读写与历史 K、V 重算,并解释两种优化为何可以同时使用。

相关内容:FlashAttention。

参考回答

FlashAttention 节省注意力中间存储和显存读写,KV Cache 省去旧 Token 的 K、V 重算。

FlashAttention 分块执行精确注意力,通过在线 softmax 合并结果,避免将完整 n×n 中间矩阵写入显存。它减少数据移动,但稠密预填充的算术复杂度仍为 O(n²)。

KV Cache 保存每层历史 K、V,让下一步只新增当前 Token 的投影。单步解码仍需读取历史缓存,所以它解决的是重复计算问题。两种优化作用不同,可以同时使用。

7. 参考资料​