输入n个向量,要输出相同个数的向量(比如,输入一个句子,输出句子中每个词的词性。每个单词转化为向量可以用one-hot vector或者word embedding方法)
如果将每个向量连一个FC(fully connected network),会出现像 I saw a saw这种情况,两个saw单词一样,所以两个FC输出结果也会一样
这时,我们可以在FC之前加一层网络,这个网络要考虑到整个句子,即self-attention
要考虑当前向量和其余向量的相似程度,流程如下
先由某个向量通过运算(其中$W^q,W^k,W^v$为矩阵,需要通过学习得出)来求出对应的query,key和v,将当前向量的query和自己及其余向量的key做点乘,得到的$\alpha$就是原始的相似度,再通过softmax归一化得到了权重$\alpha^\prime$(不一定是softmax,也可以用Relu等,只是一般softmax),最后将对应的权重和系数v相乘再累加,得到了当前向量所对应的输出
从矩阵的角度来看:
还有一种扩展,Multi-head Self-attention,就是每个向量产生出两个q,k,v,第一个q做运算时候都与第一个k做运算,同理,得到第一个输出和第二个输出,在这两个输出线性组合得到最终的输出
总结一下:
- 可以在加上一个和位置有关的参数:Positional Encoding
- 发现 dot-product 做的事情和 CNN 中 filter 对每一个 receptive field 做的事相似,这两者有什么关系?事实上,CNN 是 self-attention 的特殊版,因为 CNN 是对每一个感受野做运算,而 self-attention 实际上是拿每一个序列中的向量和序列中的所有向量做运算,相当于把感受野设置为整个序列。在数据量相对较小的时候,CNN 效果好,数据量极大的时候,self-attention 较好
- self-attention 和 RNN 的关系?比 RNN 更强。首先,RNN 是串行的,无法并行;其次,RNN(双向 RNN 也是)对于头和尾两个元素的相关性没有那么高,但是 self-attention 没有这个问题
- 由于需要更新的是整个矩阵,运算量较大,因此产生了许多其它的变形(如 transformer)。