3、Bahdanau注意力:加性注意力机制,上下文向量的计算,对齐模型

好,咱们接着聊注意力机制。上一章我们讲了经典的Seq2Seq模型,那个结构有个硬伤——编码器必须把整个输入句子压缩成一个固定长度的向量。你想想看,如果句子长了,比如20个词、30个词,这个向量能装得下所有信息吗?显然不行。

我记得2015年刚接触机器翻译项目时,就遇到了这个问题。模型翻译短句还行,一遇到长句就崩,经常漏掉关键信息。后来我看到了Bahdanau等人的论文,豁然开朗。他们提出的注意力机制,说白了就是让模型在生成每个词时,能回头看看源句子的不同位置,而不是死盯着那个固定向量。

加性注意力机制

Bahdanau注意力也叫加性注意力。为什么叫「加性」?因为它计算注意力分数时,用的是加法操作,而不是点积或乘法。

具体来说,给定解码器的上一个隐藏状态 s_{t-1} 和编码器的所有隐藏状态 h_j,我们计算一个分数:

e_{tj} = v_a^T tanh(W_a * s_{t-1} + U_a * h_j)

这里 v_aW_aU_a 都是可学习的参数矩阵。你看,这个公式里有个加法操作 W_a * s_{t-1} + U_a * h_j,所以叫加性注意力。

我个人习惯把这个公式拆成三步理解:

  1. 把解码器状态和编码器状态分别做线性变换
  2. 把变换后的结果加起来
  3. 通过tanh激活,再用一个向量做内积得到标量分数

嗯,这里要注意,tanh激活函数很重要。它把输出限制在[-1, 1]之间,能帮助训练更稳定。我在项目中遇到过,如果换成ReLU,模型收敛会慢很多,甚至不收敛。

核心要点:加性注意力通过一个小型神经网络(单隐藏层)来学习两个向量之间的相关性。它不要求编码器和解码器的隐藏状态维度相同,灵活性更高。

上下文向量的计算

有了注意力分数 e_{tj},下一步就是算权重。这个步骤你应该很熟悉了——softmax归一化:

α_{tj} = exp(e_{tj}) / Σ_k exp(e_{tk})

这里的 α_{tj} 就是注意力权重,它表示在生成第t个目标词时,模型应该关注源句子第j个词的程度。所有权重加起来等于1。

然后,上下文向量就是编码器隐藏状态的加权平均:

c_t = Σ_j α_{tj} * h_j

你想想看,这个上下文向量 c_t 是动态计算的。生成每个目标词时,它都不一样。这就解决了固定向量的问题。

我曾经在做一个中文到英文的翻译系统时,发现模型对「把」字句的处理特别差。后来分析注意力权重才发现,模型在生成英文被动语态时,注意力分散到了源句子的多个位置。调整了注意力机制的初始化参数后,效果明显提升。

小技巧:训练初期可以观察注意力权重的分布。如果权重过于均匀(每个位置都差不多),说明模型还没学会聚焦;如果权重过于集中(只关注一个位置),可能有信息丢失的风险。理想状态是集中在2-4个相关位置上。

对齐模型

Bahdanau在论文里把注意力机制叫做「对齐模型」。为什么叫对齐?因为它在学习源语言和目标语言之间的词对齐关系。

传统的统计机器翻译需要显式地做词对齐,比如用GIZA++工具。但Bahdanau的模型把对齐融入到了训练过程中,端到端地学习。

对齐模型的核心思想是:

  • 每个目标词应该关注源句子中相关的词
  • 对齐关系是软性的,一个目标词可以关注多个源词
  • 对齐权重通过反向传播自动学习

我举个例子。翻译「I love you」到中文「我爱你」:

目标词 源词注意力权重 解释
I: 0.95, love: 0.03, you: 0.02 主要关注I
I: 0.02, love: 0.92, you: 0.06 主要关注love
I: 0.01, love: 0.04, you: 0.95 主要关注you

你看,这个对齐关系非常清晰。但实际项目中,对齐关系往往没那么完美。我记得有一次做英日翻译,英语的「I like cats」翻译成日语「私は猫が好きです」,注意力图显示「like」同时关注了「好き」和「が」两个位置。这是因为日语语法结构不同,一个英语词可能对应多个日语词。

避坑指南:我曾经在训练一个长文本摘要模型时,发现注意力权重出现了「对角线偏移」现象——模型总是关注源文本中位置相近的词,而不是语义相关的词。这是因为训练数据中源文本和目标文本的顺序高度相关。解决办法是增加dropout,或者使用双向编码器来打破这种位置偏差。

Bahdanau注意力的优缺点

说了这么多,总结一下Bahdanau注意力的特点:

优点:

  • 不要求编码器和解码器维度相同,灵活性高
  • 通过tanh激活,表达能力比简单的点积更强
  • 在小数据集上表现稳定,不容易过拟合

缺点:

  • 计算速度慢,因为每个时间步都要计算所有编码器状态
  • 参数多,训练时需要更多数据
  • 在长序列上,softmax的归一化计算开销大

我个人建议,如果你的任务数据量不大(比如少于10万条),或者编码器和解码器维度不同,优先考虑Bahdanau注意力。如果追求速度,可以试试后面要讲的Luong注意力(点积注意力)。

好,这一章就到这里。下一章我们讲Luong注意力,它和Bahdanau有什么不同?为什么后来Transformer选择了点积注意力?到时候咱们细聊。