自注意力机制
我们平常输入的数据都是一个向量,但是有时候我们遇到输入是几个向量,比如说声音信号,我们该怎么办呢
我们说一句话,每个单词都是一个向量,我们当然可以创造出一个非常长的向量,它的长度是世界上所有单词的数量,然后是哪个单词,就在对应位置置1,但是这样会造成一个问题,就是我们没有办法让单词间产生联系,比如说我们没有办法让cat和dog产生联系,尽管他们都是动物,所以有了一个word embedding,这个东西能让有相近语义的词汇聚集在附近
一段声音信号其实就是一排向量,我们用一个window来表示一段声音信号,一般表示的是25ms的声音信号,然后这一段就是一个frame,就是一个向量,然后每次移动10ms,我们可以知道每一秒可以产生100个frame,一分钟也就能产生六千个向量
那么,还有其他的输入也是一串向量吗,当然有,比如说:图,每个节点就是一个向量
怎么理解这个图为什么可以这样表示呢,参考分子结构
我们有了输入,那对应的输出是什么
第一种是每一个输入都有对应的输出,比如词性标注
另一个例子是一段输入对应一个输出,比如情感分析(输入一段话,判断这段话是正面的还是负面的)
还有一种可能的输出,就是我们不去决定是什么样的输出,让机器自己决定(seq2seq),比如翻译,或者语音辨识
我们现在讲输入输出一样多的情况,也就是sequence labeling,假如我们在做词性标注,如果只是每一个单词输入进function得到输出,那么i saw a saw这句话中的saw的词性就很难区分,一个是动词看,另一个是名词锯子,只能得到两个词性中的一个,所以我们想要通过上下文去理解,我们可以将这个输入旁边的输入都一起输入进来,也就是输入一个window一样,但是,有些时候,我们得通过全文去理解,可是,我们如果把window设置成所有句子中最长的句子的长度,我们的function就会有很多参数,变得很复杂,但是我们仅仅靠window去移动来覆盖,只能做到局部理解,没有办法做到全文理解
我们可以用self-attention,它可以输入进整个sequence,然后输出对应的值,但是这些值是考虑到整个句子得到的值,然后这些值再作为输入进入function
我们可以将self-attention和fully-connection交替使用
每一个b都是考虑了所有a才得出来的
那是怎么产生b,比如说b1呢,我们输入a1,然后a1要考虑到和它关联性高的其他a,这个关联性叫α
我们怎么得到这个α呢,有两个方法,一个是dot-product,另一个是additive其实都是两个向量乘上矩阵,对结果进行运算,一个是直接相乘,另一个是相加后放到tanh这个activate function中
我们通常是这么运用的,当然,自己还要跟自己算一个attention score,也就是α,然后通过softmax,其实softmax不是必须的,有人用ReLU可以得到更好的结果
接下来,要根据attention score,也就是关联性,来抽取重要的信息,怎么抽取重要的信息呢,我们把输入a都乘上矩阵w,然后再乘上对应的attention score,最后相加得到b,
Self-Attention = 计算输入之间的“相似度”,然后根据这个相似度为“权重”,对输入进行加权求和,得到输出。
因为我们的输入其实是一排向量,输出也是一排向量,其实我们可以用矩阵来表示这一排向量
算attention score是,k矩阵要转置,
最后可得
其实以上的操作都是矩阵运算
其中唯一需要学的参数是wq,wk,wv(需要透过training data找出来的)
接下来,是multi-head self-attention,用多少head是自己调的,我们再self-attention中使用q去找k的,相关这件事有很多不同定义,我们的任务如果很复杂的话,可能需要多个q,每个q对应不同种类的相关性
假设我们要处理的任务是有两种相关性的,我们就用两个head,第一个head和第二个head分开来求,最后拼接成一个矩阵,然后乘上一个矩阵得到结果
我们到目前为止,可以发现我们的self-attention其实并没有体现到位置的信息,对于这个self-attention来说,其实a1跟a4并没有什么区别,因为self-attention对input的操作都是一样的,但是,我们input的sequence的位置信息有时候很重要,比如,词汇标注的时候,因为一个句子的句首,通常不是动词,所以我们的句首单词对动词的关联性应该会低一点,这个时候,我们要引入位置向量,positional vector,这个vector是可以自己动手调的,也可以是从数据中学出来的
self-attention在nlp中的应用很广泛
在语音中也可以用,但是我们知道,语音是作为一段向量输入的,这一段中的一个向量,代表着10ms的语音,所以,这会导致我们平常输入的语音转化为向量时,这个sequence的长度会很长,长度又跟这个matrix有关,所以,这个matrix会很大,matrix大就代表着很复杂
现在我们常用truncated self-attention,其实就是让每一个向量在附近求相关性,这个附近是多近呢,可以自己决定
当然,self-attention也可以用在影像上,我们可以把一张图片看成vector set,把每个pixel看成三维向量
那么self-attention和cnn之间有什么关系呢
我们知道cnn是每一个neuron对应一个receptive field,然后提取特征,这个感受野是我们可以认为设定的,而self-attention,是作用于全局的,可以说cnn是简化版的self-attention,self-attention的receptive field是可以让机器自己学出来的
cnn在data少的时候表现好,self-attention相反,因为cnn弹性小,不容易overfitting
rnn和self-attention有什么关系呢,其实还是有较大联系的,输入都是向量,都考虑到了其他vector(rnn可以双向),但也有区别,就是这些要被考虑的vector,得一直存在内存里,而self-attention则不一样,rnn的输入也不是平行化,无法平行处理输入输出.
在图中,self-attention可以很好运用,因为每一个node中有连线的node,都是有关联性的
self-attention也有缺点,就是运算量很大