Attention 机制在 NLP 中的应用
Attention 机制在自然语言处理(NLP)领域应用广泛,但其基本原理常被误解。本文旨在通过清晰的逻辑梳理 Attention 的核心概念、计算方式及实现。
Encoder-Decoder 模型基础
Seq2Seq(Sequence to Sequence)模型解决的是将一个序列映射到另一个序列的问题,典型应用场景包括:
- 机器翻译:源语言文本序列 → 目标语言文本序列
- 语音识别:声学特征序列 → 识别文本序列
- 问答系统:问题描述单词序列 → 生成答案单词序列
- 文本摘要:原文本序列 → 摘要序列
基础的 Seq2Seq 模型由《Sequence to Sequence Learning with Neural Networks》提出,主要包含 Encoder、Decoder 以及固定长度的语义向量。
Encoder 部分
Encoder 负责将输入序列编码为上下文信息。它通常使用 RNN、LSTM 或 GRU 等循环神经网络。
以 RNN 为例,当前隐藏状态由上一个输入的隐藏状态和当前输入共同决定:
$$h_t = f(h_{t-1}, x_t)$$
其中:
- $h_t$:RNN 当前隐藏状态
- $h_{t-1}$:上一个输入的隐藏状态
- $x_t$:当前的输入
当输入序列结束后,最后一个隐藏状态(或所有隐藏状态的聚合)被作为语义向量 $C$ 传递给 Decoder。这是一个固定长度的向量。
Decoder 部分
Decoder 接收 Encoder 输出的语义向量 $C$ 以及已生成的输出序列,预测下一个输出单词 $y_t$。
$$y_t = g(y_{t-1}, s_{t-1}, C)$$
其中 $s_{t-1}$ 是 Decoder 的隐藏状态。这种架构存在明显缺陷:由于语义向量 $C$ 是固定长度的,对于长输入序列,部分关键信息会在压缩过程中丢失,导致解码结果不佳。
Attention 机制原理
为了解决固定长度语义向量的信息瓶颈,Bahdanau 等人提出了 Attention 机制。其核心思想是模拟人类翻译时的注意力分配:在翻译某个词时,只关注源语句中相关的几个词。
工作流程
- 输入序列编码:输入序列经过 Encoder 得到一系列隐藏状态向量 $h_1, h_2, ..., h_N$。
- 注意力权重计算:对于 Decoder 的每一步,计算当前状态与 Encoder 各隐藏状态的相关性,得到注意力权重 $eta_{t,i}$。
- 计算语义向量:根据权重对 Encoder 的所有隐藏状态进行加权求和,得到动态的上下文向量 $c_t$。
- Decoder 输出:结合动态上下文向量 $c_t$ 和已生成的历史输出,预测下一个词。
注意力权重的计算方法
计算注意力权重通常涉及 Query(查询)、Key(键)和 Value(值)的概念。常见的计算函数包括:
-
Bilinear 方法 $$e_{t,i} = v^T \tanh(W_1 h_i + W_2 s_{t-1})$$ 使用权重矩阵建立映射,计算速度较快。
-
Dot Product(点积) $$e_{t,i} = s_{t-1}^T h_i$$ 直接计算点积,无需额外参数,但要求维度一致。
-
Scaled-Dot Product(缩放点积) $$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$ 在点积基础上除以向量维度的平方根,防止梯度消失,是 Transformer 模型的基础。
PyTorch 实现示例
以下是一个简化的 Scaled-Dot-Product Attention 实现,展示了如何计算注意力分数并生成上下文向量。


