注意力机制和Transformer模型

前言

在Attention出现前,RNN、LSTM这种Encoder-Decoder模型是序列处理的主流模型。这种架构把任务分为两个部分,第一是Encoder:将输入通过某种方式编码为一个固定长度的向量,称为Context Vector;第二步是Decoder:将Context Vector解码,逐字生成目标输出序列。RNN和LSTM主要是将每一轮的输出作为下一轮的输入,循环地生成输出直到结尾。但是这样首先是一个串行的步骤,性能不佳,而且如果输入太长,由于Context Vector的长度有限,难以捕捉全部的输入信息,

Attention机制的引入

2014年,为了解决context vector的这个问题,蒙特利尔大学的Dzmitry Bahdanau首次在NLP领域应用了Attention机制。这种初级的Attention机制被称为Bahadnau Attention。Bahdanau Attention认为Context Vector不应该是静态的。原本的RNN使用隐藏状态来保存记忆。Encoder计算隐藏状态的方法是:

$$ h_t=\tanh (W_{encode}\cdot h_{t-1} + U_{encode}\cdot x_t + b) $$

可以简写为:

$$h_t = \text{RNN}(h_{t-1}, x_t)$$

其中$ h_t$就是t时刻的隐藏状态,$x_t$就是t时刻的输入。通过分别和W、U相乘,决定了我们保留多少过去的记忆和新的信息。同样地,Decoder也有隐藏状态:

$$s_t = \tanh(W_{dec} \cdot s_{t-1} + U_{dec} \cdot [y_{t-1}, c_t] + b_{dec})$$

可以简写为

$$s_t = \text{RNN}(s_{t-1}, y_{t-1},c_t)$$

这里的$c_t$就是Context Vector。在普通RNN中,这个就是最后一轮Encoder的$h_t$。但是如果序列层过长,由于隐藏层记忆了太多轮,会导致记忆的丢失。

Bahdanau Attention解决这个问题的方法是:首先,不再只存一个$h$,而是对于整个Encode过程中的所有$h$,全部保留下来,存在一个矩阵里。然后在Decoder前面增加了一个小型的神经网络,输出每个token时,都计算一下当前已经输出的序列和每个h之间的分数:

$$score(s_{t-1}, h_j) = v^T \tanh(W s_{t-1} + U h_j)$$

这里的$s_t$是Decoder的隐藏状态。

使用Softmax把这些分数做一个归一化:

$$a_{tj} = \frac{\exp(score_i)}{\sum \exp(score_k)}$$

就计算出对每个h的注意力权重。然后根据这个注意力权重来算出Context Vector:

$$ c_t=\sum_{j}a_{tj}h_j $$

也就是对所有$h$进行一个加权求和。使用这个context vector给Decoder,Decoder再生成输出并计算$s_t$

由于这里的score分数是采用了s和h相加而成,因此Bahdanau Attention也被称为加性注意力(Additive Attention)。

Attention机制的改良

2015年,斯坦福大学的Minh-Thang Luong对Attention机制进行了改良,与其还要单独用一个神经网络计算注意力,不如直接用点积来计算相似度:

$$score(s_{t-1},h_j)=s_{t-1}^T\cdot h_j$$

这样直接做矩阵乘法,充分利用了GPU的性能。

Attention再进化——Self Attention

2017年,Google发布了著名论文Attention is All You Need,直接把传统RNN结构取代,改为只用Attention。之前的结构里,RNN在Encode时每次计算一个h,然后Decode时每次和h算一个注意力分数。

Attention is All You Need中指出,我们不需要再做这种麻烦的注意力计算方式,而是采用“Self Attention“,对于输入序列中的每个词,我们直接计算其与序列中其他词的

Author

John Doe

Posted on

2026-01-22

Updated on

2026-01-28

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.