前言
之前学习过的模型都是输入一个向量,输出一个类型或者数值。但平时遇到的问题中,输入可能是多个向量,并且每个向量的长度不同。
当向模型输入的是词汇时,词汇需要用向量来表示,向量表示词汇的方法有以下两种。一种是one-hot Encoding,这种方法会开一个很长很长的向量,向量的长度等于全世界词汇的数量,向量中不同的位代表一个词汇,这种方法有个弊端就是看不出每个词汇的类型。word embedding则会给每个词汇一个向量,向量中包含有语义性质的信息。
对于模型的输出一般有以下几种情况,一是输入的每个向量都有一个label。二是输入的全部向量只有一个label。三是不确定输出有几个label,由机器决定输出几个label。
对于第一种情况,当我门向fully connected network出入如下图所示的句子时,第一个单词saw和第二个单词saw会被判断为同一个类型的词组,为了解决这个问题,我们可以把相邻两个词组放入fully connected network中,从而判断词组的类型。但是当一个词组需要考虑整个句子时该怎么办呢。
self- attention
self- attention解决了上面的问题。self- attention将词组考虑整个句子后得到一个新的输出,如下图。self- attention可以做多次,并且可以和FC网络交替使用。
self- attention的运作如下图所示。下面的b1,b2,b3,b4都是考虑了a1,a2,a3,a4得到的。这里b1,b2,b3,b4是同时得到的。
下面我们详细讲解一下self- attention的运作流程。对于b1,首先根据a1找到整个句子中与a1的label有关的,每个向量与a1的关联程度用字母表示。
两个向量相关性的计算如下图所示,首先将输入向量分别乘和得到q和k之后,q和k做内积就可得到
将q+k后放进激活函数中,得到的值乘上W即可得到关联程度。
self-attention中各个输入计算相关性如下图,当计算a1与a2,a3,a4相关性时,a1*q1 与a2*k2,a3*k3,a4*k4做内积便可得到相关性。对于其他词组同理可得相关性。每个相关性计算完后经过一个softmax得到新的。
之后根据抽取出重要信息,用a1~a4分别乘得到v1~v4,v1~v4与相关性相乘并相加得到了b1,由此可见b会接近于最大的输入的v,若1,2 最大,则b1会最接近于v2。
同理我们还可以得到b2,b3,b4,其中b1,b2,b3,b4是可以同时得到的,不是一个个计算出来的。
接下来我们从矩阵乘法的角度来分析一下self-attention。
从下图中我们可以看到,将q1~q4写作矩阵Q,a1~a4写作矩阵I,v1~v2写作矩阵V,可以得到Q=I,K=I,V=I
将相关性1,1~4,4写作矩阵A,得到A=Q。A经过softmax得到。
最后将b1~b4写作矩阵O,得到O=V。
最后可以得到如下图的矩阵乘法推理公式。其中我们只需要学习得出参数.
Multi-head self-attention
当相关性有多种考虑方式是可以用到multi-head self-attention,如下图,当相关性有两种考虑方式时,每个输入应有两个q,k,v,最终也会计算出两个b。
之后将得到的两个b接起来得到一个b。
有时词组在句子中的位置可能会对词组的含义产生影响,因此用到positional encoding为每个位置设计了一个向量,记作,将加在上,便将位置对词性的影响考虑在内。其中的样子如下图右边所示。
而语音中,一个句子往往很长,因此我们可以用truncated self-attention。该方法并不是考虑一整段话,而是只考虑一个范围。
self-attention也可以用在图像上。CNN就是一种简化版的self-attention,CNN只考虑了一片区域的数据,而self-attention考虑了整个区域。
而双向RNN和self-attention都考虑了整个句子,他们有什么不同呢
双向RNN在处理最后一个输入时很难考虑到第一个输入,除非第一个输入一直存储在memory中。
self-attention考虑到了每一个词汇