直观理解注意力机制
直观理解注意力机制
1. 传统注意力机制中的Q,K,V向量来源
传统的注意力机制在encoder-decoder架构中提出,是decoder在做输出预测的时候,考虑encoder中的输入,而不仅仅考虑当前的状态。这样优化了传统RNN模型随着序列增加信息丢失的问题。
传统注意力机制的QKV来自于跨序列,即K/V来自编码器中的输入向量,Q来自解码器中的输出向量。
具体是怎么来的呢:其实也是来自于3个可训练的线性变换projection,WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV,只是输入来源不同。Q向量来自于解码器当前的隐藏状态hth_tht,K,V向量来自于编码器的输出hjh_jhj。2者分别做线性变换 htWQh_tW^QhtWQ和hjWK,hjWVh_jW^K, h_jW^VhjWK,hjWV,最后得到WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV。
需要注意的是,这里的WQ,WK,WVW^Q, W^K,W^VWQ,WK,WV向量是3个不同的投影矩阵。因为K,V向量的作用不同,前者用于与Q做匹配,后者用于输出,所以需要初始化不同的3个投影矩阵并训练。
2. 传统注意力机制中可训练的 W Q , W K , W V W^Q, W^K, W^V WQ,WK,WV投影矩阵
2.1 输入向量的维度大小
在深入了解可训练的WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV投影矩阵是怎么运作之前,我们先要明确输入向量的维度定义。在语言模型中,一个序列是由多个token组成的,而每个token都可以通过词嵌入的方式表示为一个嵌入向量,即我们的输入向量。而这个词嵌入的模型维度,就是每个token的词向量的维度,常用dmodeld_{\mathrm{model}}dmodel来表示。所以对于一个输入序列 X∈Rn×dmodelX \in \mathbb{R}^{n \times d_{\mathrm{model}}}X∈Rn×dmodel,其中有n个token,每个token的维度是dmodeld_{\mathrm{model}}dmodel。
2.2 Q,K,V向量的获取
为了得到Q,K,V向量,需要对输入向量或者隐藏状态分别乘以3个投影矩阵,WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV。这里投影矩阵尺寸的设计取决于我们对Q,K,V向量尺寸的要求,同时还要考虑的输入向量的尺寸为 Rn×dmodel\mathbb{R}^{n \times d_{\mathrm{model}}}Rn×dmodel。
同时,为了满足缩放点积的计算,即q · k要维度匹配,所以需要:
dq=dkd_q = d_kdq=dk
即Q向量的维度等于K向量的维度,但是V向量的维度没有和谁有特殊的关系。在传统的注意力机制中,只能讲到这些,下面讲解自注意力机制中,Q,K,V向量的来源,WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV投影矩阵尺寸的设计。
3. 自注意力机制
自注意力机制与传统注意力机制的区别在于,原始的Q,K,V向量的输入来源是相同的,即都来源于输入的词向量。具体流程如下:
输入是:X∈Rn×dmodelX \in \mathbb{R}^{n \times d_{\mathrm{model}}}X∈Rn×dmodel
投影矩阵分别是:
WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV
通过如下公式:
XWQ,XWK,XWV,(n×dmodel,dmodel×dk∣dmodel×dv)XW^Q, XW^K,XW^V, (n \times d_{\mathrm{model}}, d_{\mathrm{model}} \times d_k |d_{\mathrm{model}} \times d_v )XWQ,XWK,XWV,(n×dmodel,dmodel×dk∣dmodel×dv)
最终得到Q,K,V向量:
Q∈Rn×dk,K∈Rn×dk,V∈Rn×dvQ \in \mathbb{R}^{n \times {d_k}}, K \in \mathbb{R}^{n \times {d_k}}, V \in \mathbb{R}^{n \times {d_v}}Q∈Rn×dk,K∈Rn×dk,V∈Rn×dv
解释如下:在自注意力中,由于缩放点积计算(QKTQK^TQKT)的需要,我们让Q,K向量的维度相同,即都为dkd_kdk,而V向量的维度则不确定
3.1自注意力机制中的计算
- 在获得了Q,K,V向量之后,便可以计算得到输入的注意力权重:
QKT∈Rn×nQK^T \in \mathbb{R}^{n\times n}QKT∈Rn×n
- 同时为了后续训练的稳定性,还需要除以Q,K向量的维度,即 dkd_kdk ,所以最终的注意力权重就是:
QKTdk∈Rn×n\frac{QK^T}{\sqrt{d_k}} \in \mathbb{R}^{n \times n}dkQKT∈Rn×n
- 同时还需要将原始的注意力权重归一化,使得所有的权重和为1,即用softmax进行归一化:
A=Softmax(QKTdk)∈Rn×nA = Softmax(\frac{QK^T}{\sqrt{d_k}}) \in \mathbb{R}^{n \times n} A=Softmax(dkQKT)∈Rn×n
需要注意的是,这里的归一化是按照Query维度进行归一化。直观理解,Q向量去查询K向量得到了权重矩阵 A∈Rn×nA \in \mathbb{R} ^ {n \times n}A∈Rn×n,这个矩阵的每一行就代表一个token的对其他所有token的权重,都是Q向量中的一行去对整个K向量进行计算得到的,最终得到了n行。因此需要对权重矩阵A的每一行进行 Softmax 操作,这样每一行,即每个token的权重向量都是归一化,和为一的。
- 在得到了归一化后的权重矩阵,只需要让其乘上V向量,便是得到了经过注意力机制重新计算后的输入向量:
output=AV(Rn×n,Rn×dv)∈Rn×dvoutput = AV (\mathbb{R}^{n \times n}, \mathbb{R}^{n \times d_v}) \in \mathbb{R}^{n \times d_v} output=AV(Rn×n,Rn×dv)∈Rn×dv
不难看出,与最原始的输入X相比,其n维度没有变化,依旧代表序列长度,而每个token的维度则是由原来的dmodeld_{\mathrm{model}}dmodel变成了dvd_vdv。
- 后续处理。一般做法还是让dvd_vdv回到原始的输入维度dmodeld_{\mathrm{model}}dmodel,但是呢做法不一样,在《Attention is all you need》原始论文中,作者的做法是引入了一个输出投影矩阵WOW^OWO,通过投影的方式让经过注意力机制变换过的输入维度重新回到原始的嵌入向量的维度,而这也是最常见的做法:
NewOutput=output(Rn×dv)WO(Rdv×dmodel),∈Rn×dmodelNewOutput = output(\mathbb{R}^{n \times d_v}) W^O(\mathbb{R}^{d_v \times d_{\mathrm{model}}}), \in \mathbb{R} ^ {n \times d_{\mathrm{model}}} NewOutput=output(Rn×dv)WO(Rdv×dmodel),∈Rn×dmodel
这种通过投影矩阵还原维度的好处体现在多头注意力机制中,下面看多头注意力机制的讲解。
4. 多头注意力机制
4.1 什么是多头注意力机制
多头注意力指的是:在标准注意力机制基础上,模型不是只用一个 Q/K/V 投影集,而是用多个(h 个)并行的注意力头(每个头有自己的一组Q/K/V,每个头对输入进行注意力计算,最后将各头输出拼接(或整合)起来,再做一次线性变换,得到最终输出。
其实很好理解,原来的一套Q/K/V向量可以被称作一个头,对应着一套输出。现在我们可以多用几个头,来获得不同的输出,这样子做允许模型 并行地在多个“子空间” 或“视角”中学习注意力,这样每一个头可以专注于一种关系类型或一种特征子空间。
4.2 多头注意力机制中的计算
在多头注意力机制中,h是头的数量。有个常用的设定:
dk=dv=dmodel/hd_k = d_v = d_{\mathrm{model}} / h dk=dv=dmodel/h
多头注意力中的投影矩阵(每个头的投影矩阵值是不同的):
WiQ∈Rdmodel×dk,WiK∈Rdmodel×dk,WiV∈Rdmodel×dv,W_i^{Q} \in \mathbb{R}^{d_{\mathrm{model}} \times {d_k}}, W_i^{K} \in \mathbb{R}^{d_{\mathrm{model}} \times {d_k}}, W_i^{V} \in \mathbb{R}^{d_{\mathrm{model}} \times {d_v}}, WiQ∈Rdmodel×dk,WiK∈Rdmodel×dk,WiV∈Rdmodel×dv,
多头注意力中的Q/K/V向量:
Qi=XWiQ∈Rn×dk,Ki=XWiK∈Rn×dk,Vi=XWiV∈Rn×dvQ_i = XW_i^Q \in \mathbb{R}^{n \times d_k}, K_i = XW_i^K \in \mathbb{R}^{n \times d_k}, V_i = XW_i^V \in \mathbb{R}^{n \times d_v} Qi=XWiQ∈Rn×dk,Ki=XWiK∈Rn×dk,Vi=XWiV∈Rn×dv
多头注意力中的输出:
headi=Softmax(QiKiTdk)Vi,∈Rn×dvhead_i = Softmax(\frac{Q_iK_i^T}{\sqrt{d_k}})V_i, \in \mathbb{R}^{n \times d_v} headi=Softmax(dkQiKiT)Vi,∈Rn×dv
拼接多个头的输出(注意,这里的拼接是在特征维度上,即dvd_vdv维度上拼接):
output=Concate(hi),i∈1,2,....,houtput = Concate(h_i), i \in 1, 2, ...., h output=Concate(hi),i∈1,2,....,h
所谓的特征维度上拼接,就是特征维度发生了改变,变成了dv×hd_v \times hdv×h:
output∈Rn×(dv×h)output \in \mathbb{R}^{n \times (d_v \times h)} output∈Rn×(dv×h)
最后得到的输出,是经过输出投影矩阵线性变换过的:
NewOutput=output(Rn×(dv×h))WO(R(dv×h)×dmodel),∈Rn×dmodelNewOutput = output(\mathbb{R}^{n \times (d_v \times h)})W^O(\mathbb{R}^{(d_v \times h) \times d_{\mathrm{model}}}), \in \mathbb{R}^{n \times d_{\mathrm{model}}} NewOutput=output(Rn×(dv×h))WO(R(dv×h)×dmodel),∈Rn×dmodel
