美文网首页
李宏毅自然语言处理——Self Attention

李宏毅自然语言处理——Self Attention

作者: 愤怒的可乐 | 来源:发表于2021-07-20 09:13 被阅读0次

    引言

    这是李宏毅老师讲的机器学习视频中与自然语言处理有关的,本文主要关注Self-attention。

    处理序列的模型

    我们已经知道如何处理输入是一个向量的问题。假设我们遇到了更加复杂的问题。比如,输入是一系列向量。

    image-20210719202951901

    并且输入的这一系列向量的长度不是固定的。

    比如,在文字处理的场景中。输入是一个句子,将每个句子的词汇描述成一个向量,这样模型的输入就是一排向量。

    image-20210719203227324

    如何把词汇表示成向量呢,我们知道有one-hot编码。

    image-20210719203306995

    但是这种表示方法不能表示语义信息,并且维度还非常大。另一种表示方法是词嵌入向量。

    image-20210719203402220

    还有图结构也可以是一系列向量。

    image-20210719203607219

    那这些模型的输出是什么?

    有三种类型:

    每个输入的向量都有一个标签,比如词性标注任务。

    image-20210719204104294

    第二种类型是整个序列的输出就是一标签。

    比如情感分类任务、或者是输入一段语言,识别说话者是谁等。

    image-20210719204430046

    最后一种类型就是,我们也不知道有多少个输出,由机器自己决定要输出多少。比如机器翻译任务。

    我们今天关注第一种类型。这种任务又叫序列标注(Sequence Labeling)。

    image-20210719204934142

    我们不能直接用全连接网络(FC)来做,因为全连接网络同样的输入会得到同样的输出。而我们上面的例子中“I saw a saw”,第一个“saw”是动词,第二个“saw”是名词。

    如果能考虑到上下文就好了。这是有可能的,可以设定一个窗口大小,把窗口大小内的输入都串起来,一起丢到FC中。但是窗口大小始终是有限的,如何考虑整个句子呢,难道设定一个巨大的窗口包含整个语句?

    有没有更好的考虑整个序列的模型呢?有,那便是Self-atention!

    Self-attention

    image-20210719205847998

    Self-attention可以接收一整个序列的输入,序列中有多少个输入,它就可以得到多少个输出。

    比如上面输入4个向量到Self-attention中,我们就得到了4个输出向量。这4个输出向量特别之处在于,它们都是考虑了整个序列得到的结果。

    在把这些特别的向量丢给FC之后,再来决定要输出什么样的东西。

    image-20210719205959731

    Self-attention的输出还可以叠加。比如,我们得到考虑整个序列的向量后,喂给FC,得到FC的输出后,再过一次Self-attention,重新考虑FC的所有输出,再丢给另一个FC之后,得到最终的输出,如下图:

    image-20210719210420886

    所以可以把FC和Self-attention交替使用,用Self-attention处理整个序列的信息,FC专注于处理某个位置的信息。

    Attention is all you need.

    Self-attention的原理

    那Self-attention是怎么运作的呢?

    image-20210719210910693

    它的输入就是向量序列,这些向量可能是整个网络的输入,也可能是某个隐藏层的输出。

    再强调一次,每个Self-attention的输出,都是考虑了所有的输入向量才生成出来的。

    下面我们来看一下是如何生成这些向量的。

    image-20210719211107497

    我们重点来看一下是如何产生b^1这个向量的,其他的b^2 \cdots b^4同理。

    ① 我们想要根据a^1找出序列中其他与a^1有关的向量。每个向量与a^1关联程度用一个数值\alpha来表示。第一步要考虑的问题就是,Self-attention模型如何决定两个向量的关联性呢。

    那么就需要一个计算关联性(注意力)的模组。

    image-20210719211610744

    它拿两个向量作为输入,直接输出它们的相关性\alpha数值。如何计算这个数值,就有各种各样的做法。

    常用的做法有使用点乘(Dot product)的方式。

    image-20210719211751184

    点乘的方式做法如下:

    1. 把输入的向量分别乘上两个不同的权重矩阵,分别得到两个向量,记为qk
    2. 然后让q \cdot k就可以得到一个标量,这个标量就作为\alpha数值。

    还有一种叫作Additive的方式:

    image-20210719212058296

    也是乘上两个权重矩阵,得到q,k之后,再拼接起来,然后输入到一个激活函数中,激活函数输出的结果通过矩阵进行线性变换得到\alpha

    我们下面的讨论基于点乘的方式。

    ② 计算a^1和其他向量的关联性。

    image-20210719213328027

    怎么做呢? 先用a^1乘上矩阵W^q得到q^1,这个q^1被称为为query。

    image-20210719213522131

    然后a^2,a^3,a^4乘上W^k分别得到k^2,k^3,k^4,这些k^2,k^3,k^4被称为key。

    image-20210719213737880

    接下来用q^1k^2做点积得到\alpha_{1,2}值,表示a^1a^2之间的关联性,\alpha_{1,2}这种记法说明query是a^1提供的,key是a^2提供的。这个\alpha值还被称为attention score。计算出a^1a^2的关联性后,还要跟a^3,a^4计算一下。

    image-20210719214151441

    计算k^3,k^4的时候也是乘以W^k矩阵得到的,然后再与q^1做点积得到\alpha_{1,3},\alpha_{1,4}

    image-20210719214503507

    实际上,我们还要利用同样的公式计算a^1自己与自己的关联性\alpha_{1,1}

    ③ 计算Softmax

    image-20210719214621651

    我们还要对这些attention score做一个Softmax,得到\alpha_{1,i}^\prime, \quad (i=1,2,3,4),相当于与a^1与各个向量的相关性系数,我们就可以知道哪些向量与a^1相关性比较大。

    ④ 计算最终的b^1

    在计算b^1之前呢,还有一个向量要计算。

    image-20210719215329865

    这个向量就是v向量,把a^1a^4都乘上W^v,得到v^1v^4。这个v可以看成是向量a所携带的信息编码。

    然后与Softmax之后的\alpha^\prime做一个加权求和就得到了b^1

    image-20210719215531474

    假设a^2a^1关联性较大,那么得到的权重系数就很大,在计算b^1时,就会有很大程度的信息来自于v^2,也就是来自于a^2

    下面得到b^2,b^3,b^4是一样的,虽然这里先探讨b^1的产生,其实b^1,b^2,b^3,b^4是可以同时产生的。

    image-20210719230137343

    不过计算b^2时,是以a^2计算的q^2作为query的。同理以a^3得到q^3就可以计算b^3

    刚才我们说是可以同时计算的,是怎么回事呢。其实计算q,k,v无非就是不同的向量与矩阵相乘得到的,如果把这些向量写在一起,写成一个矩阵,不就可以一次得到了吗。

    image-20210719230633080

    a^1,a^2,a^3,a^4拼成一个矩阵I,然后让矩阵W^q乘以它得到矩阵Q,矩阵Q可以分解为q^1,q^2,q^3,q^4

    剩下的K = W^k I,\quad V = W^v I也是同样的道理。

    接下来,计算attention score也可以写成矩阵运算。

    image-20210719231301572

    我们先看q^1,它计算\alpha_{1,1},\alpha_{1,2},\alpha_{1,3},\alpha_{1,4}可以写成矩阵K与向量q^1的乘积。

    image-20210719232058259

    同理不难理解\alpha_{2,1},\alpha_{2,2},\alpha_{2,3},\alpha_{2,4}也可以写成K\cdot q^2

    这样把q^1,q^2,q^3,q^4拼成矩阵Q,然后通过K^T Q得到AA经过Softmax之后就得到了A^\prime矩阵,A^\prime矩阵中每列之和为1A^\prime也被成为Attenion Matrix。

    image-20210719232315344

    接下来看b^1

    image-20210719232902939

    相当于是把v^1,v^2,v^3,v^4组成的矩阵V乘以A^\prime的第一列,就得到了b^1

    image-20210719233109938

    那么用矩阵V乘以A^\prime就可以得到b^1,b^2,b^3,b^4得到的矩阵O

    image-20210719232818576

    总结下来,这一连串的操作,其实就是矩阵的乘法而已。我们用一个图来总结一下。

    image-20210719233317789

    I是Self-attention模型的输入组成的矩阵,W^q,W^k,W^v是三个可以学习的权重矩阵;

    用这三个矩阵乘I分别得到Q,K,V矩阵;

    然后用K矩阵做个转置乘上Q就得到了A,经过Softmax得到A^\prime

    V乘上A^\prime得到最终的输出O

    其中需要学习的参数,就是W^q,W^k,W^v

    Multi-head Self-attention

    Multi-head Self-attention是Self-attention的一个升级版本,Multi-head指的是计算出多个Q,K,V矩阵。

    为什么这样有意义呢? Self-attention是用query去找相关性,但是相关性可能有很多个种类,这时得到多个Q,K,V就分别代表不同种类。多出来的Q,K,V矩阵是怎么计算的呢。

    image-20210719234040696 以2 head为例,我们还是用W^q a^i来得到q^i,然而,此时用这个q^i乘以一个不同的矩阵,得到q^{i,1},q^{i,2}

    同理用k^i,v^i乘上不同的矩阵分别得到k^{i,1},k^{i,2}v^{i,1},v^{i,2}

    然后计算\alphab的时候,把q^{i,1},k^{i,1},v^{i,1}这些第二个上标为1的进行计算,最后得到b^{i,1};上标为2的进行计算,得到b^{i,2}

    image-20210719234420672

    接下来也可以拼接b^{i,1},b^{i,2},然后乘以一个矩阵W^o得到b^i

    Positional Encoding

    现在整个过程看下来,Self-attention少了一个重要的信息,即位置信息。

    我们上面在进行矩阵运算的时候,对于不同的位置的输入,都是同等对待的。没有说像RNN那样后面的输入考虑了前面输入的信息。也没有考虑输入的距离远近。

    本小节介绍的Positional Encoding就是用于解决这个问题的。具体就是为每个位置的输入设置一个独立的位置向量e^i

    image-20210720075343640

    Attention is all you need中用的e^i是下图中的每一列:

    image-20210720075558287

    即每一列代表一个位置向量e^i,这些位置向量e^i是通过sin和cos函数形成一个公式生成的。当然还有其他的生成方法,甚至可以当成一个可以学习的参数。

    image-20210720080033193

    Self-attention的应用

    比较出名的两个就是TransformerBERT

    image-20210720080536933

    这两个家伙常年活跃在自然语言处理领域。

    当然还可以应用在语音和图像上。

    image-20210720080618122 image-20210720080726887

    对于图像来说,把每个位置的输入看成一个3维(rgb)的向量。

    Self-attention vs CNN

    image-20210720081024051

    CNN在做卷积的时候,考虑的是感受野之内的信息,而Selt-attention考虑的是整个输入的信息。

    因此CNN可以看成是一个简化版的Self-attention。

    这样好像是让Self-attention自己去决定感受野的形状是什么样的。

    image-20210720081309703

    Self-attention只要设置合适的参数,就可以做到CNN能做到的事情。

    image-20210720081516079

    Self-attention在数据量大时表现更好,而CNN在小数据量时表现更好。这样不难理解,显然Self-attention比CNN更复杂,需要的数据量显然更多。

    Self-attention vs RNN

    Self-attention和RNN都可以处理序列数据,RNN得到结果时必须按照时间步的顺序(正序或逆序)来生成,利用双向RNN的设计可以考虑整个序列信息。

    image-20210720082041592

    而Self-attention每个输出都也是考虑了整个序列信息。虽然双向RNN也考虑了整个序列信息,但是如果将它俩进行对比,还是可以发现一些不同。

    image-20210720082505122

    比如考虑上面红框框出来的(深蓝色)输入,RNN要考虑这个输入,必须保存到内存中,然后一步一步传递到最后,得到红框框出来的黄色输出。所以是很难考虑到比较远的输入。

    而Self-attention就没有这个问题,只要它们的query和key比较相关,得到的相关性系数较大,不管多远,都能轻易地抽取出信息。

    还有一个重要的不同就是并行化,这影响到训练效率。RNN是不能并行化的,而Self-attention可以。这样Self-attention完胜RNN。

    想要了解更多Self-attention和RNN的关系,可以参考这篇论文☞Transformers are RNNs: Fast Autoregressive Transformers with Linear Attention

    Self-attentioni for Graph

    image-20210720083157317

    Self-attention还可以用在图结构上,图中每个节点看成一个输入,图结构中边的概念,可以看成有关联的向量。可以形成一个稀疏矩阵,其中白色空白区域代表无关联性。

    比如上图节点1和5,6,8相连,所以我们只需要计算它们之间的attenion score。

    Self-attention的变体

    Self-attention有很多种变体,Self-attention最早用在Transformer上面,后来就出来了各种“xxformer”。

    image-20210720083618866

    Long Range Arena: A Benchmark for Efficient Transformers

    Efficient Transformers: A Survey

    相关文章

      网友评论

          本文标题:李宏毅自然语言处理——Self Attention

          本文链接:https://www.haomeiwen.com/subject/qodlmltx.html