# 注意力机制总括

总结来自[这篇论文的第7章](http://arxiv.org/abs/1808.09772)

## 注意力机制

注意力机制是一种在**编码器-解码器**结构中使用到的机制, 现在已经在多种任务中使用:

* 机器翻译(Neural Machine Translation, NMT)
* 图像描述(Image Captioning (translating an image to a sentence))
* 文本摘要(Summarization(translating to a more compact language))

而且也不再局限于**编码器-解码器**结构, 多种变体的注意力结构, 应用在各种任务中.

总的来说, 注意力机制应用在:

* 允许**解码器**在序列中的多个向量中, 关注它所需要的信息, 是传统的注意力机制的用法. 由于使用了编码器多步输出, 而不是使用对应步的单一定长向量, 因此保留了更多的信息.
* 作用于**编码器**, 解决表征问题(例如Encoding Vector再作为其他模型的输入), 一般使用**自注意力**(self-attention)

### 1. 编码器-解码器注意力机制

#### 1.1 编码器-解码器结构

![](https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWicMiaqpI5cdFEvj2sOZVykZicf02bU7VDhpNWAsu5ZoFYpum7RyEjJRhJiapmn7C0GV7IwzIIicWNDgbA/640?wx_fmt=png\&tp=webp\&wxfrom=5\&wx_lazy=1\&wx_co=1)

如上图, **编码器**将输入**嵌入**为一个向量, **解码器**根据这个向量得到输出. 由于这种结构一般的应用场景(机器翻译等), 其输入输出都是**序列**, 因此也被称为序列到序列的模型**Seq2Seq**.

对于编码器-解码器结构的训练, 由于这种结构**处处可微**, 因此模型的参数$$\theta$$可以通过训练数据和**最大似然估计**得到最优解, 最大化对数似然函数以获得最优模型的参数, 即:

$$\arg\max\limits\_{\theta}{\sum\limits\_{(x,y)\in{corpus}}\log{p(y|x;\theta)}}$$

这是一种**端到端**的训练方法.

#### 1.2 编码器

原输入通过一个网络模型(CNN, RNN, DNN), 编码为一个向量. 由于这里研究的是注意力, 就以**双向RNN**作为示例模型.

对于每个时间步$$t$$, 双向RNN编码得到的向量$$h\_t$$可以如下表示:

![](http://garnet.oss-cn-shenzhen.aliyuncs.com/18-10-10/2726445.jpg)

#### 1.3 解码器

这里的解码器是**单向RNN**结构, 以便在每个时间点上产生输出, 行程序列. 由于解码器**仅**使用**最后时间步**$$T$$对应的编码器的隐藏向量$$h\_{T\_x}$$, $$T\_x$$指的是当前样本的时间步长度(对于NLP问题, 经常将所有样本处理成等长的). 这就迫使编码器将更多的信息整合到最后的隐藏向量$$h\_{T\_x}$$中.

但由于$$h\_{T\_x}$$是单个长度一定的向量, 这个单一向量的**表征能力**有限, 包含的信息量有限, 很多信息都会损失掉.

**注意力机制**允许**解码器**在每一个时间步$$t$$处考虑整个编码器输出的**隐藏状态序列**$$(h\_1, h\_2, \cdots, h\_{T\_x})$$, 从而**编码器**将更多的信息分散地保存在所有隐藏状态向量中, 而**解码器**在使用这些隐藏向量时, 就能决定对哪些向量更关心.

具体来说, 解码器生产的目标序列$$(y\_1, \cdots, y\_{T\_x})$$中的每一个输出(如单词)$$y\_t$$, 都是基于如下的条件分布:

$$P\[y\_t|{y\_1,\cdots,y\_{t-1}},c\_t]=softmax(W\_s \tilde{h}\_t)$$

其中$$\tilde{h}\_t$$是**引入注意力的隐藏状态向量**(attentional hidden state), 如下得到:

$$\tilde{h}\_t=\tanh(W\_c\[c\_t;h\_t])$$

$$h\_t$$为编码器顶层的隐藏状态, $$c\_t$$是上下文向量, 是通过当前时间步上下文的隐藏向量计算得到的, 主要有**全局**和**局部**两种计算方法, 下午中提到. $$W\_c$$和$$W\_s$$参数矩阵训练得到. 为了式子的简化没有展示偏置项.

#### 1.4 全局注意力

通过全局注意力计算**上下文向量**$$c\_t$$时, 使用整个序列的隐藏向量$$h\_t$$, 通过**加权和**的方式获得. 假设对于样本$$x$$的序列长度为$$T\_x$$, $$c\_t$$如下计算得到:

$$c\_t=\sum\limits\_{i=1}^{T\_x}\alpha\_{t,i}h\_i$$

其中长度为$$T\_x$$的校准向量**alignment vector** $$\alpha\_t$$的作用是在$$t$$时间步, 隐藏状态序列中的所有向量的重要程度. 其中每个元素$$\alpha\_{t,i}$$的使用**softmax**方法计算:

$$\alpha\_{t,i}=\frac{\exp(score(h\_t, h\_i))}{\sum\limits\_{j=1}^{T\_x}\exp(score(h\_t, h\_j))}$$

值的大小指明了序列中哪个时间步对预测当前时间步$$t$$的作用大小.

**score函数**可以是任意的比对向量的函数, 一般常用:

* 点积: $$score(h\_t, h\_i)=h\_t^Th\_i$$

  这在使用全局注意力时有更好的效果
* 使用参数矩阵:

  $$score(h\_t, h\_i)=h\_t^TW\_{\alpha}h\_i$$

  这就相当于使用了一个**全连接层**, 这种方法在使用局部注意力时有更好的效果.

全局注意力的总结如下图:

![](https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWicMiaqpI5cdFEvj2sOZVykZic5SwVXksjias1lA5ukFcJ4ficRgmwIyBLK8PcibmvT8Tq4iaIqMl0IaQfVw/640?wx_fmt=png\&tp=webp\&wxfrom=5\&wx_lazy=1\&wx_co=1)

#### 1.5 局部注意力

全局注意力需要在序列中所有的时间步上进行计算, 计算的代价是比较高的, 可以使用**固定窗口大小**的局部注意力机制, 窗口的大小为$$2D+1$$. $$D$$为超参数, 为窗口边缘距离中心的单方向距离. 上下文向量$$c\_t$$的计算方法如下:

$$c\_t=\sum\limits\_{i=p\_t-D}^{p\_t+D}\alpha\_{t,i}h\_i$$

可以看到, 只是考虑的时间步范围的区别, 其他完全相同. $$p\_t$$作为窗口的中心, 可以直接使其等于当前时间步$$t$$, 也可以设置为一个变量, 通过训练获得, 即:

$$p\_t=T\_x\sigma(v\_p^T\tanh(W\_ph\_t))$$

其中$$\sigma$$为**sigmoid**函数, $$v\_p$$和$$W\_p$$均为可训练参数. 因此这样计算得到的$$p\_t$$是一个**浮点数**, 但这并没有影响, 因为计算校准权重向量$$\alpha\_t$$时, 增加了一个均值为$$p\_t$$, 标准差为$$\frac{D}{2}$$的**正态分布**项:

$$\alpha\_{t,i}=\frac{\exp(score(h\_t, h\_i))}{\sum\limits\_{j=1}^{T\_x}\exp(score(h\_t, h\_j))}\exp(-\frac{(i-p\_t)^2}{2(D/2)^2})$$

当然, 这里有$$p\_t\in\mathbb{R}\cap\[0, T\_x]$$, $$i\in\mathbb{N}\cap\[p\_t-D, p\_t+D]$$. 由于正态项的存在, 此时的注意力机制认为窗口中心附近的时间步对应的向量更重要, 且与全局注意力相比, 除了正态项还增加了一个截断, 即一个截断的正态分布.

局部注意力机制总结如下图:

![](https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWicMiaqpI5cdFEvj2sOZVykZicY0S8hIU5KTVdgIyhkibh0t8jUaPnR0oKSD2QVF3sE3v50agib3ZySuqQ/640?wx_fmt=png\&tp=webp\&wxfrom=5\&wx_lazy=1\&wx_co=1)

### 2. 自注意力

#### 2.1 与编码器-解码器注意力机制的不同

最大的区别是自注意力模型**没有解码器**. 因此有两个最直接的区别:

* **上下文向量**$$c\_t$$在**seq2seq**模型中, $$c\_t=\sum\limits\_{i=1}^{T\_x}\alpha\_{t,i}h\_i$$, 用来组成**解码器**的输入$$\tilde{h}\_t=\tanh(W\_c\[c\_t;h\_t])$$, 但由于自注意力机制没有解码器, 所以这里就直接是模型的输出, 即为$$s\_t$$
* 在计算校准向量$$\alpha\_t$$时, **seq2seq**模型使用的是各个位置的隐藏向量与当前隐藏向量的比较值. 在**自注意力**机制中, 校准向量中的每个元素由每个位置的隐藏向量与当前时间步$$t$$的**平均最优向量**计算得到的, 而这个平均最优向量是通过训练得到的

#### 2.2 自注意力机制实现

首先将隐藏向量$$h\_i$$输入至全连接层(权重矩阵为$$W$$), 得到$$u\_i$$:

$$u\_i=\tanh(Wh\_i)$$

使用这个向量计算校正向量$$\alpha\_t$$, 通过**softmax**归一化得到:

$$\alpha\_{t,i}=\frac{\exp(score(u\_i, u\_t))}{\sum\limits\_{j=1}^{T\_x}\exp(score(u\_j, u\_t))}$$

这里的$$u\_t$$是当前时间步$$t$$对应的**平均最优向量**, 每个时间步不同, 这个向量是通过**训练**得到的.

最后计算最后的输出:

$$s\_t=\sum\limits\_{i=1}^{T}a\_{t, i}h\_i$$

一般来说, 在序列问题中, 只关心最后时间步的输出, 前面时间步不进行输出, 即最后的输出为$$s=s\_T$$

#### 2.3 层级注意力

如下图, 对于一个NLP问题, 在整个架构中, 使用了两个**自注意力**机制: **词层面**和**句子层面**. 符合文档的自然层级结构:

**词->句子->文档**. 在每个句子中, 确定每个单词的重要性, 在整片文档中, 确定不同句子的重要性.

![](https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWicMiaqpI5cdFEvj2sOZVykZic11SAVzYTkwjmr0v3r0Gk2zfgiakvPfqkdQDCW768A3JTFFzc4B0PT6A/640?wx_fmt=png\&tp=webp\&wxfrom=5\&wx_lazy=1\&wx_co=1)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blessbingo.gitbook.io/garnet/ji-qi-xue-xi/xu-lie-mo-xing/zhu-yi-li-ji-zhi/zhu-yi-li-ji-zhi-zong-kuo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
