重新学习 Transformer:这次我终于把它为什么有效想明白了

最近又开始重新学习 Transformer。第一次看这套东西的时候,更多是在记结论:Self-Attention、Multi-Head、Positional Encoding、Encoder-Decoder……名词都知道,但总觉得像在背模板。现在再回头看,才慢慢觉得自己抓到了它真正厉害的地方:它不是单纯把 RNN 换掉,而是重新定义了“序列信息该怎么流动”。

这篇就不照着论文逐段翻译了,主要记录一下我这次重新学习后,对 Transformer 的几个核心理解。

Transformer 到底解决了什么问题

如果把 NLP 任务看成“让模型理解一段有顺序的 token”,RNN 的思路是按时间一步一步往前走。第 10 个词的表示,要通过前 9 步一层一层传过来。

这有两个老问题:

  1. 串行计算,训练慢
  2. 长距离依赖难学

比如一句话里,前面提到的人名,后面隔了二三十个 token 才再次出现,RNN 理论上能记住,实际上梯度一路传下来很容易衰减。LSTM/GRU 是缓解了这个问题,但没有根治。

Transformer 的关键转变在于:不要让信息只沿着时间顺序传递,而是让每个 token 直接看见所有 token。

这个想法听起来简单,但它直接把“序列建模”的通信方式改了。

Self-Attention 的直觉:每个词都在问,谁跟我最相关

Self-Attention 最容易被公式吓到,但如果只看直觉,其实很自然。

假设句子是:

The animal didn’t cross the street because it was too tired.

当模型处理 it 的时候,真正重要的问题是:it 指的是谁?

Self-Attention 做的事情,本质上就是让 it 去看整句话,然后给其他 token 打分:

  • animal 的相关性高
  • street 的相关性低
  • tired 也有关系,但角色不同

于是 it 的新表示,不再只是它自己的 embedding,而是整句话中与它最相关信息的加权汇总

这就是 Attention 的核心:
表示一个 token,不只靠它自己,还要看上下文里谁对它最重要。

Q、K、V 不是什么玄学,只是三种不同视角

很多人第一次看 Q/K/V 会卡住,觉得这三个矩阵太抽象。现在我更愿意把它理解成下面三件事:

  • Query:我现在在找什么
  • Key:我这里有什么信息,值不值得你关注
  • Value:如果你真的关注我,你最终拿走的内容是什么

还是拿 it 举例:

  • it 发出一个 Query:我想知道我指代的是谁
  • 其他 token 各自提供自己的 Key:我是 animal,我是 street,我是 tired
  • Query 和所有 Key 做匹配,得到注意力权重
  • 再用这个权重对所有 Value 做加权求和

最后输出的新表示就是:“在当前上下文下,这个 token 应该带着哪些信息往后传”。

所以 Q/K/V 并不是三个神秘对象,而是把“查找”和“传值”分开建模。这个拆分很关键,因为一个 token 被关注的原因,不一定等于它最终输出给别人的内容。

为什么要除以 sqrt(d_k)

论文里有个看起来很工程的小细节:
注意力分数要除以 sqrt(d_k)

这个东西的意义其实很朴素:维度一大,点积的数值波动就会变大,送进 softmax 后容易特别尖锐,导致梯度不稳定。除以 sqrt(d_k) 相当于把分数拉回一个更适合 softmax 的区间。

它不改变 Attention 的思想,但让训练更稳。很多深度学习里真正重要的创新,往往就是这种“看似细节,实则决定是否能训起来”的设计。

Multi-Head Attention:不是看得更多,而是看得更“分工明确”

单头 Attention 当然也能工作,但 Multi-Head 的意义在于:让模型从不同子空间并行观察同一段序列。

一个 head 可能更关注:

  • 语法依赖
  • 指代关系
  • 位置邻近性
  • 长距离语义关联

它们最后再拼起来,形成更丰富的表示。

我现在觉得,多头机制最有价值的地方不是“多个头更强”这么简单,而是它在结构上鼓励模型形成一种可并行的角色分工。你不用指望一个单一表示同时把所有关系都压进去,而是给它多个观察窗口。

为什么没有 RNN 也能知道顺序

Transformer 最大的“反直觉”问题之一是:
如果没有按顺序处理,模型怎么知道谁在前谁在后?

答案就是 Positional Encoding

最早论文里用的是正弦/余弦位置编码。第一次看我只记住了公式,第二次再看,才明白它的设计思路很漂亮:

  1. 每个位置都有唯一表示
  2. 不同位置之间的相对距离可以通过线性方式表达
  3. 可以自然泛化到更长序列

当然,后面大家也发展出了 learned positional embedding、relative position、RoPE 等各种更实用的方案。但核心问题始终没变:
Attention 本身不带顺序感,所以必须额外把位置信息注入进去。

Encoder 和 Decoder,本质上是两种不同的信息流

一开始我老是把 Encoder-Decoder 图背下来,却没真正理解它们的区别。

现在看就清楚很多了:

  • Encoder:让输入序列内部充分交互,产出上下文化表示
  • Decoder:一边看已经生成的内容,一边从 Encoder 的输出里取信息,逐步生成目标序列

Decoder 里最关键的是 Masked Self-Attention
它保证模型在生成第 t 个 token 时,只能看见前面的 token,不能偷看未来答案。

所以 Encoder 的 Attention 是“全局双向”的,Decoder 的自注意力是“因果单向”的。这个区别后来也直接分化成了今天常见的几类模型:

  • BERT 系:偏 Encoder,适合理解任务
  • GPT 系:偏 Decoder,适合生成任务
  • T5 / 原始 Transformer 翻译模型:完整 Encoder-Decoder

Feed Forward Network 没有 Attention 那么出名,但它同样重要

Transformer block 里除了 Attention,还有一层经常被一笔带过的 FFN。

以前我会下意识把它当成“配角”,现在反而觉得它很像每个 token 的局部非线性变换器。Attention 负责在 token 之间交换信息,FFN 负责对单个 token 的表示做进一步加工。

可以粗暴理解成:

  • Attention:决定我该从别人那里拿什么
  • FFN:拿到之后,我怎么重新整理成更有用的特征

如果说 Attention 是通信层,FFN 更像计算层。两者交替堆叠,才构成了 Transformer 的表达能力。

我这次重新学习后最大的感受:Transformer 强在“路径短”

现在回头看,Transformer 最本质的优势可能不是“更大”或者“更并行”,而是:

任意两个 token 之间的信息传递路径变短了。

在 RNN 里,前后两个远距离 token 的交互,需要跨很多时间步。
在 Transformer 里,一层 Attention 就能直接连上。

这带来几个连锁反应:

  • 更容易学长距离依赖
  • 更适合 GPU 并行
  • 更容易随着数据和参数规模扩展

也正因为如此,Transformer 后来不只统一了 NLP,还扩散到了视觉、多模态、语音、蛋白质结构等各种领域。它不只是一个“翻译模型”,而是一种足够通用的信息交互框架。

但它也不是没有代价

重新学的时候,另一个更清楚的感受是:Transformer 的成功并不意味着它完美。

最典型的问题就是 Attention 的计算和显存开销对序列长度是二次增长的。序列一长,成本就非常夸张。这也是为什么后来会有 FlashAttention、Linear Attention、Mamba、MoE、KV Cache 等一整套优化和替代路线。

所以今天学 Transformer,已经不能只停在 2017 年那篇论文本身了。更重要的是理解:

  • 它的基本假设是什么
  • 它在哪些地方真的比旧架构好
  • 它的瓶颈又是怎么催生后续一大批改进工作的

结语

这次重新学习 Transformer,对我来说最大的变化不是“终于记住公式”了,而是开始把它看成一个很清晰的系统设计:

  • 用 Attention 解决 token 间的信息路由
  • 用位置编码补上顺序信息
  • 用多头机制做并行分工
  • 用 FFN 做局部特征变换
  • 用残差、LayerNorm 和堆叠把整个系统训练起来

第一次学的时候,我看到的是模块;这次再看,才慢慢看到它背后的设计逻辑。

如果后面继续往下啃,我下一步大概率会去重点补三块:

  1. RoPE 和相对位置编码到底为什么更适合大模型
  2. KV Cache 从推理角度到底节省了什么
  3. FlashAttention 是怎么把“理论一样”的 Attention 做到实际快很多的

学模型这件事,很多时候不是第一次看懂,而是隔一段时间再回来,突然发现自己终于知道该看哪里了。