讲完CNN以后,要介绍另一个常用的network架构 – Self-attention。
到目前为止,我们的network的input都是一个向量,那如果输入是一排向量呢?而且向量的数目是会改变的呢?
例如:输入的是一个句子,一段语音,一个图,一个分子。。。
第一个例子是文字处理:
假设我们今天network的输入是一个句子的话,每一个句子长度都不一样,我们model的输入就会是一个Vector set 而且这个vector set的大小每次都不一样(句子的长度不一样)
那怎么把一个词汇表示成一个向量?
最”简单“做法:One-hot Encoding,开一个很长很长的向量,长度跟世界上存在的词汇的数目一样多。但这种方法,有一个非常严重的问题,它假设了所有词汇直接都是没有关系的
另外一个方法:Word Embedding:我们会给每一个词汇一个向量,而这个向量是有语义的资讯。 如果你把Word Embedding画出来的话,你会发现所有的动物可能聚集成一圈,所有的植物可能在一起。Word Embedding会给每一个词汇一个向量,而一个句子就是一排长度不一的向量。
还有什么样的例子,我们需要把一个向量的sequence当做输入呢?
一段声音讯号其实是一排向量,我们会把一段声音讯号取一个范围,这个范围叫window,把window里面的资讯描述成一个向量,把这个向量叫做frame。
为了描述一整段的声音讯号,你会把这个window往右移一点,通常移动的大小是10ms
还有什么东西是一堆向量呢?
一个graph也是一堆向量
我们知道Social Network就是一个graph,每一个节点可以看做一个向量
或者是一个分子
可能的输出:
第一种:每一个向量都有一个对应的label(又叫Sequence Labeling)
第二种:只有一个label
一整个sequence只需要一个label就可以了
第三种:机器自己决定要输出多少个label
这种任务又叫做seq2seq(语音辨识,翻译就是seq2seq的任务,因为输入输出是不用的语言,他们的词汇的数目不会一样多)
为什么需要Self-attention?
每一个向量都有一个对应的label,又叫Sequence Labeling,那怎么解决Sequence Labeling的问题呢?
直觉的想法就是各个击破,把每个向量分别输入到Fully-Connected的Network里面,然后产生输出就结束了。
但这么做显然有非常大的瑕疵,比如上图中的第一个saw 和第二 saw它们是同一个词汇,Fully-Connected的Network会输出相同的结果。但实际上你期待第一个saw要输出动词,第二个saw要输出名词。
为了解决这个问题,我们可以让Fully-Connected的Network考虑更多的向量,比如把前后几个向量都串起来,一起丢到Fully-Connected的Network就结束了。
但是这样的方法还是有极限的
假设我们今天有一个任务,不是考虑一个window就可以解决的,而是要考虑整个sequence才能解决的,怎么办呢?sequence 的长度是有长有短的,我们无法让window的大小大到可以把整个sequence 盖住。而window 越大,也意味着说Fully-Connected 的 Network 它需要非常多的参数。
那有没有更好的办法呢,来考虑整个sequence的资讯呢?Self-attention 这不就来了嘛~
Self-attention运作机制:
Self-attention 会吃一整个sequence 的资讯,你input几个vector 他就输出几个vector。
输出的vector都是考虑一整个sequence 以后才得到的。
在把这个考虑整个句子的向量丢进Fully-Connected 的 Network 然后再来决定说它应该是什么样的东西。
如此一来Fully-Connected 的 Network 它就不是只考虑一个非常小的范围,而是考虑整个sequence的资讯,再来决定现在应该输出什么样的结果。
这就是Self-attention。
Self-attention 不是只能用一次,你可以叠加很多次
Self-attention的输出通过 Fully-Connected 的 Network 以后,得到Fully-Connected 的 Network的输出,这个输出在做一次 Self-attention,在重新考虑一次整个input sequence 的资讯 在丢到另外一个 Fully-Connected 的 Network 最后在得到最终的结果。
就是 Self-attention 处理整个 sequence 的资讯,Fully-Connected 的 Network 专注于处理某一个位置的资讯。
有关Self-attention最知名的paper就是《Attention is all you need》。
Self-attention的input就是一串的vector,这个vector可能是你整个network的input, 也可能是整个Hidden Layer的output。Self-attention 的output是b向量,都是考虑了所有的a以后才生成出来的。
那怎么产生b1向量呢?(b2 及其其他b向量同理)
需要强调的一点是,b1到b4它们并不需要依序产生,是一次同时被计算出来的。
第一个步骤:根据a1找出这个sequence里面跟a1相关的其他向量。
我们知道说今天我们要做Self-attention 目的就是为了要考虑整个sequence,但是我们又不希望把整个sequence 所有的咨询包在一个window里面,所以我们有一个特别的机制,这个机制是根据a1这个向量找出整个sequence里面到底那些部分是重要的。
每一个向量跟a1的关联程度我们用一个数值 α 来表示。
随之而来的问题:Self-attention 的module 怎么自动决定两个向量之间的关联性呢?
那你就需要一个计算attention的模组。
这个模组就是拿两个向量作为输入,然后直接输出数值 α ,即两个向量的关联程度。
关于α 的计算就有多种不同的做法了。
比较常见的做法:Dot-product(下图 左半部分)
在接下来的讨论,我们都采用Dot-product,这也是今天最常用的做法,也是用在Transformer里面的方法。
接下来我们需要计算a1 与a2,a3,a4分别计算他们之间的关联性。
要把a1乘上Wq得到q1,这个q有一个名字叫做Query
a2,a3,a4乘上Wk得k这个vector,k这个vector也有一个名字叫做Key
这个q1 跟这个 k2算inner-product就得到 α ,我们用α1,2代表Query是1提供的 Key是2提供的,1跟2他们之间的关联性,这个α 也有一个名字叫做 attention score
其他参数同理。在实做时,q1也会跟自己算关联性。
我们在做出a1 跟每一个向量的关联性以后,还会做一个soft-max(跟分类时是一样的)。
得到α‘ 以后,我们还要去抽取这个sequence里面重要的资讯。
根据α我们已经知道哪些向量跟a1是最有关系的,接下来我们要根据这个attention的分数,来抽取重要的资讯。
怎么抽取重要的资讯呢?
我们会把a1…a4 每个向量乘上Wv 得到新的向量,用v1…v4来表示。
接下来把v1…v4每一个向量都乘上Attention的分数(α‘),然后再把他们加起来。
我们可以想象到,比如说如果a1跟a2的关联性很强α‘很大,那我们今天得到的b1的值就可能会比较接近v2。
b1 到 b4 是同时被计算出来的。
从矩阵乘法角度再来看一遍Self-attention 运作:
每个a都产生 q k v
下一步:每一个q都会去跟每一个k去计算inner product得到attention分数。
从矩阵角度就是KT 与Q相乘
下一步:乘v向量得到b向量
整个过程:
I 是input ,O是 output 从I到O就是self-attention
整个过程只有Wq,Wk,Wv 是未知的,需要通过我们的训练资料把它找出来。
Self-attention 的进阶版本 : Multi-head Self-attention
我们在做这个 Self-attention 的时候我们就是用q 去找相关的k ,但是相关这件事情有很多种不同的形式,有很多种不同的定义。
所有我们应该要有多个q,不同的q 负责不同种类的相关性。
接下来的操作跟之前一样,只是1那一类的一起做,2那一类的一起做。
目前为止 Self-attention 没有位置的相关信息。
但有时候位置的资讯也许很重要,比如说在做 POS tagging(词性标记)的时候,也许你知道说动词比较不容易出现在句首。
怎么把位置的资讯塞进去呢?
这边就要用到一个positional encoding 的技术。
为每个不同的位置设置一个positional vector ei ,把这个 ei 加到 ai 上就结束了。
Self-attention 在做语音处理时,你讲一句话,这句话所产生的的attention matrix 可能太大,大到你根本就不容易处理。
有一招叫做Truncated Self-attention,它要做的就是我们在做 Self-attention 的时候不要看一整句话,我们只看一个小的范围就好。至于这个范围多大,是人设定的,取决于你对这个问题的理解。
Self-attention 也可以用在图像处理上:
paper链接如下
Self-attention v.s. CNN
CNN可以看做是一种简化版的Self-attention。
因为CNN只考虑receptive field 里面的资讯而在做self-attention的时候我们是考虑整张图片的资讯。
Self-attention 只要设定合适的参数就可以做到跟CNN一模一样的事情。
paper链接:https://arxiv.org/abs/1911.03584
比较flexible 的 model ,需要更多的data ,如果data不够就有可能overfitting;
比较有限制的model,适合在data小的时候,可能比较不会overfitting。
CNN 和 Self-attention 之间就可以看到这种现象。
Self-attention vs RNN
Self-attention 可以平行处理所有的output
RNN 没有办法平行处理所有的output
Self-attention 也可以用在graph上:
Self-attention 的一些变形: