Day 28 自注意力(Self-Attention) 机制

我们昨天介绍了 Transformer 的结构,但是并没有介绍到 Transformer 内最神秘的 Self-Attention 层。究竟 Transformer 是怎麽凭藉着 Self-Attention 来对输入序列进行平行运算?又要怎麽做到解决预测结果和关键讯息的位置过於遥远的问题?

PS:接下来介绍的教材来源皆为台大李宏毅教授的网路教学,有兴趣的话可以去听详细内容,相信一定能有所收获。

介绍


由於人类语言具有前後顺序、上下文关系,对於这种时间序列的资料很常使用 RNN 进行处理,像是文章分类、语意分析...等。

但是 RNN 有个问题就是它并不容易被平行运算,假如今天我们输入一个 Sequence https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 ~ https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24 ,而我们想算出 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E4%24 的话,我们就必须先从 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E2%24https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E3%24 → 直到 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24,才能把 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E4%24 算出来

因此有人提出用 CNN 取代 RNN 的方法,一个三角形代表一个 filter,每个 filter 的输入就是 Sequence 的其中一小段,不同的 filter 对应 Sequence 中不同的部分。但是 CNN 需要叠很多层的才能涵盖句子的所有资讯,而且後来的表现也不比 RNN 佳,因此出现了Self-Attention 机制。


Self-Attention 想要做的事情就是取代 RNN 可以做的事情
它的输出/入跟 RNN 一样的,它的最大优势在於:

  1. 可以平行化运算
  2. 每一个输出的向量,都看过整个输入的序列。因此不用像 CNN 那样堆好几层。

运算过程

现在我们假设输入https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 ~ https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24 四个向量,而 Self-Attention 要输出另外一排 b 向量,而每一个 b 都是考虑了所有的 a 以後才生成出来的

要算出 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E1%24 ,第一个步骤是根据 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 找出这个 sequence 里面跟 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 相关的其他向量,而每一个向量跟 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 的关联的程度,我们用一个数值叫 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%24 来表示。

在这里必须先提一下 Self-Attention 机制里面有3个非常重要的值: Query, Key, Value 。分别表示用来匹配的值、被匹配的值、以及抽取出来的资讯。

至於决定两个向量之间的关联性 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%24 最常用的方法就是dot product (内积)。它就是拿两个向量作为输入,分别乘上两个不同的矩阵,左边的向量乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Eq%24 矩阵、右边的向量乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Ek%24 矩阵 ( https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Eq%24 就是 Query 矩阵 ,而 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Ek%24 就是 Key 矩阵,他们的值都是随机初始化後通过训练得到 )

接下来得到 https://chart.googleapis.com/chart?cht=tx&chl=%24q%24https://chart.googleapis.com/chart?cht=tx&chl=%24k%24 这两个向量後再做内积,全部加起来以後就得到一个 scalar (纯量),而这个纯量就是 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%24 ,我们就把它当作两个向量关联的程度。


接下来我们把刚才介绍的套用在 Self-Attention 里面。

  1. 首先将 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E2%24 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E3%24 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24 分别都去计算他们之间的关联性 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%24 。把 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Eq%24 得到 https://chart.googleapis.com/chart?cht=tx&chl=%24q%5E1%24 ,再将 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E2%24 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E3%24 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24 都去乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Ek%24 ,再透过内积计算出 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 跟每一个向量的关联性 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%24
  2. 执行 Soft-Max 函式得到 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24
  3. 得到这个 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24 後,我们就能根据这个 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24 去抽取出这个 Sequence 里面重要的资讯了!


怎麽用 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24 抽取重要的资讯呢?步骤如下:

  1. 先把 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24 ~ https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E4%24 都乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Ev%24 得到新的向量,分别就是用 https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E1%24https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E2%24 https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E3%24 https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E4%24 来表示( https://chart.googleapis.com/chart?cht=tx&chl=%24W%5Ev%24 就是 Value 矩阵)
  2. 接下来把这边的 https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E1%24 ~ https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E4%24 每一个向量都去乘上 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24 後进行相加,就可以得到输出的 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E1%24 了。 (公式写在图片右上角)

如果某一个向量它得到的分数越高,假如说 https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E1%24https://chart.googleapis.com/chart?cht=tx&chl=%24a%5E2%24 的关联性很强、这个 https://chart.googleapis.com/chart?cht=tx&chl=%24%5Calpha%5E%7B'%7D%24 得到的值很大,那我们今天在做权重总和以後得到的 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E1%24 的值就可能会比较接近 https://chart.googleapis.com/chart?cht=tx&chl=%24v%5E2%24

现在,既然我们已经知道如何计算出 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E1%24 ,那麽自然也能根据同样的方法推算出 https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E2%24https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E3%24https://chart.googleapis.com/chart?cht=tx&chl=%24b%5E4%24。 至此,我们已经将 Self-Attention 的内部的计算方式讲解完毕。明天来聊聊使用了 Transformer 中 Encoder 架构的自然语言处理模型 BERT 吧!


<<:  [Day28] HTB Optimum

>>:  [Day28] Security

【Day 08】C 的算数运算子

我们写程序,很多时候是想要用电脑做一些复杂的计算。这时候就会需要用到今天我们要来讲的主角-算数运算子...

Day22 - [丰收款] 以Django Web框架实作永丰API线上支付模拟情境(3) - 两种付款方式实作

昨天使用了Bootstrap5、Vue,打造了我们的付款流程入口页面後,今天要将之前的ATM虚拟帐户...

【从零开始的Swift开发心路历程-Day27】如何在App中播放影片!

今天来教大家要怎麽在App上播放Youtube影片! 我们要用的是WebKitView来达成这个功能...

电子书阅读器上的浏览器 [Day08] 调整网页字型

字型大小 这次的重点是字型。先来说说字型大小。 现在市面上的电子纸设备大大小小各种尺寸都有:从海信...

[DAY-29] 你是谁,比你做什麽更重要

好拉~ 倒数第二天,我就来全部统整复习一下吧! 世界会改变 生命的重要本质 人生大哉问 信仰与理性...