这一节的重点在于自注意力机制(Self-Attention)的引入
RNN 和 CNN 的局限性
在笔记三循环神经网络中,我们已经知道了实用 RNN 可以取处理时序的数据。但是 RNN 处理这种数据的方式,是非常低效的:后一个单元需要用到前一个单元的输出或者是中间结果。这就导致了,如果我想要下图中的输出 b^4^,就必须从头到尾将 a^1^~a^4^ 一个个的输入网络。我们想要找到一种并行处理序列数据的能力:考虑将这个序列一字排开输入 CNN。CNN 中不同的卷积核是可以平行计算的,但是 CNN 也有着其局限性:低层的卷积核只拥有很小的视野,如果想要利用好整个序列的数据,必须加深整个网络取高层的卷积核。所以,我们的重点就放在,如何让 CNN 的每个节点都能 “看到” 整个序列的信息。
自注意力机制
对于输入的某个序列数据,自注意力机制的每个单元会输出一个序列,同时内部对序列中每一项的计算是并行的。
自注意力机制的计算过程其实并没有看上去那么复杂,直观理解的话,我们在得到每一个输出的时候,都是用了输入序列中所有的信息计算得到的。计算过程图示如下:
输入序列中的每一项都会做这样的 attention 操作,所以整个过程就可以写成矩阵相乘的形式
除此之外,self-attention 还有一个多头机制 (multi head)。多头机制类似于卷积操作中不同的卷积核,每一个 “头” 都可以有着自己的关注点,各司其职。
自注意力机制的局限性
虽然自注意力机制给了 CNN 处理卷积序列的能力,但是在做计算的时候,每一个位置都能得到其他所有位置的信息,这样就使得整个过程下来丢失了序列中每一项的先后关系。为此,在原始 paper 里面,每一个 input x^i^ 通过 transform 变成 a^i^ 以后,还要加上一个维度相同的向量 e^i^, e^i^ 是我们自定义的,代表位置的资讯。比如,我们可以在原来的 a^i^ 后面街上一个 one-hot 的向量,1 的位置就代表了当前的词在序列中的位置。
Seq2Seq with attention
这个其实非常的直接,只要把原先 seq2seq 中的 encoder 和 decoder 的 RNN 结构全部换成 self-attention 就行了
Transformer
Transformer 的结构看这个图已经很清晰了,这里稍微提几个点:
- 在左边的灰色 block 会重复 N 次,每个 block 的结构为 multi-head attention ——> add&norm ——> feed forward ——> add&norm
- 上一步的 add 操作是将输入和这个块的输出直接相加,这个和拼接是不一样的(类似于残差的思想?这个不确定)。后面的 norm 操作是 layer norm,batch norm 是对一个 batch 中的所有样本做 normalization,而 layer norm 实对当前样本的输出做 normalization。
Transformer 的可视化
在做了 attention 之后,网络会知道词语此之间的某些关系(不同于词向量,词向量也是没有考虑先后关系的),比如图示中 it 会 attend 到其指代对象
下面这张图则是说明了 multi-head 的每个头都是在 “专注于” 不同的事情