为什么 Attention 能干掉 RNN?
RNN 必须逐词传递信息,第 180 个词想看第 3 个词时信号已经衰减殆尽。Self-Attention 用一次矩阵乘法让任意两个词直接对话,这就是 Transformer 取代 RNN 的根本原因。
第 1 篇 / 共 1 篇
INFO
系列导读 本文是《从 LLM 到 Agent》系列的第 1 篇。
先说一个坐标系
如果你是前端工程师,大概率没追过 AI 的技术演进。这三十秒的背景能帮你定位"这篇在讲什么阶段的事"。
1990s-2012:规则和统计。机器翻译靠人工写规则、词频表查概率。效果勉强能用,但碰到稍微复杂的句子就崩。
2013:Word2Vec 让词变成了向量。Mikolov 在 Google 证明:把每个词映射成一组数字(向量),词和词之间的语义关系会自然浮现——"国王 - 男 + 女 ≈ 女王"。从此 NLP 进入"用数字表示语义"的时代,进阶篇第 2 篇 Embedding 就讲这个。
2014-2017:LSTM 统治序列建模。RNN 的改良版 LSTM 成为所有序列任务的默认方案。2016 年底 Google 翻译突然变好了——背后就是 8 层 LSTM + Attention 的 GNMT 系统。那时候所有人都觉得 LSTM 就是终局。
2017:Transformer 登场,LSTM 退位。Vaswani 等人发表 Attention Is All You Need,完全抛弃循环结构,用纯注意力机制处理序列。训练速度快了一个数量级,长距离依赖不再是问题。之后的 GPT、BERT、ChatGPT 全部基于 Transformer。
这篇文章就从 LSTM 的问题开始——理解它为什么失败,你才能理解 Transformer 为什么成功。
RNN 的致命缺陷
一段 200 词的文本,第 3 个词是"John",第 180 个词是"he"。人类读到"he"时,瞬间知道它指的是"John"。
RNN(循环神经网络)做不到 1。
RNN 的结构要求信息逐步传递——处理完第 1 个词,把隐藏状态传给第 2 个词,再传给第 3 个词……一直到第 180 个词。"John"的信息要经过 177 步传递才能到达"he"。每传一步,信号就衰减一点。
这不是 RNN"不够聪明",而是结构性的物理限制。LSTM 通过门控机制缓解了衰减,但没有根治——信息传递的路径长度仍然是 O(n),和句子长度成正比。句子越长,早期词的信号越弱。
除了信号衰减,还有一个同样致命的问题:无法并行。第 n 步必须等第 n−1 步完成才能开始,100 个词就是 100 步串行计算。GPU 有数千个并行计算核心,但 RNN 只能用上一个。
2017 年,Vaswani 等人提出了一个激进的想法 2:把 RNN 的循环结构整个扔掉,只用注意力。论文标题即宣言——Attention Is All You Need。
先体验:注意力在做什么
在讲公式之前,先看看注意力的效果。
下面的 Demo 模拟了 Self-Attention 的工作方式。点击任意一个词,观察它在"关注"谁——弧线越粗,注意力权重越大:
NOTE
教学简化说明 上面的注意力权重是为教学设计的模拟数据。实际模型的注意力分布更分散且多层叠加。但核心机制相同:每个 token 通过 Q/K 相似度计算决定"关注谁多一些"。
关键观察:点击"它",48% 的注意力指向了"苹果"——模型通过注意力权重"理解"了代词指代关系。而且这是一步完成的——"它"直接看到了"苹果",不需要经过中间的"很"。
RNN 里,"它"要理解"苹果"必须通过隐藏状态逐步传递。Self-Attention 里,任意两个词之间的距离变成了 O(1)——常数时间,不随句子长度增长。
这就是 Attention 能干掉 RNN 的核心原因。现在来看它是怎么做到的。
公式拆解:三步理解 Self-Attention
Self-Attention 的完整公式是:
Attention(Q,K,V)=softmax(dkQKT)V自注意力机制一次看这个公式会懵。拆成三步,每步解决一个问题。
第一步:QKT——"这两个词有多相关?"
每个 token 先被转换成一个固定长度的数字向量(叫 embedding),作为模型可以计算的数学表示。然后这个 embedding 被线性变换成三个向量:
- Query(查询):"我在寻找什么信息?"
- Key(键):"我能提供什么信息?"
- Value(值):"我的实际内容是什么"
QKT 计算的是 Query 和 Key 的点积——两个向量方向越相似,点积越大。当"它"的 Query 和"苹果"的 Key 方向一致时,得分就高,意味着"它"应该关注"苹果"。
Q、K、V 是同一份数据通过三个不同的权重矩阵投影出来的。为什么要三个角色?因为"我在找什么"和"我能提供什么"不一样。一个词作为查询者和作为被查询者时,关注的语义维度不同。
到这里我们解决了:任意两个词之间的相关性打分。O(1) 直接连接,不需要逐步传递。
第二步:除以 dk——防止 softmax 饱和
dk 是 Key 向量的维度。当维度很高时(比如 64 维),点积的数值会变得很大。
为什么这是个问题?因为下一步要过 softmax。softmax 会把最大值推向 1、其余推向 0——如果输入值太大,softmax 的输出会接近 one-hot 分布,梯度几乎为零,训练卡死。
除以 dk 把点积的量级拉回合理范围。这不是调参技巧,是数学必要——dk 维向量的点积期望方差为 dk,除以 dk 后方差归一化为 1。
到这里我们解决了:数值稳定性。保证 softmax 输出的梯度健康,训练能正常进行。
第三步:乘以 V——"拿多少信息"
softmax 把原始分数转换成 0-1 之间的概率分布(所有权重加起来 = 1)。这些权重决定了每个词从其他词那里"拿多少信息"。
最后乘以 V(Value 矩阵),就是用这些权重对所有词的实际内容做加权求和。"它"的新表示 = 48% × 苹果的内容 + 12% × 我的内容 + 8% × 吃了的内容 + ……
到这里我们解决了:信息聚合。每个词的输出不再只是它自己,而是融合了全句上下文信息的新表示。
三步合起来:计算相关性(QKT)→ 稳定数值(/dk)→ 聚合信息(×V)。一次矩阵运算,所有词同时完成,完全并行。
多头注意力:一个头不够
单头注意力只能学到一种关注模式。但语言中的关系是多维的——同一个句子里同时存在语法关系(主谓宾)、指代关系(代词→名词)、位置关系(相邻词)。
解法:拆分并行。
多头注意力(Multi-Head Attention)把 Q/K/V 各拆成 h 份(原论文用 8 个头),每份独立做注意力计算,最后 concat 起来再做一次线性投影:
MultiHead(Q,K,V)=Concat(head1,...,headh)WO多头注意力精妙之处:拆成 h 个头后,每个头处理的维度变成 d/h,总计算量和单头几乎一样。8 个头用相同的算力,获得了 8 个不同的关注视角。
实际训练出来的注意力头确实学到了不同的模式。后续的 BERTology 系列研究 3 发现:某些头专注于语法依赖(主语→谓语),某些头捕捉共指关系(代词→先行词),某些头关注相邻词的局部上下文。模型自动学会了这种分工,不需要人为指定。
位置编码:补上顺序信息
到目前为止,Self-Attention 有一个致命缺陷:它不关心词的顺序。
把输入 token 打乱,注意力分数不会变。"狗咬人"和"人咬狗"在 Self-Attention 看来完全等价。
原因:RNN 按顺序处理,天然感知位置。Self-Attention 做的是集合运算(所有词两两比较),没有"先后"的概念。
解法:给每个位置一个独特的向量,加到 token embedding 上。原论文用正弦和余弦函数的组合生成位置编码——不同频率的三角函数让每个位置有唯一的"指纹"。后来旋转位置编码 RoPE 4 成为主流方案,被 LLaMA 等现代模型广泛采用。
加了位置编码后,"狗咬人"中"狗"的表示 = 狗的语义向量 + 位置 1 的编码,"人咬狗"中"狗"的表示 = 狗的语义向量 + 位置 3 的编码。两者不再相同,Self-Attention 就能区分语序了。
完整的 Transformer Block
前面的模块组合起来,就是一个 Transformer Block:
每个 Block 包含两个子层,各自带残差连接和 LayerNorm:
注意力子层:Multi-Head Attention → Add & LayerNorm。负责 token 之间的信息交换。
FFN 子层:两层全连接网络(中间 GELU 激活)→ Add & LayerNorm。负责每个 token 独立的信息加工——注意力告诉 token"你应该关注什么",FFN 告诉 token"拿到这些信息后怎么处理"。
残差连接(output=f(x)+x)保证深层网络的梯度能传回去 5。原论文堆了 6 层,GPT-3 堆了 96 层——没有残差,梯度传不过 10 层。
模型就是把这个 Block 重复堆叠 N 次。每一层的注意力模式不同:浅层关注局部语法,深层捕捉全局语义。
亲手验证
打开上面的注意力可视化 Demo,做以下实验:
-
验证指代消解:点击"它",预测注意力最高的词应该是"苹果"(因为"它"指代"苹果")。验证你的预测。然后思考:如果把句子改成"我吃了一个苹果,它很贵"——"它"现在可能指"苹果"也可能指吃苹果这件事。模型的注意力分布会如何变化?
-
验证语法关系:点击"一个",注意力应该集中在"苹果"上(量词修饰名词)。点击"很",注意力应该指向"甜"(副词修饰形容词)。这些语法关系不是硬编码的规则,而是从数据中学出来的模式。
-
理解 RNN 做不到的事:在这个 Demo 里,"甜"可以一步看到"苹果"(22%)。如果是 RNN,"甜"的信息要经过"很"→"它"→"苹果"三步传递才能建立这个联系。每多一步,信号就弱一点。当句子更长——比如"苹果"在第 3 个位置,"甜"在第 180 个位置——RNN 的信号几乎衰减为零,而 Self-Attention 仍然是一步到位。
如果你能向别人解释:Self-Attention 让任意两个词直接对话(O(1) 距离),同时完全并行化(矩阵乘法),这两点解决了 RNN 的长距离遗忘和串行瓶颈——那你理解了 Transformer 的核心设计动机。
参考文献
- Long Short-Term Memory提出门控机制缓解梯度消失,Transformer 之前序列建模的主力架构。
- Attention Is All You Need提出 Transformer 架构,8 位作者后来分散到不同方向——Gomez 联合创办 Cohere,Shazeer 联合创办 Character.AI。
- "What Does BERT Look At? An Analysis of BERT's Attention"系统分析 BERT 各注意力头的功能分工——语法依赖、共指关系、局部上下文等模式。
- "RoFormer: Enhanced Transformer with Rotary Position Embedding"提出旋转位置编码 RoPE,被 LLaMA、GPT-NeoX 等主流大模型采用。
- Deep Residual Learning for Image Recognition残差连接的原始出处,来自 CV 领域但直接影响了 Transformer 的设计。