Self-attention算法
Posted 所追寻的那座城
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Self-attention算法相关的知识,希望对你有一定的参考价值。
一、Vector Set as Input
1、文字处理:
在文字处理中,我们的input是一个句子(不同的句子或者词汇着不同的长度)我们可以将句子中的每个词汇描绘成一个vector,这样我们将文字的输入转变成输入一个vector set。(不同长短的句子对应的vector的长度不同)
2、One-Hot Encoding(将词汇变成vector的一种编码方式)
我们可以设计一个很长的向量,这个向量包括了这个世界上的所有词汇,其中的每一个维度对应着一个词汇。(如上图所示)
但是这种编码也有一定的缺陷。它所有假设的词汇彼此之间都是相互独立的,在上面几个向量中,Cat跟Dog都是动物所以他们本应该比较相近,但是Cat跟Apple一个是动物一个是植物,他们应该相隔比较远,但是在one-hot encoding中我们无法描述出他们之间的关系。
当然一样有办法去解决这个问题,我们可以使用另一种编码方式:Word Embeding
这种编码方式一样是给每一个词汇一个vector,但是这个vector中都是包括了语义资讯的,上图是将Word Embedding可视化之后的样子,所有的植物可能都聚成一团,所有的动词聚成一团等。我们需要明白Word Embedding就是给每一个词汇一个vector,而每一个句子就是一排长度不一的vector。
3、声音信号处理
一段声音信号其实就是一排信号,我们可以将一段声音信号取一个范围,这个范围就叫做一个Window,我们将这个Window中的资讯描述成一个向量,这个向量就叫做一个Frame,在语音上,我们会把一个vector叫做一个Frane。通常一个Window的长度就是25个Millisecond。
一段25Millisecond里面的语音信号,为了要描述整个声音信号,我们可以把这个Window向右移动10个Millisecond。
在一段声音信号中,我们用一串向量来表示,而因为每个Window往右是平移10个Milisecond,所以在一秒中的声音信号就有100个向量,因此声音信号是一个很复杂的vector set。
4、图(graph)在Social Network中,每一个节点就是一个人,然后节点跟节点之间的edge就是他们之间的关系连接(比如说是不是朋友等)
而每一个节点可以看作是一个向量,我们们可以拿其中的任何一个人的,比方说他的个人信息就可以用一个vector来表示)
因此一个Social Network或者Graph也可以看成由一堆向量组成的。(当然分子的信息,我们也可以用graph描述)
二、What is the output?
1、每一个向量都有一个对应的一个label
举例来说 在文字处理上,假设你今天要做的是POS Tagging,
POS Tagging就是词性标註,你要让机器自动决定每一个词汇它是什么的词性?(它是名词 还是动词 还是形容词等等)
举例来说,你现在看到一个句子,I saw a saw
这个句子意思是:“我看到一个锯子”, 这个第二个saw当名词用的时候,它是锯子,那所以机器要知道,第一个saw是个动词,第二个saw虽然它也是个saw,但它是名词,但是每一个输入的词汇,都要有一个对应的输出的词性
这个任务就是,输入跟输出的长度是一样的Case,这个就是属于第一个类型的输出。
2、一整个Sequence,只需要输出一个Label
Sentiment Analysis(给机器看一段话,它要决定说这段话是正面的还是负面的)
假设你的公司开发了一个产品,这个产品上线了,你想要知道网友的评价怎么样,但是你又不可能一则一则网友的留言都去分析,那我们就可以使用Sentiment Analysis的技术,让机器自动去判读说,当一则评价里面有提到某个产品的时候,它是正面的还是负面的,那你就可以知道你的产品,在网友心中的评价怎么样,这个是Sentiment Analysis给一整个句子,只需要一个Label,那Positive或Negative,那这个就是第二类的输出。
或者是如果是Graph的话呢,今天你可能想要给一个分子,然后要预测说这个分子,比如说它有没有毒性,或者是它的亲水性如何,那这就是给一个Graph 输出一个Label
3、机器自己去决定输出多少个Label(sequence to sequence)
翻译就是sequence to sequence的任务,因为输入输出是不同的语言,它们的词汇的数目本来就不会一样多
或者是语音辨识也是,真正的语音辨识也是一个sequence to sequence的任务,输入一句话,然后输出一段文字,这也是一个sequence to sequence的任务
三、Sequence Labeling(输入跟输出数目一样多的状况)
1、解决sequence to sequence问题的方法
直觉的想法就是我们就拿个Fully-Connected的Network
然后虽然这个输入是一个Sequence,但我们就各个击破,不要管它是不是一个Sequence,把每一个向量,分别输入到Fully-Connected的Network里面,然后Fully-Connected的Network就会给我们输出,那现在看看,你要做的是Regression还是Classification,产生正确的对应的输出,就结束了
那这么做显然有非常大的瑕疵,假设今天是,词性标记的问题,你给机器一个句子,I saw a saw,对Fully-Connected Network来说,后面这一个saw跟前面这个saw完全一模一样,它们是同一个词汇,
既然Fully-Connected的Network输入同一个词汇,它没有理由输出不同的东西
但实际上,你期待第一个saw要输出动词,第二个saw要输出名词,但对Network来说它不可能做到,因為这两个saw 明明是一模一样的,你叫它一个要输出动词,一个要输出名词,它会非常地困惑,完全不知道要怎么处理
为了让Fully-Connected的Network,考虑更多的,比如说上下文的Context的资讯把前后几个向量都串起来,一起丢到Fully-Connected的Network就结束了
所以我们可以给Fully-Connected的Network,一整个Window的资讯,让它可以考虑一些上下文的,跟我现在要考虑的这个向量,相邻的其他向量的资讯
但是这样子的方法还是有极限,真正的问题,但是如果今天我们有某一个任务,不是考虑一个Window就可以解决的,而是要考虑一整个Sequence才能够解决的话,就算是给你Sequence的资讯,你考虑整个Sequence,你可能也很难再做的更好了。
那有人可能会想说这个很容易,我就把Window开大一点,大到可以把整个Sequence盖住就结束了
但是,今天Sequence的长度是有长有短的,我们刚才有说,我们输入给我们的Model的Sequence的长度,每次可能都不一样
如果你今天说我真的要开一个Window,把整个Sequence盖住,那你可能要统计一下你的训练资料,然后看看你的训练资料裡面,最长的Sequence有多长,然后开一个Window比最长的Sequence还要长,你才有可能把整个Sequence盖住
但是你开一个这麼大的Window,意味著说你的Fully-Connected的Network,它需要非常多的参数,那可能不只运算量很大,可能还容易Overfitting
这时候我们可以使用Self-Attention,考虑整个Input Sequence的资讯
四、Self-Attention
Self-Attention的运作方式就是,Self-Attention会“吃”一整个Sequence的资讯
然后你Input几个Vector,它就输出几个Vector,比如说你这边Input一个深蓝色的Vector,这边就给你一个另外一个Vector
这边给个浅蓝色,它就给你另外一个Vector,这边输入4个Vector,它就Output 4个Vector
如此一来你这个Fully-Connected的Network,它就不是只考虑一个非常小的范围,或一个小的Window,而是考虑整个Sequence的资讯,再来决定现在应该要输出什么样的结果,这个就是Self-Attention。
Self-Attention不是只能用一次,你可以叠加很多次
可以Self-Attention的输出,通过Fully-Connected Network以后,再做一次Self-Attention,Fully-Connected的Network,再过一次Self-Attention,再重新考虑一次整个Input Sequence的资讯,再丢到另外一个Fully-Connected的Network,最后再得到最终的结果,所以可以把Fully-Connected的Network,跟Self-Attention交替使用:
1、Self-Attention处理整个Sequence的资讯
2、Fully-Connected的Network,专注于处理某一个位置的资讯
3、再用Self-Attention,再把整个Sequence资讯再处理一次
4、然后交替使用Self-Attention跟Fully-Connected
五、Self-Attention过程
Self-Attention的Input,它就是一串的Vector,那这个Vector可能是你整个Network的Input,它也可能是某个Hidden Layer的Output,所以我们这边不是用
x
x
x来表示它,
我们
a
a
a用来表示它,代表它有可能是前面已经做过一些处理,它是某个Hidden Layer的Output,那Input一排a这个向量以后,Self-Attention要Output另外一排
b
b
b这个向量。
那这每一个
b
b
b都是考虑了所有的
a
a
a以后才生成出来的,所以这边刻意画了非常非常多的箭头,告诉你
b
1
b^{1}
b1 考虑了
a
1
a^{1}
a1 到
a
4
a^{4}
a4 产生的,
b
2
b^{2}
b2 考虑
a
1
a^{1}
a1 到
a
4
a^{4}
a4 产生的,
b
3
b
4
b^{3} b^{4}
b3b4 也是一样,考虑整个input的sequence才产生出来的。
那接下来呢就是要跟大家说明,怎么产生
b
1
b^{1}
b1 这个向量
当我们知道怎么产生
b
1
b^{1}
b1 这个向量以后,你就知道怎么产生
b
1
b
2
b
3
b
4
b^{1} b^{2} b^{3} b^{4}
b1b2b3b4 剩下的向量
这里有一个特别的机制,这个机制是根据
a
1
a^{1}
a1 这个向量,找出整个很长的sequence里面,到底哪些部分是重要的,哪些部分跟判断
a
1
a^{1}
a1 是 哪一个 label是有关系的, ,哪些部分是我们要决定
a
1
a^{1}
a1 的class,决定
a
1
a^{1}
a1 的regression数值的时候,所需要用到的资讯。
每一个向量跟的关联的程度,用一个数值叫
α
α
α来表示
这个self-attention的module,怎么自动决定两个向量之间的关联性呢?
你给它两个向量
a
1
a^{1}
a1 跟
a
4
a^{4}
a4, 它怎么决定
a
1
a^{1}
a1 跟
a
4
a^{4}
a4 有多相关,然后给它一个数值
α
α
α,
此时我们需要一个计算attention的模组
这个计算attention的模组,就是拿两个向量作为输入,然后它就直接输出
α
α
α那个数值,
计算这个 α α α的数值有各种不同的做法
1、dot product(比较常见的作法),输入的这两个向量分别乘上两个不同的矩阵,左边这个向量乘上
W
q
W^{q}
Wq 这个矩阵得到矩阵
q
q
q,右边这 个向量乘上
W
k
W^{k}
Wk 这个矩阵得到矩阵
k
k
k,再把
q
q
q 跟
k
k
k 做dot product,就是把他们做element-wise 的相乘,再全部加起来以后就得到一个 scalar,这个scalar就是
a
a
a, 这是一种计算a的 方式
2、Additive,它的计算方法就是,把同样这两个向量通过
W
q
W
k
W^{q} W^{k}
WqWk, 得到
q
q
q 跟
k
k
k,那我们不是把它做Dot-Product,是 把它这个串起来,然后丟到这个过一个Activation Function,然后再通过一个Transform,然后得到
α
α
α**
但是在接下来的讨论里面,我们都只用dot product方法,这也是今日最常用的方法,也是用在Transformer里面的方法
下面我们就要把这边的去跟这边的,分别都去计算他们之间的关联性,也就是计算他们之间的
α
α
α
我们将
a
1
a^{1}
a1 乘上
W
q
W^{q}
Wq 得到
q
1
q^{1}
q1(这个q有一个名字,叫做Query),它就像是你搜寻引擎的时候,去搜寻相关文章的问题就像搜寻相关文章的关键字,所以这边叫做Query Product
然后接下来
a
2
a
3
a
4
a^{2} a^{3} a^{4}
a2a3a4 我们都要去把它乘上W
k
^{k}
k, 得到
k
k
k 这个Vector, k这个Vectora叫做Key,把这个Query q1,跟这个Key k2,算Inner-product就得到
α
α
α
我们这边用
α
1
,
2
\\alpha_{1,2}
α1,2 来代表说,Query是1提供的,Key是2提供的时候这个1跟2他们之间的关联性,这个a这个关联性叫做Attention的Score, 叫做 Attention的分数,
接下来也要跟
a
3
a
4
a^{3} a^{4}
a3a4 来计算
把
a
3
a_{3}
a3 乘上
W
k
W^{k}
Wk, 得到另外一个Key也就是
k
3
,
a
4
k^{3}, a^{4}
k3,a4 乘上
W
k
W^{k}
Wk 得到
k
4
k^{4}
k4,然后你再把
k
3
k^{3}
k3这个Key,跟
q
1
q^{1}
q1 这个Query做 lnner-Product,得到1跟3之间的关联性,得到
α
1
,
3
\\alpha_{1,3}
α1,3,我们把
k
4
k^{4}
k4 跟
q
1
q^{1}
q1 做Dot-Product,得到
α
1
,
4
\\alpha_{1,4}
α1,4, 得到1跟4之间的关联性,其实一般在实做时候,
q
1
q^{1}
q1也会跟自己算关联性,自己跟自己计算关联性这件事情有多重要
计算出,a1跟每一个向量的关联性以后,接下来这边会接入一个Soft-Max 以上是关于Self-attention算法的主要内容,如果未能解决你的问题,请参考以下文章 TensorFlow实现自注意力机制(Self-attention) Transformer自学笔记(李宏毅课:Self-attention+Transformer)
这个Soft-Max跟分类的时候的那个Soft-Max是一模一样的,所以Soft-Max的输出就是一排
α
α