2026.08.25 · WRITING

Transformer 如何用 Self-Attention 理解上下文

从一句服务调用出发,跟着一个 token 走完 Self-Attention:看它如何生成 Query、Key、Value,计算 Attention Weights,并在 Multi-Head Attention 中汇总上下文。

Self-Attention 会让每个 token 根据当前可见的上下文,更新自己的表示。

这句话听起来还是很抽象。下面不从公式开始,而是跟着一个 token 走一遍完整过程。

刚进入模型时,token 还不理解上下文

假设输入是:

服务 A 调用了配置中心 B,因为它需要获取最新配置。

文本会先被切分成 token,再转换成向量。位置信息如何进入模型取决于具体设计:原始 Transformer 把 Positional Encoding 加到输入 Embedding 上,使用 RoPE 的模型则会在后续的 Query 和 Key 计算中编码位置。无论采用哪种方式,单看“它”的词向量,模型都无法确定它指的是服务 A,还是配置中心 B。

这句话本身也存在一点歧义。如果前文再补充一句“服务 A 启动后没有本地配置”,那么“它”与服务 A 的联系通常会更强。上下文改变了,“它”在当前句子中的含义也会跟着改变。

“它”查看上下文并汇总相关信息
Encoder-style Self-Attention 示意图;连接强弱仅用于解释计算过程,不是某个实际模型的测量结果。

可以把 Self-Attention(自注意力)理解成:每个 token 在继续向下传递之前,都会从自己有权看到的位置收集信息。在 Encoder 中,这个范围可以是整段输入;在 Causal Decoder 中,它通常只能看到自己和之前的 token。

模型会比较“它”与其他 token 的关系,例如:

这些关系会被转换成不同的 Attention Weights(注意力权重)。关系越强,模型从对应位置取回的信息就越多。处理完成后,“它”不再只是一个孤立的词,而是一个融合了当前上下文的新表示。

这里的 Attention Weights 是某一层、某一个 Head 汇总 Value 时使用的系数,不能直接当成模型最终预测的因果解释。

句子中的其他 token 也会经历同样的过程。

Query、Key、Value(Q/K/V):同一个 token 的三种角色

为了完成“查找相关内容并取回信息”这件事,Transformer 会把每个 token 的表示分别映射成三个向量:Query、Key 和 Value。

一个 token 生成 Query、Key 和 Value
三个向量来自同一个 token,但在注意力计算中承担不同职责。

可以借用搜索系统来理解它们:

当模型更新“它”这个 token 时,会拿“它”的 Query 与当前可见范围内所有 token 的 Key 做比较。这个比较只负责回答“应该关注谁”。真正被汇总进新表示的,是相应 token 的 Value。

因此,Key 和 Value 虽然来自同一个 token,职责却不同:Key 用来匹配,Value 用来传递内容。

一次 Self-Attention 计算发生了什么

注意力计算可以拆成四步。

缩放点积注意力的四个步骤
先用 Q 和 K 判断相关性,最后才从 V 中取回内容。

第一步:计算相关性分数

当前 token 的 Query 与所有 Key 做点积:

QKᵀ

分数越高,说明两个向量在当前表示空间中越匹配。这里得到的还不是最终权重,只是一组未经归一化的分数。

第二步:缩放分数

分数会除以 √dₖ,其中 dₖ 是 Key 向量的维度。

向量维度增大时,点积的绝对值通常也会变大。如果直接送入 Softmax,分布容易过早饱和,梯度变得很小。缩放的作用,是把数值控制在更合适的范围。

第三步:得到 Attention Weights

Softmax 会把这些分数转换成一组大于零、总和为 1 的权重。它表达的是:当前 token 应该把多少注意力分配给序列中的每个位置。

第四步:汇总 Value

模型用注意力权重对所有 Value 做加权求和。权重高的位置贡献更多信息,权重低的位置贡献更少。

整个过程写成公式是:

Attention(Q, K, V) = softmax(QKᵀ / √dₖ)V

公式看起来包含矩阵运算,但它实际完成的事情很朴素:先判断谁更相关,再按相关程度取回信息。

Multi-Head Attention 到底是什么

这里的 Head(注意力头)不是另一个模型,也不是“多个大脑”。一个 Head,就是一套独立的 Q、K、V 投影参数,再加上一轮 Scaled Dot-Product Attention 计算。

多头注意力从不同表示空间观察同一序列
每个 Head 使用独立参数,从不同表示空间观察同一段输入。

Multi-Head Attention(多头注意力)会让同一份输入同时经过多组不同参数的 Head。每个 Head 在一个较小的表示空间中工作,因此可以从不同角度寻找关系。原始 Transformer Base 的 d_model 是 512,使用 8 个 Head,且每个 Head 的 dₖdᵥ 都是 64。

某些 Head 可能更关注指代,某些 Head 可能更关注局部搭配、语义联系或位置关系。这些职责不是人为指定的,而且并非每个 Head 都能对应一个清晰、可命名的语言功能。

所有 Head 的输出最后通过 Concat 拼接,再经过一次 Linear Projection,恢复成模型需要的输出表示。Multi-Head Attention 的核心不是简单地“重复计算”,而是让 Transformer 同时保留多种关系视角。

Transformer 为什么更容易建模长距离关系

RNN 按时间顺序处理序列。第 2 步依赖第 1 步,第 3 步依赖第 2 步。早期信息想传到很后面,必须经过一条较长的中间路径。

Fully-connected Self-Attention 允许任意两个彼此可见的位置直接建立联系。在单层中,信息不需要经过中间 token 逐步传递,最大路径长度可以视为 O(1)。对于 Causal Decoder,后面的 token 可以直接读取前面的 token,反方向则会被 Mask 阻止。

RNN 的串行路径与自注意力的直接连接
路径更短、单次前向更容易并行,是 Transformer 适合大规模训练的两个关键原因。

另一个差别是并行性。RNN 的当前步骤依赖上一步结果,很难同时计算整条序列。Self-Attention 的核心操作是矩阵乘法,可以一次计算大量 token 之间的关系,更适合 GPU。

这两点让 Transformer 更容易捕获长距离关系,也更适合大规模训练。

这里的并行性指训练或单次前向计算。自回归生成仍然需要先生成前一个 token,再生成下一个 token。

Self-Attention 也有代价

标准 Self-Attention 需要让每个 token 与其他所有 token 计算关系。序列长度为 n 时,注意力矩阵包含大约 个位置。上下文越长,计算量和显存开销增长得越快。

稀疏注意力和线性注意力通过减少连接或改变计算形式来缓解这个问题。FlashAttention 保留了精确注意力的计算结果和 O(n²) 级别的算术复杂度,主要通过减少 GPU 显存读写和中间数据存储来提升速度、降低显存占用。

不引入位置信息时,Self-Attention 无法仅凭输入表示区分 token 的排列顺序。原始 Transformer 把正弦余弦 Positional Encoding 加到输入 Embedding 上;RoPE 则旋转 Query 和 Key,把相对位置信息带入注意力分数。

把整条路径连起来

一段文本进入 Transformer 后,核心过程可以压缩成三句话:

  1. 每个 token 生成自己的 Query、Key 和 Value。
  2. Query 与所有 Key 比较,得到 Attention Weights。
  3. 使用这些权重汇总 Value,生成包含上下文的新表示。

Multi-Head Attention 会从多个表示空间并行执行这套过程;多层 Transformer 又会在上一层结果上继续更新。模型对上下文的理解,不是一次判断完成的,而是在一层层信息交换中逐渐形成的。

参考资料