Jerry's Blog

Back

返回专题总目录

[01] 02 > 03 > 04 > 05 > 06 | 07 > 08 > 09 > 10 > 11 > 12

“Attention 不是让模型凭空变聪明,而是让模型在需要的时候,能去对的位置取对的信息。“


问题:序列建模的核心矛盾#

如果没有 Attention,绝大多数序列模型(RNN、LSTM、GRU、甚至早期 CNN)都采用同一种思路:

  1. 读取:从头到尾扫描整个输入序列。
  2. 压缩:把所有信息塞进一个固定维度的内部表示。
  3. 输出:基于这个表示生成目标序列。

这套方案在短句子上勉强能用。但一旦句子变长,就会暴露三个核心问题:

问题直觉描述数学根源
长距离依赖前面很早出现的信息,到后面容易被冲淡梯度消失 / 信息衰减
固定长度瓶颈不管输入多长,都被硬塞进同样大小的向量cRd\mathbf{c} \in \mathbb{R}^ddd 固定
静态读取所有输出步骤共用同一个压缩结果p(yty<t,c)p(y_t \mid y_{<t}, \mathbf{c})c\mathbf{c} 不随 tt 变化

Attention 的出现,就是为了同时解决这三个问题。


从 Encoder-Decoder 说起#

在经典的 Seq2Seq 架构(Sutskever et al., 2014)中,最容易出问题的一步就是中间的”瓶颈”:

交互演示:固定向量瓶颈
拖动滑块改变输入长度,观察信息密度变化

你可以把这个固定向量 c\mathbf{c} 理解成一个小背包:

  • 输入很短时,背包还能装下。
  • 输入一长,信息就开始挤压。
  • 真到生成输出时,模型只能翻这个背包,不能再回去看原文。

用数学语言来说,Encoder 把整个输入序列 (x1,x2,,xT)(x_1, x_2, \ldots, x_T) 编码成一个固定向量:

c=fenc(x1,x2,,xT)Rd\mathbf{c} = f_{\text{enc}}(x_1, x_2, \ldots, x_T) \in \mathbb{R}^d

Decoder 在每一步生成时都只能依赖这同一个向量:

p(yty1,,yt1,c)p(y_t \mid y_1, \ldots, y_{t-1}, \mathbf{c})

无论 T=5T = 5 还是 T=500T = 500c\mathbf{c} 的维度 dd 始终不变。这就是信息论意义上的瓶颈


经验证据:翻译质量随句子变长急剧下降#

Cho et al. (2014) 和 Bahdanau et al. (2015) 都观测到同一个现象:无 Attention 的 Seq2Seq 模型,BLEU 分数会随着源句子长度的增加而迅速下降。 加入 Attention 后,长句翻译质量显著恢复。

交互图表:BLEU 分数 vs 句子长度
基于 Bahdanau et al. (2015) 论文数据趋势复现。悬停查看具体数值。

这不是巧合。固定向量 c\mathbf{c} 的容量不会随输入长度增长——短句时它够用,长句时信息必然丢失。Attention 通过让 Decoder 在每一步直接回看 Encoder 的所有位置,从根本上绕过了这个瓶颈。


一个具体场景:翻译为什么会难#

假设输入句子是:

那位在加州工作了十年、后来搬到纽约创业、最近又回到上海的工程师,昨天终于发布了自己的新产品。

如果模型要把它翻成英文,不同的输出位置需要关注输入中的不同部分:

交互演示:翻译对齐
点击英文词,看它应该关注哪些中文词
← 点击上面的英文词试试

旧方案的问题在于:它会先把整句话压缩成一个统一的 c\mathbf{c},到真正生成 CaliforniaNew Yorkreleased 这些词时,模型没法说”这一步我想重点看输入的哪一段”。

而 Attention 的思路恰好相反——每一步输出都可以重新决定:我现在最该看哪里。


RNN 在长距离依赖上为什么会吃力#

信息传递路径:传话游戏#

RNN 的信息流动方式是链式传递

ht=f(Whht1+Wxxt+b)\mathbf{h}_t = f(\mathbf{W}_h \mathbf{h}_{t-1} + \mathbf{W}_x \mathbf{x}_t + \mathbf{b})

tt 步想用到第 11 步的信息,要经过 t1t - 1 次状态传递。

交互演示:RNN 信息传递衰减
点击「播放」观察信息如何在链式传递中逐步衰减
信号从 x₁ 出发,观察它在传递中如何衰减

这会带来三个核心问题:

1. 路径太长 → 梯度消失#

越早的信息,要经过越多步才能影响当前输出。数学上,信息的传递和梯度的反向传播都涉及矩阵连乘:

hth1=k=2thkhk1\frac{\partial \mathbf{h}_t}{\partial \mathbf{h}_1} = \prod_{k=2}^{t} \frac{\partial \mathbf{h}_k}{\partial \mathbf{h}_{k-1}}

tt 很大时,如果每一步的偏导数(即 Jacobian 矩阵)的谱范数小于 1:

hkhk1<1\left\| \frac{\partial \mathbf{h}_k}{\partial \mathbf{h}_{k-1}} \right\| < 1

那么连乘结果会指数衰减,导致梯度消失。模型在训练时根本学不到远距离依赖。反过来,如果谱范数大于 1,梯度会指数爆炸。

直觉:你可以把它理解成”传话游戏”——一句话中间只传两三个人,失真还不明显;传二三十个人,最后的内容就很难保证不变形。

2. 隐藏状态负担过重#

RNN 的隐藏状态 htRd\mathbf{h}_t \in \mathbb{R}^d 要同时承担:

  • 记忆存储:保留之前所有输入的关键信息
  • 当前处理:编码当前时间步的输入
  • 未来服务:为后续预测提供上下文

一个 dd 维向量同时做”存储器 + 压缩器 + 决策依据”,句子一长负担就会明显加重。

3. 早期信息的重要性不稳定#

有些信息刚出现时看起来不重要,但到后面突然变得关键。比如:

主语在句首出现 → 句子中间是各种修饰 → 谓语在句末出现

此时主语(句首)对谓语(句末)至关重要,但 RNN 很难保证这个信息能被稳定保留。

补充:LSTM / GRU 部分缓解了梯度问题,但没有解决瓶颈#

LSTM 通过门控机制(遗忘门、输入门、输出门)让信息可以选择性地”直通”多个时间步,大幅缓解了梯度消失:

ct=ftct1+itc~t\mathbf{c}_t = \mathbf{f}_t \odot \mathbf{c}_{t-1} + \mathbf{i}_t \odot \tilde{\mathbf{c}}_t

当遗忘门 ft1\mathbf{f}_t \approx 1 时,旧记忆几乎无损传递。GRU 是类似的简化版。

但是,LSTM/GRU 不能解决固定长度瓶颈——最终仍然是把整个序列压进一个 hT\mathbf{h}_T。Attention 解决的是更根本的问题:不是”怎么更好地记忆”,而是”怎么更灵活地读取”。


CNN 也不能从根上解决问题#

CNN 处理序列时比 RNN 更并行,但也有天然限制。

一个卷积核的感受野(receptive field)是有限的。如果窗口大小为 kk,那么一层 CNN 只能看到 kk 个相邻的 token。想看到距离为 LL 的位置,需要的层数为:

层数L1k1\text{层数} \geq \frac{L - 1}{k - 1}

也就是说,远距离交互的路径长度O(L/k)O(L / k)——虽然比 RNN 的 O(L)O(L) 好,但仍然不是 O(1)O(1)

交互对比:三种架构的信息路径长度
拖动滑块改变序列长度,观察不同架构的路径差异

Attention 在这里的优势是:任意两个位置之间的交互路径长度始终为 O(1)O(1),因为它允许每个位置直接”看到”所有其他位置。

架构路径长度序列操作复杂度并行度
RNNO(n)O(n)O(n)O(n)O(1)O(1)
CNN(kk 层)O(n/k)O(n / k)O(nk)O(n \cdot k)O(1)O(1)
Self-AttentionO(1)O(1)O(n2d)O(n^2 \cdot d)O(n)O(n)

Self-Attention 用 O(n2)O(n^2) 的计算换来了 O(1)O(1) 的信息路径,这是它的核心 trade-off。


固定长度表示为什么不够#

这是理解 Attention 最关键的一点。

信息论视角#

把输入序列看成一个信息源,它的信息量(熵)大致随序列长度线性增长:

H(X1,X2,,XT)THˉH(X_1, X_2, \ldots, X_T) \approx T \cdot \bar{H}

其中 Hˉ\bar{H} 是每个 token 的平均信息量。

但固定维度向量 cRd\mathbf{c} \in \mathbb{R}^d 能承载的信息量是有上界的(由 dd 决定)。当 TT 增大到一定程度:

THˉ>capacity(c)T \cdot \bar{H} > \text{capacity}(\mathbf{c})

信息必然会丢失。这不是模型”没学好”,而是信息论的硬约束

不同解码步骤需要不同信息#

即使假设 c\mathbf{c} 的容量无限大,还有一个更根本的问题:

解码第 1 个词时需要的信息,和解码第 10 个词时需要的信息,往往不是一回事:

p(y1c)需要主语信息p(y10y<10,c)需要动作/时态信息\underbrace{p(y_1 \mid \mathbf{c})}_{\text{需要主语信息}} \neq \underbrace{p(y_{10} \mid y_{<10}, \mathbf{c})}_{\text{需要动作/时态信息}}

但如果所有步骤都只能用同一个 c\mathbf{c},等于要求这个向量同时满足所有解码步骤的需求。这是一个很强、也很不自然的要求。

更合理的做法是:输入序列先保留下来,每次输出时,再根据当前需求去取不同部分。

这正是 Attention 的出发点。


Attention 到底解决了什么#

Attention 的核心转变用一个公式就能说清楚。

旧方案(固定 context vector):

c=hT(只用 Encoder 最后一个状态)\mathbf{c} = \mathbf{h}_T \quad \text{(只用 Encoder 最后一个状态)}

Attention 方案(动态 context vector):

ct=j=1Tαtjhj\mathbf{c}_t = \sum_{j=1}^{T} \alpha_{tj} \cdot \mathbf{h}_j

其中 αtj\alpha_{tj} 是 Decoder 在生成第 tt 个输出时,对 Encoder 第 jj 个位置的注意力权重

αtj=exp(etj)k=1Texp(etk)\alpha_{tj} = \frac{\exp(e_{tj})}{\sum_{k=1}^{T} \exp(e_{tk})}

etje_{tj} 是一个对齐分数,衡量”Decoder 当前状态”和”Encoder 第 jj 个位置”之间的相关性:

etj=a(st1,hj)e_{tj} = a(\mathbf{s}_{t-1}, \mathbf{h}_j)

这里 a()a(\cdot) 是一个可学习的对齐函数(比如一个小型前馈网络),st1\mathbf{s}_{t-1} 是 Decoder 在前一步的隐藏状态。

步进演示:Attention 计算流程
逐步观察 Attention 如何从”分数 → 权重 → 加权求和”完成动态信息提取(支持键盘 ←→)
0 / 5

关键的变化是:

c旧:固定不变ct新:随 t 变化\underbrace{\mathbf{c}}_{\text{旧:固定不变}} \longrightarrow \underbrace{\mathbf{c}_t}_{\text{新:随 } t \text{ 变化}}

每个解码步骤 tt 都有自己独立的 context vector ct\mathbf{c}_t,它由 Encoder 所有位置的加权和构成,而权重 αtj\alpha_{tj} 反映了当前步骤对各位置的关注程度。

所以 Attention 真正解决的,不是单独一个点,而是三个问题一起

  1. 读取方式太死 → 现在每一步都可以按需读取不同位置
  2. 远距离路径太长 → 每个位置直接与所有位置交互,路径 O(1)O(1)
  3. 不同步骤需求不同 → 每一步有独立的 ct\mathbf{c}_t

“动态地看不同位置”是什么意思#

这是后面所有 Attention 公式的直觉原点。

同一个输入序列,在不同输出时刻,模型关注的位置本来就应该不同。

交互演示:动态注意力分配
点击下方不同的输出词,观察注意力权重的动态变化
← 点击输出词查看注意力分布

注意,Attention 不是”只看一个位置”。很多时候,当前输出会同时依赖多个位置。所以更准确地说:

Attention 是一种按相关性分配读取权重的机制。它不是硬选择(hard selection),而是软检索(soft retrieval)。

用数学表达就是:

ct=j=1Tαtjhj,where j=1Tαtj=1,αtj0\mathbf{c}_t = \sum_{j=1}^{T} \alpha_{tj} \mathbf{h}_j, \quad \text{where } \sum_{j=1}^{T} \alpha_{tj} = 1, \quad \alpha_{tj} \geq 0

每个 αtj\alpha_{tj} 都是非负的,加起来为 1——这就是一个概率分布,描述了”当前步骤对各个输入位置的注意力分配”。


注意力热图:全景视角#

上面的柱状图一次只看一个输出词的注意力分布。如果把所有输出词的注意力权重放在一起,就得到了一个注意力矩阵(attention heatmap)——这也是 Bahdanau 论文中最经典的可视化。

交互热图:完整注意力矩阵
悬停/点击任意格子查看该位置的注意力权重。颜色越深 = 权重越大。
悬停在热图上查看权重

热图的每一对应一个英文输出词,每一对应一个中文输入词。你可以清楚地看到:

  • 对角线附近的高亮带表示局部对齐(顺序大致对应的翻译)。
  • 偏离对角线的亮点表示跨距对齐(输出需要回头看远处的输入)。
  • 每行的颜色分布不同,说明每个输出步骤关注的位置确实不一样

这就是 Attention 的可视化证据:模型真的在”动态地看不同位置”。


Bahdanau Attention 的完整公式#

这里给出 Bahdanau et al. (2015) 的原始 Attention 公式,供需要完整数学推导的读者参考。

Encoder:双向 RNN,得到每个位置的注释向量(annotation):

hj=[hj;hj]R2d\mathbf{h}_j = [\overrightarrow{\mathbf{h}}_j ; \overleftarrow{\mathbf{h}}_j] \in \mathbb{R}^{2d}

Decoder:在生成第 tt 个 token 时:

  1. 计算对齐分数:
etj=vatanh(Wast1+Uahj)e_{tj} = \mathbf{v}_a^\top \tanh(\mathbf{W}_a \mathbf{s}_{t-1} + \mathbf{U}_a \mathbf{h}_j)
  1. 归一化得到注意力权重:
αtj=softmaxj(etj)=exp(etj)k=1Texp(etk)\alpha_{tj} = \text{softmax}_j(e_{tj}) = \frac{\exp(e_{tj})}{\sum_{k=1}^{T} \exp(e_{tk})}
  1. 计算加权上下文向量:
ct=j=1Tαtjhj\mathbf{c}_t = \sum_{j=1}^{T} \alpha_{tj} \mathbf{h}_j
  1. 更新 Decoder 状态:
st=f(st1,yt1,ct)\mathbf{s}_t = f(\mathbf{s}_{t-1}, y_{t-1}, \mathbf{c}_t)
  1. 预测输出概率:
p(yty<t,x)=g(st,yt1,ct)p(y_t \mid y_{<t}, \mathbf{x}) = g(\mathbf{s}_t, y_{t-1}, \mathbf{c}_t)

其中 va,Wa,Ua\mathbf{v}_a, \mathbf{W}_a, \mathbf{U}_a 都是可学习参数。

后面第 3 讲会详细展开 Self-Attention 的公式(QKTVQK^TV 形式),它是 Bahdanau Attention 的进一步简化和推广。


这一讲先记住三句话#

如果你读完这一讲只记住三件事,我希望是:

  1. Attention 首先在解决”怎么取信息”,而不是单纯解决”怎么存信息”。
  2. 旧模型的瓶颈不只是记不住,而是必须把所有信息提前压进固定长度表示里。
  3. Attention 的核心思想是:当前需要什么,就按相关性去不同位置取什么。

一个最小化心智模型#

方案类比数学描述
RNN / 固定向量先把整本书写成一页摘要,之后所有问题都只能看这页摘要c=hT\mathbf{c} = \mathbf{h}_T(固定)
Attention书还放在桌上,你每回答一个问题,都可以重新翻到最相关的几页ct=jαtjhj\mathbf{c}_t = \sum_j \alpha_{tj} \mathbf{h}_j(动态)

Attention 没有取消”表示学习”,而是把”读取”这件事从一次性压缩,改成了按需检索


试着想一想#

  1. 如果一句话长度从 10 个词变成 100 个词,固定长度向量为什么会越来越吃力?(提示:信息论)
  2. 为什么生成一句翻译的不同词时,模型需要看输入中的不同位置?
  3. 如果 Attention 权重 αtj\alpha_{tj} 退化成均匀分布 αtj=1/T\alpha_{tj} = 1/T,会发生什么?这还有意义吗?
  4. 为什么说 Attention 的信息路径长度是 O(1)O(1)
  5. LSTM 缓解了梯度消失,为什么仍然需要 Attention?

如果这五个问题你已经能用自己的话讲清楚,那这一讲的目标就达到了。


参考文献#

  • Sutskever, I., Vinyals, O., & Le, Q. V. (2014). Sequence to Sequence Learning with Neural Networks. NeurIPS.
  • Cho, K., et al. (2014). Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation. EMNLP.
  • Bahdanau, D., Cho, K., & Bengio, Y. (2015). Neural Machine Translation by Jointly Learning to Align and Translate. ICLR.
  • Vaswani, A., et al. (2017). Attention Is All You Need. NeurIPS.

下一讲#

下一讲进入 Attention 最常见、也最容易混淆的三个角色:

  • Query
  • Key
  • Value

我们先不急着写公式,而是先把它们讲成一个非常直观的”查资料 / 取信息”过程。


Attention 01:为什么需要 Attention
https://jerry609.github.io/blog/attention-01-why-attention
Author Jerry
Published at March 16, 2026
Comment seems to stuck. Try to refresh?✨