2017 年之前,处理序列靠 RNN/LSTM——像读句子一样一个词一个词往后读,把"读到现在的记忆"传给下一步。两个致命问题:
| 问题 | 后果 |
|---|---|
| 必须顺序计算 | 第 100 个词要等前 99 个算完才能算 → 没法并行,GPU 喂不饱,训练慢。 |
| 长距离依赖会衰减 | 句首信息传到句尾要经过几十步,像传话游戏,越传越糊。 |
论文的回答简单粗暴:把循环整个删掉,只留 attention。标题就是这个意思——注意力,足够了。
核心机制叫 self-attention。给每个 token,先从它的向量算出三个角色向量:
| 角色 | 直觉(用「查资料」打比方) |
|---|---|
| Query(查询) | 我想找什么?——我带着一个「问题」去问全场。 |
| Key(键) | 每个 token 挂出的「标签」——表明"我这有什么信息"。 |
| Value(值) | 每个 token 真正要交出去的「内容」。 |
然后三步算出某个 token 的新表示:
1. 我的 Query 去和【所有 token 的 Key】做点积 → 一串「相关度分数」
2. 分数 ÷ √d_k,再过 softmax → 一组加起来=1 的「注意力权重」
3. 用这组权重,对【所有 token 的 Value】加权求和 → 我的新表示
一句话:注意力 = 带着权重,从最相关的那些 token 那里取信息。 权重不是写死的,是 token 之间用 Q·K 当场算出来的——这就是它比"传话"强的地方:句首和句尾一步直连,不衰减。
① 为什么要 ÷√d_k? 向量维度大时点积数值会很大,softmax 会被推到"几乎全 1 / 全 0"的饱和区,梯度消失。除以 √d_k 把它拉回温和区间。
② Multi-head(多头): 不止一组 Q/K/V,而是并行好几组(base 模型 8 组)。每组关注不同侧面——有的盯语法、有的盯指代。最后拼起来。
③ Positional Encoding(位置编码): attention 本身不分先后(打乱词序它算出来一样)。所以要额外给每个位置注入一个"位置信号",模型才知道词序。
下面这句话里有个指代:"它"到底指谁?点不同的 query 词,看它的注意力权重落在哪些词上(示意权重,帮你建立直觉)。
| 维度 | RNN / LSTM | Transformer(self-attention) |
|---|---|---|
| 并行性 | 不能,必须顺序 | 整句一次并行 |
| 任意两词的连接距离 | O(n) 步,会衰减 | O(1) 步,直连 |
| 每层计算量 | O(n·d) | O(n²·d) ← 序列越长越贵的根源 |
| 词序信息 | 天然自带 | 要额外加位置编码 |
上面那张表有点干。把 RNN 和 Transformer 各还原成一个画面,区别就立起来了——而且表里每一条,都是画面的直接后果。
| RNN / LSTM = 蒙眼接力 | Transformer = 圆桌会议 | |
|---|---|---|
| 画面 | 你蒙着眼,别人一个词一个词念给你听,你边听边在唯一的一页笔记上更新(这页笔记 = 隐状态 h)。 | 每个词变成一个人,全坐圆桌、同时在场;谁想了解谁,直接转头问,一步到位。 |
| 所以 并行 |
第 100 个词得等前 99 个听完 → 必须排队,GPU 喂不饱。 | 大家同时开问 → 整句并行,GPU 喂得饱。 |
| 所以 长距离 |
第 1 个词的信息在笔记上被覆盖、稀释 99 次 → 越传越糊。 | 第 100 个人转头就问第 1 个人,不过中间 99 人 → 不衰减。 |
| 所以 成本 |
每词只更新一次笔记 → O(n),便宜。 | 人人互相握一次手 → O(n²),人多就贵。 |
注意:Transformer 不是全面碾压。它 O(n²) 更贵,还天生不知道词序——圆桌上大家同时在场、没有先来后到,所以才要额外发个「座位号」(positional encoding)。这两点上 RNN 反而天然占优。
正因为 RNN 推理是 O(n) 便宜、Transformer 是 O(n²) 烧钱,这两年有了「RNN 复兴」——Mamba、RWKV 这类架构想把线性成本捡回来,专攻超长序列。判断这类「线性注意力 / 状态空间模型」的卖点,核心就一句:要 RNN 的便宜,又不想丢 Transformer 的并行。
| 你工作里的东西 | 其实就是这篇论文的什么 |
|---|---|
| 你用的所有模型底座 | 就是这个 self-attention block 堆叠几十层(GPT 是它的 decoder 部分)。 |
| KV cache(实时语音等低延迟场景) | 生成时把已算过的 Key/Value 缓存下来,新 token 不必重算——直接来自这里的 K、V。 |
| 长上下文为什么又慢又贵 | 那个 O(n²):上下文翻倍,注意力计算量翻四倍。FlashAttention(P13)就是来治它的。 |
| 模型"能同时顾及多个方面" | multi-head:多组注意力并行,各看各的侧面。 |
课上被问到、值得单独记一笔的点。点开看答。
不是轮流当 Q(那就退回 RNN 了),是所有 token 同时各生成自己的 Q/K/V、并行各查各的。n 个 token 就有 n 个 Q、K、V,摞成矩阵一次算完:
Attention(Q,K,V) = softmax( Q·Kᵀ / √d_k ) · V
Q·Kᵀ 是一张 n×n 注意力分数矩阵(第 i 行第 j 列 = token i 对 token j 的相关度);每一行做 softmax = 该 token「把注意力分给谁、各多少」,再加权求和对应的 V 得到它的新表示。单 token 那五步(Q·K → ÷√d_k → softmax → 加权 V),只是把「向量」换成「矩阵」一次并行做完。
🔮 那张 n×n 矩阵就是本课「圆桌握手」的真身、也是 O(n²) 的出处——你问「多个 Q 怎么办」,答案本身就解释了长上下文为什么又慢又贵。生成时新 token 只给矩阵加最后一行,旧 K/V 缓存不重算,就是 KV cache。
一句话:把「一串大小不一的分数」换算成「一组加起来正好 = 1 的百分比」。
小猫 3.0, 因为 0.2, 累了 1.0 … ← 原始分数,可大可小、可正可负
↓ softmax
小猫 0.70, 因为 0.05, 累了 0.15 … ← 变成百分比,加起来 = 1
两步:① 每个分数取 e^x(指数 → 都变正数、且放大差距);② 各自除以总和(归一化到「和 = 1」)。
attention 为什么非要它:下一步「加权 V」做的是加权平均,权重必须是「加起来 = 1 的比例」才行。Q·K 出来的是任意分数(可能 17、-3),直接加权尺度就乱了——softmax 是把「原始好感分」规整成「合法权重」的那道工序。
💡 名字直觉:soft + max = 软性取最大。硬 max 只给最高分 100%;softmax 让高分拿大头、低分拿一点——正是注意力该有的样子。(它和最后出 token 时是同一个运算,见 GLOSSARY.md。)
先澄清一个易混点:新表示 ≠ V。V 是原料,新表示是成品。每个 token 有自己的 V(它的「货」);某个 token 的新表示是把全场所有 V 按权重 α 混合出来的(Σ α·V)。谁权重高,成品里谁的货占大头。
句子「小猫 … 它 …」里的「它」,走完整五步:
Q·K);所以同一个「它」,在不同句子里会吸收不同的词,得到不同的新表示——这就是 self-attention 的终极目的:让每个词的表示,按上下文动态吸收它该吸收的信息。
先看图解打直觉:Jay Alammar — The Illustrated Transformer。
再读原典:Attention Is All You Need (arXiv:1706.03762)—— 重点读第 3.2 节(Scaled Dot-Product & Multi-Head Attention)。
想看它怎么变成可跑的代码:Karpathy — Let's build GPT。
参考:
Vaswani et al., Attention Is All You Need, NeurIPS 2017;Alammar, The Illustrated Transformer;Karpathy, Let's build GPT.