深度学习(8)Self Attention*-p1

 一、李宏毅-Self Attention自注意力机制 - p1

相关性查询(q, k)-softmax - 乘上v

视频链接:https://www.bilibili.com/video/BV1JK4y1D7Wb?p=26&vd_source=29387dc08d18f642078183a6816e93e8

跟自己计算关联性重要吗?

为什么用softmax?relu也行

到目前为止,我们的Network的Input都是一个向量,不管是在预测这个,YouTube观看人数的问题上啊,还是影像处理上啊,我们的输入都可以看作是一个向量,然后我们的输出,可能是一个数值,这个是Regression,可能是一个类别,这是Classification

1.1 What is the output?

我们刚才已经看说输入是一堆向量,它可以是文字,可以是语音,可以是Graph,那这个时候,我们有可能有什么样的输出呢,有三种可能性。

1.1.1 每一个向量都有一个对应的Label

当你的模型,看到输入是四个向量的时候,它就要输出四个Label,而每一个Label,它可能是一个数值,那就是Regression的问题,如果每个Label是一个Class,那就是一个Classification的问题。

image-20220612171420908

举例来说 在文字处理上,假设你今天要做的是==POS Tagging==,POS Tagging就是词性标註,你要让机器自动决定每一个词汇 它是什么样的词性,它是名词 还是动词 还是形容词等等。

这个任务啊,其实并没有很容易,举例来说,你现在看到一个句子,I saw a saw。这并不是打错,并不是“我看一个看”,而是“我看到一个锯子”,这个第二个saw当名词用的时候,它是锯子,那所以机器要知道,第一个saw是个动词,第二个saw虽然它也是个saw,但它是名词,但是每一个输入的词汇,都要有一个对应的输出的词性。

1.1.2 一整个Sequence,只需要输出一个Label

image-20220612171433616

举例来说,如果是文字的话,我们就说Sentiment Analysis。Sentiment Analysis就是给机器看一段话,它要决定说这段话是正面的还是负面的

那你可以想像说这种应用很有用,假设你的公司开发了一个产品,这个产品上线了,你想要知道网友的评价怎么样,但是你又不可能一则一则网友的留言都去分析,那也许你就可以用这种,Sentiment Analysis的技术,让机器自动去判读说,当一则贴文里面有提到某个产品的时候,它是正面的 还是负面的,那你就可以知道你的产品,在网友心中的评价怎么样,这个是Sentiment Analysis给一整个句子,只需要一个Label,那Positive或Negative,那这个就是第二类的输出。

那如果是语音的例子的话呢,在作业四里面我们会做语者辨认,机器要听一段声音,然后决定他是谁讲的。或者是如果是Graph的话呢,今天你可能想要给一个分子,然后要预测说这个分子,比如说它有没有毒性,或者是它的亲水性如何,那这就是给一个Graph 输出一个Label。

1.1.3 机器要自己决定,应该要输出多少个Label

我们不知道应该输出多少个Label,机器要自己决定,应该要输出多少个Label,可能你输入是N个向量,输出可能是N'个Label,为什么是N',机器自己决定。

image-20220612171446043

这种任务又叫做==sequence to sequence==的任务,那我们在作业五会有sequence to sequence的作业,所以这个之后我们还会再讲

  • 翻译就是sequence to sequence的任务,因为输入输出是不同的语言,它们的词汇的数目本来就不会一样多
  • 或者是语音辨识也是,真正的语音辨识也是一个sequence to sequence的任务,输入一句话,然后输出一段文字,这也是一个sequence to sequence的任务

第二种类型有作业四,感兴趣可以去看看作业四的程式,那因为上课时间有限,所以上课,我们今天就先只讲第一个类型,也就是输入跟输出数目一样多的状况。

1.2 Sequence Labeling

那这种输入跟输出数目一样多的状况又叫做Sequence Labeling,你要给Sequence里面的每一个向量,都给它一个Label,那要怎么解Sequence Labeling的问题呢?那直觉的想法就是我们就拿个Fully-Connected的Network

然后虽然这个输入是一个Sequence,但我们就各个击破,不要管它是不是一个Sequence,把每一个向量,分别输入到Fully-Connected的Network里面,然后Fully-Connected的Network就会给我们输出,那现在看看,你要做的是Regression还是Classification,产生正确的对应的输出,就结束了,

那这么做显然有非常大的瑕疵,假设今天是,词性标记的问题,你给机器一个句子,I saw a saw,对Fully-Connected Network来说,后面这一个saw跟前面这个saw完全一模一样,它们是同一个词汇啊。

方案一:Window

既然Fully-Connected的Network输入同一个词汇,它没有理由输出不同的东西。但实际上,你期待第一个saw要输出动词,第二个saw要输出名词,但对Network来说它不可能做到,因为这两个saw 明明是一模一样的,你叫它一个要输出动词,一个要输出名词,它会非常地困惑,完全不知道要怎么处理。所以怎么办,有没有可能让Fully-Connected的Network,考虑更多的,比如说上下文的Context的资讯呢。这是有可能的,你就把前后几个向量都串起来,一起丢到Fully-Connected的Network就结束了

所以我们可以给Fully-Connected的Network,一整个Window的资讯,让它可以考虑一些上下文的,跟我现在要考虑的这个向量,相邻的其他向量的资讯。把Window开大一点啊,大到可以把整个Sequence盖住就结束了。

如果你今天说我真的要开一个Window,把整个Sequence盖住,那你可能要统计一下你的训练资料,然后看看你的训练资料里面,最长的Sequence有多长,然后开一个Window比最长的Sequence还要长,你才有可能把整个Sequence盖住但是你开一个这么大的Window,意味著说你的Fully-Connected的Network,它需要非常多的参数,那可能不只运算量很大,可能还容易Overfitting

方案二:self-attention

Self-Attention的运作方式就是,Self-Attention会吃一整个Sequence的资讯

image-20220613211233215

然后你Input几个Vector,它就输出几个Vector,比如说你这边Input一个深蓝色的Vector,这边就给你一个另外一个Vector。这边给个浅蓝色,它就给你另外一个Vector,这边输入4个Vector,它就Output 4个Vector。那这4个Vector有什么特别的地方呢,这4个Vector,他们都是考虑一整个Sequence以后才得到的,那等一下我会讲说Self-Attention,怎么考虑一整个Sequence的资讯。

如此一来你这个Fully-Connected的Network,它就不是只考虑一个非常小的范围,或一个小的Window,而是考虑整个Sequence的资讯,再来决定现在应该要输出什么样的结果,这个就是Self-AttentionSelf-Attention不是只能用一次,你可以叠加很多次

image-20220613211415203

可以Self-Attention的输出,通过Fully-Connected Network以后,再做一次Self-Attention,Fully-Connected的Network,再过一次Self-Attention,再重新考虑一次整个Input Sequence的资讯,再丢到另外一个Fully-Connected的Network,最后再得到最终的结果。

所以可以把Fully-Connected的Network,跟Self-Attention交替使用

  • Self-Attention处理整个Sequence的资讯
  • Fully-Connected的Network,专注于处理某一个位置的资讯
  • 再用Self-Attention,再把整个Sequence资讯再处理一次
  • 然后交替使用Self-Attention跟Fully-Connected

有关Self-Attention,最知名的相关的文章,就是《Attention is all you need》.那在这篇Paper里面呢,Google提出了==Transformer==这样的Network架构,那Transformer就是变形金刚,所以提到这个Network的时候呢,我们就会有变形金刚这个形象。

image-20220613211500443

Transformer我们今天还不会讲到,但我们之后会讲到,Transformer里面一个最重要的Module就是Self-Attention,它就是变形金刚的火种源。那这篇Paper最厉害的地方,就是它有一个霸气的名字Attention is all you need.

那其实像Self-Attention这样的架构,最早我并不会说它是出现在《Attention is all you need》这样的Paper,因为其实很多更早的Paper,就有提出过类似的架构,只是不见得叫做Self-Attention,比如说叫做Self-Matching,或者是叫别的名字,不过呢是Attention is all you need.这篇Paper,把Self-Attention这个Module,把它发扬光大。

1.3 Self-Attention过程

Self-Attention的Input,它就是一串的Vector,那这个Vector可能是你整个Network的Input,它也可能是某个Hidden Layer的Output,所以我们这边不是用\(x\)来表示它,用\(a\)来表示它。

image-20220613211620957

我们用\(a\)来表示它,代表它有可能是前面已经做过一些处理,它是某个Hidden Layer的Output,那Input一排a这个向量以后,Self-Attention要Output另外一排b这个向量。那这每一个b都是考虑了所有的a以后才生成出来的,所以这边刻意画了非常非常多的箭头,告诉你$b^1 \(考虑了\)a1\(到\)a4\(产生的,\)b2\(考虑\)a1\(到\)a4\(产生的,\)b3 b^4$也是一样,考虑整个input的sequence,才产生出来的。

那接下来呢就是要跟大家说明,怎么产生\(b^1\)这个向量,那你知道怎么产生\(b^1\)这个向量以后,你就知道怎么产生剩下\(b^1 b^2 b^3 b^4\)剩下的向量。

这里有一个特别的机制,这个机制是根据\(a^1\)这个向量,找出整个很长的sequence里面,到底哪些部分是重要的,哪些部分跟判断\(a^1\)是哪一个label是有关系的,哪些部分是我们要决定\(a^1\)的class,决定\(a^1\)的regression数值的时候,所需要用到的资讯

image-20220613212112611

每一个向量跟\(a^1\)的关联的程度,用一个数值叫α来表示,这个self-attention的module,怎么自动决定两个向量之间的关联性呢,你给它两个向量\(a^1\)\(a^4\),它怎么决定\(a^1\)\(a^4\)有多相关,然后给它一个数值α呢,那这边呢你就需要一个计算attention的模组

image-20220613212206065

这个计算attention的模组,就是拿两个向量作为输入,然后它就直接输出α那个数值,计算这个α的数值有各种不同的做法:

  • ==dot product==:输入的这两个向量分别乘上两个不同的矩阵,左边这个向量乘上\(W^q\)这个矩阵得到矩阵\(q\),右边这个向量乘上\(W^k\)这个矩阵得到矩阵\(k\)

    再把\(q\)\(k\)做dot product,就是把他们做element-wise 的相乘,再全部加起来以后就得到一个 scalar,这个scalar就是α,这是一种计算α的方式

  • ==Additive==:把同样这两个向量通过\(W^q\) \(W^k\),得到\(q\)\(k\),那我们不是把它做Dot-Product,是把它这个串起来,然后丢到这个过一个Activation Function,然后再通过一个Transform,然后得到α。

总之有非常多不同的方法,可以计算Attention,可以计算这个α的数值,可以计算这个关联的程度,但是在接下来的讨论里面,我们都只用左边这个方法,这也是今日最常用的方法,也是用在Transformer里面的方法。那你就要把这边的\(a^1\)去跟这边的\(a^2 a^3 a^4\),分别都去计算他们之间的关联性,也就是计算他们之间的α。

image-20220613212357947

你把\(a^1\)乘上$W^q \(得到\)q^1$,那这个q有一个名字,我们叫做==Query==,它就像是你搜寻引擎的时候,去搜寻相关文章的问题,就像搜寻相关文章的关键字,所以这边叫做Query。

然后接下来呢,\(a^2 a^3 a^4\)你都要去把它乘上\(W^k\),得到\(k\)这个Vector,\(k\)这个Vector叫做==Key==,那你把这个 Query q1,跟这个Key k2,算 Inner-Product就得到 α‘ (注意力矩阵)我们这边用\(α_{1,2}\)来代表说,Query是1提供的,Key是2提供的时候,这个1跟2他们之间的关联性,这个α这个关联性叫做==Attention的Score==,叫做Attention的分数。

接下来也要跟\(a^3 a^4\)来计算,把\(a_3\)乘上\(W^k\),得到另外一个Key也就是\(k^3\),\(a^4\)乘上\(W^k\)得到\(k^4\),然后你再把\(k^3\)这个Key,跟\(q^1\)这个Query做Inner-Product,得到1跟3之间的关联性,得到1跟3的Attention,你把\(k^4\)\(q^1\)做Dot-Product,得到\(α_{1,4}\),得到1跟4之间的关联性。

image-20220613212536289

其实一般在实作时候,\(q^1\)也会跟自己算关联性,自己跟自己计算关联性这件事情有多重要。计算出,a1跟每一个向量的关联性以后,接下来这边会接入一个Soft-Max

image-20220613221201944

这个Soft-Max跟分类的时候的那个Soft-Max是一模一样的 ,所以Soft-Max的输出就是一排α,所以本来有一排α,通过Soft-Max就得到\(α'\)

这边你不一定要用Soft-Max,用别的替代也没问题,比如说有人尝试过说做个ReLU,这边通通做个ReLU,那结果发现还比Soft-Max好一点,所以这边你不一定要用Soft-Max,这边你要用什么Activation Function都行,你高兴就好,你可以试试看,那Soft-Max是最常见的,那你可以自己试试看,看能不能试出比Soft-Max更好的结果。

接下来得到这个\(α'\)以后,我们就要根据这个\(α'\)去抽取出这个Sequence里面重要的资讯,根据这个α我们已经知道说,哪些向量跟\(a^1\)是最有关系的,怎么抽取重要的资讯呢?

image-20220613221501080

  • 首先把\(a^1\)\(a^4\)这边每一个向量,乘上$W^v \(得到新的向量,这边分别就是用\)v^1 v^2 v^3 v^4$来表示

  • 接下来把这边的\(v^1\)\(v^4\),每一个向量都去乘上Attention的分数,都去乘上\(α'\)

  • 然后再把它加起来,得到\(b^1\)

\[ b^1=\sum_i\alpha'_{1,i}v^i \]

如果某一个向量它得到的分数越高,比如说如果\(a^1\)\(a^2\)的关联性很强,这个\(α'\)得到的值很大,那我们今天在做Weighted Sum以后,得到的\(b^1\)的值,就可能会比较接近\(v^2\),所以谁的那个Attention的分数最大,谁的那个\(v\)就会Dominant你抽出来的结果