重新学习 Transformer:这次我终于把它为什么有效想明白了
最近又开始重新学习 Transformer。第一次看这套东西的时候,更多是在记结论:Self-Attention、Multi-Head、Positional Encoding、Encoder-Decoder……名词都知道,但总觉得像在背模板。现在再回头看,才慢慢觉得自己抓到了它真正厉害的地方:它不是单纯把 RNN 换掉,而是重新定义了“序列信息该怎么流动”。
这篇就不照着论文逐段翻译了,主要记录一下我这次重新学习后,对 Transformer 的几个核心理解。
Transformer 到底解决了什么问题
如果把 NLP 任务看成“让模型理解一段有顺序的 token”,RNN 的思路是按时间一步一步往前走。第 10 个词的表示,要通过前 9 步一层一层传过来。
这有两个老问题:
- 串行计算,训练慢
- 长距离依赖难学
比如一句话里,前面提到的人名,后面隔了二三十个 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。
最早论文里用的是正弦/余弦位置编码。第一次看我只记住了公式,第二次再看,才明白它的设计思路很漂亮:
- 每个位置都有唯一表示
- 不同位置之间的相对距离可以通过线性方式表达
- 可以自然泛化到更长序列
当然,后面大家也发展出了 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 和堆叠把整个系统训练起来
第一次学的时候,我看到的是模块;这次再看,才慢慢看到它背后的设计逻辑。
如果后面继续往下啃,我下一步大概率会去重点补三块:
- RoPE 和相对位置编码到底为什么更适合大模型
- KV Cache 从推理角度到底节省了什么
- FlashAttention 是怎么把“理论一样”的 Attention 做到实际快很多的
学模型这件事,很多时候不是第一次看懂,而是隔一段时间再回来,突然发现自己终于知道该看哪里了。