自注意力机制详解

视频链接:李宏毅 self-attention讲解上
参考文章:RNN详解
     Attention详解
     彻底搞懂Attention机制
     知乎Transformer详解

传统的编码器解码器架构

在这里插入图片描述
一般最简单的编码器-解码器架构都是基于RNN模型的,编码器将输入的序列转换为语义编码C,语义编码C中包含了整个输入序列的信息。
解码器也是采用RNN模型,计算每一时刻的输出 y t y_t yt时,除了上一时刻的输出 y t − 1 y_{t-1} yt1和上一时刻隐藏层的值 h t − 1 h_{t-1} ht1还需要语义编码C。
h t = f ( h t − 1 , y t − 1 , C ) h_t = f(h_{t-1},y_{t-1},C) ht=f(ht1,yt1,C) y t = f ( h t , y t − 1 , C ) y_t = f(h_t,y_{t-1},C) yt=f(ht,yt1,C) h t h_t ht表示当前t时刻的隐藏层的数值, y t − 1 y_{t-1} yt1为上一时刻预测的输出,每个时刻语义编码C都是相同的。

这种编码方法,无法体现对一个句子序列中不同语素的关注程度。在自然语言中,一个句子中的不同部分是有不同含义和重要性的。比如:I hate this movie。如果是做情感分析的应用场景,训练的时候明显应该对hate这个词语做更多的关注。如果采用上述的方法则达不到这种效果。

注意力机制

人类在感知环境的时候(比如看一张图片或者一个句子),大脑让我们能够分清哪部分是重要的,哪部分是次要的,从而聚焦更重要的方面以获得对应的信息。我们在设计神经网络模型的时候,希望模型也具有这样的能力。这就引入了注意力机制。

在计算机算力资源有限的情况下,注意力机制可以将注意力集中在有用的信息上,从而减少了在噪声中花费的时间。
在这里插入图片描述
上图是引入了Attention机制的编码器-解码器架构。此时编码器的输出不再是只有有一个单一的语义编码C。而是具有多个C1,C2,C3这样的编码。在预测Y1的时候,使用C1作为语义编码,在预测Y2的时候,使用C2作为语义编码,这样就模拟了人类的注意力机制。其中 C i C_i Ci就是对序列中的不同语素,赋予不同的权重吗,最后进行加权平均得到的结果,我们称为中间语义表示。Attention机制的关键是将固定的中间语义表示C换成了根据当前输出单词而变换的中间语义表示 C i C_i Ci

中间语义表示

下面我们来介绍一下中间语义表示是如何进行计算的。

注意力机制描述了(序列)元素的加权平均值,其权重是根据输入的query和元素的键值进行动态计算的。具体地,在注意力机制中,有4个概念需要明确。

  • Query:Query(查询)是一个特征向量,描述我们在序列中寻找什么,即我们可能想要注意什么。
  • Keys:每个输入元素有一个键,它也是一个特征向量。该特征向量粗略地描述了该元素“提供”什么,或者它何时可能很重要。键的设计应该使得我们可以根据Query来识别我们想要关注的元素。
  • Values:每个输入元素,我们还有一个值向量。这个向量就是我们想要平均的向量。
  • Score function:评分函数,为了对想要关注的元素进行评分,我们需要指定一个评分函数f。该函数将查询和键作为输入,并输出查询-键对的得分(注意力权重)。它通常通过简单的相似性度量来实现,例如点积。

在这里插入图片描述

a i = exp ⁡ ( f a t t n ( k e y i , q u e r y ) Σ j exp ⁡ ( f a t t n k e y j , q u e r y ) ) out = ∑ i a i ⋅ v a l u e i \begin{aligned}a_i&=\frac{\exp(f_{attn}(key_i,query)}{\Sigma_j\exp(f_{attn}key_j,query))} \\\text{out}&=\sum_ia_i\cdot value_i\end{aligned} aiout=Σjexp(fattnkeyj,query))exp(fattn(keyi,query)=iaivaluei
注意力机制的目的是解码器在进行解码的时候,对输入数据有着不同权重的参考
如图所示,来自于Decoder模块中的查询首先和每个encoder中的键进行点集,得到一个评分函数,该评分函数通过softmax函数得到评分权重,将评分权重和encoder中的值进行相乘得到最终的输出,这个输出也就是我们所说的中间语义表示。

公式化结果

  • 首先利用RNN模型获得序列的隐层状态 h 1 , h 2 , . . . , h n h_1,h_2,...,h_n h1,h2,...,hn
  • 如果当前Decoder阶段已经到达 S i − 1 S_{i-1} Si1需要进行下一个 S i S_i Si的预测了,现在计算每一个输入位置 h j h_j hj对当前位置的影响 e i , j = a ( s i − 1 , h j ) e_{i,j}=a(s_{i-1},h_j) ei,j=a(si1,hj)
  • 对评分函数进行归一化处理,得到评分权重分布 α i j = exp ⁡ ( e i j ) ∑ k = 1 T x exp ⁡ ( e i k ) \alpha_{ij}=\frac{\exp\left(e_{ij}\right)}{\sum_{k=1}^{T_x}\exp\left(e_{ik}\right)} αij=k=1Txexp(eik)exp(eij)
  • 利用评分权重加权求和,得到相应的中间语义表示 c i = ∑ j = 1 T x α i j h j c_i=\sum_{j=1}^{T_x}\alpha_{ij}h_j ci=j=1Txαijhj
  • 计算Decoder中第i个隐藏层的输出 s i = f ( s t − 1 , y t − 1 , C ) s_i =f(s_{t-1},y_{t-1},C) si=f(st1,yt1,C)

编码器中的隐层状态又可以看作是Attention机制的keys和values

Attention模型优缺点

优点

  • 速度快(据说可以在Decoder阶段实现并行化,但是目前没弄懂,t时刻的隐状态需要t-1时刻的隐状态,这样如何并行呢)
  • 效果好:注意力机制能够获取到局部的重要信息,能够抓住重点

缺点

  • Encoder 部分仍然依赖于RNN结构,对于中长距离之间两个词之间的关系没有办法很好的获取

自注意力模块

自注意力机制和传统的注意力机制不同,传统的注意力机制是根据源端和目标端的隐变量计算注意力的,结果是源端的每个词和目标端的每个词之间的依赖关系。

自注意力机制,首先分别在源端和目标端进行自身的注意力,捕捉到其自身的词与词之间的依赖关系,之后将源端得到的自注意力加到目标端中的attention机制中,称为Cross-Attention,以捕获源端和目标端词与词之间的依赖关系。

在这里插入图片描述

按照Transformer论文计算自注意力机制的流程

  • 将输入单词转换为嵌入向量 a i a^i ai
  • 根据嵌入向量与权重参数 W q , W k , W v W^q,W^k,W^v Wq,Wk,Wv 相乘得到𝑞,𝑘,𝑣三个向量
  • 为每个向量计算一个分数: a i , j = q i ⋅ k j a_{i,j}=q_i\cdot k_j ai,j=qikj
  • 归一化处理 a i , j ′ = s o f t m a x ( q i ⋅ k j d ) a_{i,j}^\prime=softmax(\frac{q_i\cdot k_j}{\sqrt d}) ai,j=softmax(d qikj)
  • v a l u e value value进行点乘,得到加权的每个输入向量的评分 v v v
  • 相加后得到最终的输出结果𝑧=∑𝑣

self-attention 通过 Q ∗ K Q*K QK得到词与词之间的相关性矩阵,然后根据此相关性与V进行加权求和,这样最终输出的向量主要就是与之相似的词的向量构成的,与之不相似的向量对其的贡献度可以忽略不计。(数值很小,几乎可以忽略不计
最终计算出来的向量就会变成,如果两个词很相似,那么向量的相似度也很近,就起到了语义层面的意义,这样词与词之间就因语义的不同而自动区分开来了。

自注意力模块的复杂度计算

这里只考虑在self-attention机制下一层的计算复杂度。(越学到后面发现就需要考虑这些问题,所以在这里也记录一下吧)

单个矩阵相乘的计算复杂度
针对于维度为 ( m ∗ n ) (m*n) (mn)的矩阵A,维度为 ( n ∗ p ) (n*p) (np)的矩阵B,两者相乘得到维度为 ( m ∗ p ) (m*p) (mp)的矩阵C
对于结果矩阵C中的每个元素,我们需要计算矩阵A中的一行和矩阵B中的一列的点积,这个点积涉及到对应元素的乘积和求和。
上述对于矩阵C中的每个元素,需要执行n次乘法运算和n-1加法运算,同时C中有m x p个元素,因此所需要的总操作数为 ( m ∗ p ∗ ( 2 n − 1 ) ) (m*p*(2n-1)) (mp(2n1))。为了表述简单,矩阵乘法的总体复杂度为 O ( m ∗ n ∗ p ) O(m*n*p) O(mnp)

自注意力机制的复杂度计算
假设 Q , K , V Q,K,V Q,K,V的维度大小相同为 [ N , d ] [N,d] [N,d]

  • 计算 Q K T QK^T QKT
    [ N , d ] ∗ [ d , N ] − > [ N , N ] [N,d]*[d,N]->[N,N] [N,d][d,N]>[N,N],此时计算量为 2 N 2 d 2N^2d 2N2d
  • 计算score*V
    [ N , N ] ∗ [ N , d ] − > [ N , d ] [N,N]*[N,d]->[N,d] [N,N][N,d]>[N,d],此时计算量为 2 N 2 d 2N^2d 2N2d

因此总的计算复杂度可以简化为 O ( N 2 d ) O(N^2d) O(N2d)

多头自注意力机制

由于每个向量可能会有不同的相关性,可以利用 q q q去寻找不同的相关性。得到不同相关性的输出。
在这里插入图片描述

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值