AI Infra学习之旅-Transformer最核心的计算机制

这是“Transformer 原理深讲系列”的第 2 篇。
上一篇我们讲了两件事:为什么需要 Transformer,以及文本是如何通过 tokenization 和 embedding 进入神经网络的。
这一篇进入 Transformer 最核心的内部机制,集中回答三个问题:
为什么 embedding 还不够?Q、K、V 到底是什么?一次 Attention 到底在算什么?


一、为什么 embedding 还不够

上一篇的结尾,我们已经把一句文本变成了一个向量矩阵:

XRn×dmodelX \in \mathbb{R}^{n \times d_{\text{model}}}

其中:

  • (n) 是序列长度
  • (d_{\text{model}}) 是模型维度
  • 第 (i) 行 (x_i) 是第 (i) 个 token 的 embedding

例如句子:

狗 咬 人

可以被写成:

[x, x, x][x_{\text{狗}},\ x_{\text{咬}},\ x_{\text{人}}]

而句子:

人 咬 狗

则是:

[x, x, x][x_{\text{人}},\ x_{\text{咬}},\ x_{\text{狗}}]

看起来顺序已经不一样了,为什么还要额外做位置编码?

因为 embedding 只表达“这个 token 是什么”,并不表达“这个 token 在哪里”。

同一个 token,不管出现在第 1 个位置还是第 100 个位置,它的 embedding 向量本身通常是同一个。
换句话说:

  • “狗”在句首和句尾,本体 embedding 没变
  • “人”在主语位置和宾语位置,本体 embedding 也没变

如果模型只看到 token embedding,而没有显式位置信号,那么它更像是在处理一组“有内容的元素”,而不是一条“有严格顺序的序列”。


二、为什么 Transformer 的 Attention 天然不理解顺序

这一步是位置编码存在的根本原因。

RNN 为什么天然带顺序感?
因为它是一步一步递推的:

ht=f(xt,ht1)h_t = f(x_t, h_{t-1})

顺序直接写在计算路径里。

而 Transformer 不一样。
Transformer 的核心是 Self-Attention,它的基本形式是:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

这里本质上是在做:

  • 所有位置之间的两两匹配
  • 再做全局加权聚合

如果你不给它位置,它就很难天然知道:

  • 谁在前
  • 谁在后
  • 谁离谁更近

更准确地说:

Self-Attention 本身更擅长建模“内容之间的关系”,而不是“顺序本身”。

所以 Transformer 要处理语言序列,必须额外注入位置结构。


三、位置编码到底在解决什么问题

位置编码的目标,不是单纯给每个位置编号,而是把“顺序”转化为向量空间中的可计算信号。

它至少要让模型知道三件事:

  1. 当前 token 在第几个位置
  2. 两个位置之间谁在前、谁在后
  3. 两个位置之间相距多远,是否相邻

所以位置编码的本质可以概括为:

把原本不在 embedding 中的顺序信息,注入到输入表示里。


四、最基础的位置编码形式:和 embedding 相加

设第 (i) 个位置的 token embedding 是:

xiRdmodelx_i \in \mathbb{R}^{d_{\text{model}}}

给这个位置再定义一个同维度的位置向量:

piRdmodelp_i \in \mathbb{R}^{d_{\text{model}}}

那么模型实际使用的输入表示不是 (x_i),而是:

hi=xi+pih_i = x_i + p_i

整句话的表示就变成:

H=X+PH = X + P

其中:

  • (X \in \mathbb{R}^{n \times d_{\text{model}}})
  • (P \in \mathbb{R}^{n \times d_{\text{model}}})

这就是最经典、最重要的基本形式:

内容向量 + 位置向量


五、为什么通常是“相加”,而不是“拼接”

理论上,你也可以把 token embedding 和位置向量拼接:

[xi; pi][x_i;\ p_i]

但 Transformer 更常用相加:

hi=xi+pih_i = x_i + p_i

原因主要有三点。

1. 维度保持不变

如果拼接,维度会从 (d) 变成 (2d),后面所有层都要跟着改。
相加不会改变模型维度。

2. 内容和位置从一开始就融合

加法意味着模型第一层就看到“带位置信号的内容表示”,而不是两块分开的信息。

3. 工程实现更自然

后续所有线性映射、注意力、FFN 都可以直接复用统一维度,不需要额外处理拼接后的结构。

所以可以把这一步理解成:

  • embedding 告诉模型“是什么”
  • position vector 告诉模型“在哪里”
  • 相加后的输入表示同时携带两者

六、原始 Transformer 的位置编码:正弦余弦函数

原始论文 Attention Is All You Need 采用的是固定位置编码。
对位置 (pos) 和维度 (i),定义:

PE(pos,2i)=sin(pos100002i/dmodel)PE(pos, 2i)=\sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)

PE(pos,2i+1)=cos(pos100002i/dmodel)PE(pos, 2i+1)=\cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)

这意味着:

  • 偶数维使用正弦
  • 奇数维使用余弦
  • 不同维度采用不同频率

于是每个位置都会对应一个多频率波形组成的高维向量。


七、为什么正弦余弦位置编码有意义

如果只从表面看,这个公式会显得很“神秘”。
但它其实有很清晰的数学和直觉含义。

1. 每个位置都对应一个唯一的连续向量

位置 1、2、3、4…… 都会对应不同波形组合,所以模型可以区分它们。

2. 相邻位置之间变化平滑

由于三角函数是连续函数,相邻位置不会发生突兀跳变,这有利于模型学习邻近结构。

3. 不同频率提供多尺度位置感知

低频维度更适合表达粗粒度位置变化,
高频维度更适合表达细粒度差异。

4. 相对位移关系更容易被模型利用

由于三角函数具有明确的代数关系,位置 (pos+k) 和 (pos) 之间的关系不是完全无结构的随机差异,而是带规律的。

所以正弦余弦位置编码的本质不是“给位置编号”,而是:

用一组连续多频率基底,把离散位置嵌入到高维几何空间。


八、可学习位置编码和现代位置表示

除了固定正弦位置编码,很多模型也采用可学习的位置 embedding:

PRL×dmodelP \in \mathbb{R}^{L \times d_{\text{model}}}

其中 (L) 是最大长度。
每个位置对应一个可训练向量,然后同样与 token embedding 相加。

再后来,很多大模型进一步采用:

  • RoPE
  • ALiBi
  • 相对位置编码等

它们的目标都类似:
让 Attention 在处理长上下文时更自然地感知位置关系。

不过在原理层面,你现在先记住这一点就够了:

Transformer 必须显式引入位置信息,否则仅靠 token embedding 不足以稳定表达顺序。


九、有了位置编码之后,输入矩阵真正变成了什么

加上位置编码后,输入就不再只是 token embedding 的堆叠,而是:

HRn×dmodelH \in \mathbb{R}^{n \times d_{\text{model}}}

其中每一行:

hi=xi+pih_i = x_i + p_i

所以从这一刻开始,模型接收到的不是“纯内容表示”,而是:

内容 + 位置 的混合表示

后面的所有 Q/K/V 计算,都是从这个 (H) 出发的。

这点非常重要,因为它说明:

  • 位置编码不是后面补进去的
  • 而是从 Attention 一开始就已经渗透在输入里了

十、Q、K、V 到底是怎么从输入里来的

现在进入第二个核心问题:
Q、K、V 是怎么来的?

很多人初学时会把它们当成一种“神秘命名”,其实不是。
它们只是同一个输入表示 (H) 经过三套不同线性映射后的结果。

设:

HRn×dmodelH \in \mathbb{R}^{n \times d_{\text{model}}}

定义三组参数矩阵:

WQRdmodel×dkW^Q \in \mathbb{R}^{d_{\text{model}} \times d_k}

WKRdmodel×dkW^K \in \mathbb{R}^{d_{\text{model}} \times d_k}

WVRdmodel×dvW^V \in \mathbb{R}^{d_{\text{model}} \times d_v}

那么:

Q=HWQ,K=HWK,V=HWVQ = HW^Q,\quad K = HW^K,\quad V = HW^V

于是:

  • (Q \in \mathbb{R}^{n \times d_k})
  • (K \in \mathbb{R}^{n \times d_k})
  • (V \in \mathbb{R}^{n \times d_v})

所以你可以把 Q、K、V 理解成:

同一个输入表示,在三个不同功能子空间中的投影。


十一、为什么要拆成 Q、K、V 三份

Attention 之所以不直接拿输入向量自己和自己比,而是拆成 Q/K/V,根本原因是它要把两件事分开:

1. 匹配谁重要

这是关系判断问题。

2. 从谁那里拿什么内容

这是信息传递问题。

于是:

  • Query / Key 负责匹配
  • Value 负责内容承载

可以这样理解:

  • Query:我现在想找什么
  • Key:我这里适不适合被你关注
  • Value:如果你关注我,我真正提供什么内容

这个分工非常重要,因为它让“找谁”和“拿什么”分开了。


十二、一个单头 Attention 到底完整经历了什么

现在进入这一篇最核心的部分:
一次单头 Attention 到底在算什么。

标准公式是:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

下面一步步拆。


第 1 步:计算相关性分数 (QK^T)

设:

  • (Q \in \mathbb{R}^{n \times d_k})
  • (K \in \mathbb{R}^{n \times d_k})

那么:

QKTRn×nQK^T \in \mathbb{R}^{n \times n}

其中第 (i,j) 个元素是:

(qikj)(q_i \cdot k_j)

表示:

第 (i) 个位置的 Query 与第 (j) 个位置的 Key 的匹配程度。

这个矩阵本质上就是一张“谁该关注谁”的原始打分表。


第 2 步:为什么要除以 (\sqrt{d_k})

原始分数会随着维度变大而变大。
如果直接把很大的点积分数送入 softmax,softmax 会过于尖锐,导致:

  • 某些位置权重几乎全占满
  • 梯度不稳定
  • 训练困难

所以做缩放:

QKTdk\frac{QK^T}{\sqrt{d_k}}

作用是:

控制分数尺度,保持数值稳定。


第 3 步:softmax 到底在做什么

softmax 作用在 score matrix 的每一行:

A=softmax(QKTdk)A = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)

得到:

ARn×nA \in \mathbb{R}^{n \times n}

第 (i) 行的所有元素加起来等于 1。
它表示:

第 (i) 个位置把自己的注意力,如何分配给全序列的每个位置。

也就是说,softmax 的作用不是装饰,而是:

把原始相关性分数变成可解释的注意力权重分布。


第 4 步:为什么最后要乘 (V)

得到注意力权重矩阵 (A) 后,再做:

O=AVO = AV

其中:

  • (A \in \mathbb{R}^{n \times n})
  • (V \in \mathbb{R}^{n \times d_v})

所以:

ORn×dvO \in \mathbb{R}^{n \times d_v}

第 (i) 个输出向量可以写成:

oi=j=1nAijvjo_i = \sum_{j=1}^{n} A_{ij} v_j

这表示:

第 (i) 个位置会把所有位置的 value 按注意力权重加权求和,形成新的上下文化表示。

所以 Attention 的完整本质是:

  1. 先决定“谁值得看”
  2. 再把“值得看的内容”加权收回来

十三、Attention 从几何和直觉上到底意味着什么

如果只看公式,Attention 很容易显得冷冰冰。
但从几何和直觉上,它其实很自然。

从几何上看

  • Query 和 Key 的点积衡量方向对齐程度
  • 方向越一致,分数越高
  • 说明这个位置越值得关注

从直觉上看

Attention 不是“挑一个最重要的位置”,而是:

为当前 token 动态构造一张上下文加权视图。

也就是说,它是一个:

  • 数据依赖的
  • 全局可访问的
  • 基于相关性做内容聚合的机制

十四、为什么这一机制是 Transformer 的核心

因为它彻底改变了序列建模方式。

RNN 是:

  • 当前状态依赖上一步状态
  • 信息沿时间链条递推

Attention 则是:

  • 当前位置可以直接查看全局
  • 再按需要吸收相关内容

所以 Transformer 最关键的创新,不是“用了 Q/K/V 三个字母”,而是:

让每个位置可以通过可学习匹配,直接建立和全局所有位置的关系。

这也是为什么 Transformer 能够:

  • 更容易建模长距离依赖
  • 更适合并行计算
  • 更适合扩展成大模型

十五、本篇真正要记住的三条主线

第一条:位置编码

  • embedding 只表达“是什么”
  • Transformer 的 attention 本身不天然理解顺序
  • 所以必须显式注入位置信息
  • 最基本形式是:

hi=xi+pih_i = x_i + p_i

第二条:Q/K/V

  • 它们都来自同一个输入 (H)
  • 只是经过三套不同线性变换
  • Q/K 负责匹配,V 负责内容承载

第三条:一次 Attention

  • (QK^T) 计算相关性
  • 除以 (\sqrt{d_k}) 保证数值稳定
  • softmax 变成注意力权重
  • 再对 (V) 做加权求和
  • 得到新的上下文化表示

十六、用一句话压缩本篇

位置编码让 Transformer 真正具备顺序感;Q/K/V 则把输入表示拆成“匹配空间”和“内容空间”。一次 Attention 的本质,就是基于 Query 和 Key 的相关性,为每个位置从全局 Value 中动态聚合新的上下文化表示。


下一篇预告

下一篇主题是:

多头、Mask 与 FFN:Transformer 为什么不只是一个 Attention 公式

会重点讲清楚:

  • 为什么单头 attention 不够
  • Multi-Head Attention 到底“多”在哪里
  • 为什么 Decoder 必须有 causal mask
  • padding mask 和 causal mask 有什么区别
  • FFN 的数学形式是什么
  • 为什么 attention 后面还必须接 FFN