1. 注意力机制起源

讲注意力机制之前,咱们先聊聊它为什么会出现。说白了,没有痛点就没有创新。

我刚开始做机器翻译那会儿,用的还是最基础的 Seq2Seq 模型。当时觉得这结构挺巧妙的——一个编码器把源语言句子压成一个向量,解码器再从这个向量里生成目标语言。但做着做着就发现问题了:句子一长,效果就崩。

1.1 Seq2Seq 的瓶颈:信息瓶颈问题

Seq2Seq 的核心思路很简单:

  • 编码器:把输入序列(比如英文句子)编码成一个固定长度的上下文向量 c
  • 解码器:基于这个 c 和之前生成的词,逐步生成目标序列(比如中文句子)

你想想看,无论输入句子是 5 个词还是 50 个词,最终都得压缩成一个固定长度的向量。这就像让你把一整部电影的内容用一句话概括——信息损失是必然的。

核心问题:固定长度的上下文向量成为信息瓶颈。长序列中,早期输入的信息在压缩过程中被稀释甚至丢失。

我在一个英中翻译项目里遇到过这种情况。训练时句子长度在 10 个词以内时,BLEU 值还不错。一旦测试集里出现 30 个词以上的长句,翻译质量直接腰斩。尤其是句子开头的那些词,经常被漏译或错译。

1.2 为什么固定向量不行?

咱们用个具体例子来说明。假设要翻译这句话:

英文:The cat, which was sitting on the mat, started to purr loudly.
中文:那只坐在垫子上的猫,开始大声咕噜。

在传统 Seq2Seq 里,编码器读完整个句子后,生成一个固定向量 c。解码器生成每个中文词时,看的都是同一个 c。这意味着:

  • 生成「那只」时,模型需要关注 The cat
  • 生成「垫子」时,模型需要关注 mat
  • 生成「咕噜」时,模型需要关注 purr

但传统模型做不到这种「按需关注」。它只能从那个压缩后的向量里「盲猜」每个位置该生成什么。

我曾经踩过的坑:在训练一个对话生成模型时,我尝试把编码器输出的维度从 256 增加到 1024,想着「向量大了总能装更多信息吧」。结果呢?训练变慢了,过拟合了,长句效果依然没改善。问题不在向量大小,而在「固定长度」这个结构本身。

1.3 Bahdanau Attention:让模型学会「看哪里」

2015 年,Bahdanau 等人提出了一个关键思路:解码时,每一步都动态地「回头看」编码器的所有隐藏状态,而不是只依赖一个固定向量。

这就是 Bahdanau Attention(也叫 Additive Attention)。它的核心思想可以概括为三步:

  1. 计算注意力分数:解码器当前状态与编码器每个位置隐藏状态的匹配程度
  2. 归一化:用 softmax 把分数转成概率分布(注意力权重)
  3. 加权求和:用注意力权重对编码器隐藏状态做加权平均,得到上下文向量

公式长这样:

e_ij = v^T * tanh(W * h_j + U * s_{i-1})    # 注意力分数
α_ij = exp(e_ij) / Σ_k exp(e_ik)             # 注意力权重
c_i  = Σ_j α_ij * h_j                        # 上下文向量

其中:

  • h_j 是编码器第 j 个位置的隐藏状态
  • s_{i-1} 是解码器上一个时间步的状态
  • W、U、v 是可学习的参数

我的理解方式:你可以把注意力机制想象成一个「聚光灯」。传统 Seq2Seq 是在黑屋子里用一个手电筒照全场,光线分散。注意力机制则是在每个解码步骤,自动把聚光灯打到最需要的位置上。

1.4 注意力机制带来的改变

有了注意力之后,翻译长句的效果明显提升。咱们用表格对比一下:

对比维度 传统 Seq2Seq Seq2Seq + Attention
信息传递方式 固定长度向量 动态加权求和
长序列表现 随长度增加急剧下降 相对稳定
可解释性 黑盒,不知道关注了哪里 可以可视化注意力权重
计算复杂度 O(n) O(n²)(但可接受)
参数量 较少 增加少量参数

我在实际项目中验证过:加入 Bahdanau Attention 后,30 词以内的句子 BLEU 值提升了 3-5 个点,50 词以上的长句提升更明显,能达到 8-10 个点。而且注意力权重可视化出来,确实能看到模型在生成每个词时「盯」着源句子的对应位置——这感觉就像你终于能看懂模型在想什么了。

1.5 注意力机制的核心知识结构

下面这张图梳理了从 Seq2Seq 到 Bahdanau Attention 的演进逻辑:

注意力机制起源:从 Seq2Seq 到 Bahdanau Attention 问题:长序列翻译效果差 传统 Seq2Seq:固定长度上下文向量 编码器 → 固定向量 c → 解码器 信息瓶颈:长序列信息被压缩丢失 早期输入被稀释,长句效果急剧下降 Bahdanau Attention:动态注意力机制 解码每一步动态计算编码器各位置的注意力权重 ① 计算注意力分数 e_ij = score(h_j, s_{i-1}) ② Softmax 归一化 α_ij = softmax(e_ij) ③ 加权求和 c_i = Σ α_ij * h_j

1.6 为什么说这是「注意力」?

这个名字其实很形象。你想想看,当你在嘈杂的房间里听人说话时,你会不自觉地「注意」到说话人的嘴唇和声音,忽略背景噪音。注意力机制做的也是类似的事——在众多输入中,有选择地聚焦于当前最相关的部分。

Bahdanau Attention 有几个关键特性,至今仍在各种注意力变体中被继承:

  • 可微分:整个注意力计算过程是可微的,可以用反向传播端到端训练
  • 动态性:每个解码步骤的注意力分布不同,不是静态的
  • 可解释性:注意力权重可以可视化,帮助我们理解模型在关注什么

一个重要的认知转变:注意力机制不是「要不要关注」的问题,而是「如何自动学会关注哪里」的问题。它把人类的直觉——按需聚焦——变成了一个可训练的数学框架。

嗯,到这里你应该明白了。注意力机制的诞生,本质上是对「固定长度信息瓶颈」的一次反击。它让模型不再「盲人摸象」,而是学会了「按需取用」。这个思路后来被发扬光大,演化出 Transformer 里的 Self-Attention、Multi-Head Attention,以及视觉语言模型里的 Cross-Attention——但追根溯源,都是从 Bahdanau Attention 这一步开始的。