注意力机制原理介绍
1.注意力机制是什么
注意力机制(Attention Mechanism)是深度学习领域中的一种技术,它模仿人类视觉注意力的功能,使模型能够集中于输入数据中最重要的部分。这个概念最初来源于神经科学,后来被引入到机器学习模型中,特别是在自然语言处理(NLP)和计算机视觉领域。
在深度学习模型中,注意力机制允许模型动态地对输入序列的不同部分分配不同的处理权重。这意味着模型可以在处理一个元素时,考虑到序列中其他元素的信息,并且能够根据当前的任务来关注不同的信息。
以下是注意力机制的一些关键特点:
-
选择性聚焦:模型不需要同时处理所有输入信息,而是可以选择性地聚焦于当前任务最相关的部分。
-
上下文建模:注意力机制允许模型在做出决策时考虑全局上下文信息。
-
可解释性:通过分析注意力权重,我们可以了解模型在做出预测时哪些输入信息起到了关键作用,从而提高模型的可解释性。
-
灵活性:注意力机制可以与各种模型结构结合使用,如循环神经网络(RNN)、卷积神经网络(CNN)和变换器(Transformer)。
-
并行处理:与序列处理模型(如RNN)相比,基于注意力机制的模型可以更有效地并行处理序列数据。
注意力机制的一个典型应用是变换器(Transformer)模型,它完全基于注意力机制来处理序列数据,无需传统的循环或卷积结构。在计算机视觉中,注意力机制也被用于图像识别、目标检测和图像分割等任务,帮助模型更好地理解图像内容。
总的来说,注意力机制是深度学习中一个强大的工具,它通过模拟人类的注意力过程来提高模型的性能和适应性。
2.经典注意力机制
2.1用机器翻译任务带你看Attention机制的计算
单独地去讲Attention机制会有些抽象,也有些枯燥,所以我们不妨以机器翻译任务为例,通过讲解Attention机制在机器翻译任务中的应用方式,来了解Attention机制的使用。
什么是机器翻译任务?以中译英为例,机器翻译是将一串中文语句翻译为对应的英文语句,如图1所示。

图1展示了一种经典的机器翻译结构Seq-to-Seq,并且向其中添加了Attention计算。Seq-to-Seq结构包含两个部分:Encoder和Decoder。其中Encoder用于将中文语句进行编码,这些编码后续将提供给Decoder进行使用;Decoder将根据Encoder的数据进行解码。我们还是以图1为例详细解释一下Decoder的解码过程。
更明确的讲,图1展示的是生成单词"machine"时的计算方式。首先将前一个时刻的输出状态 q2q_2q2 和Encoder的输出 h=[h1,h2,h3,h4]h=[h_1,h_2,h_3,h_4]h=[h1,h2,h3,h4] 进行Attention计算,得到一个当前时刻的 contextcontextcontext ,用公式可以这样组织:
[a1,a2,a3,a4]=softmax([s(q2,h1),s(q2,h2),s(q2,h3),s(q2,h4)])context=∑i=14ai⋅hi \begin{align} [a_1,a_2,a_3,a_4] &= softmax([s(q_2, h_1), s(q_2,h_2),s(q_2, h_3),s(q_2, h_4)]) \\ context&=\sum_{i=1}^4 a_i \cdot h_i \end{align} [a1,a2,a3,a4]context=softmax([s(q2,h1),s(q2,h2),s(q2,h3),s(q2,h4)])=i=1∑4ai⋅hi
我们来解释一下,这里的 s(qi,hj)s(q_i,h_j)s(qi,hj) 表示注意力打分函数,它是个标量,其大小描述了当前时刻在这些Encoder的结果上的关注程度,这个函数在后边会展开讨论。然后用softmax对这个结果进行归一化,最后使用加权评价获得当前时刻的上下文向量 contextcontextcontext。这个contextcontextcontext可以解释为:截止到当前已经有了"I love",在此基础上下一个时刻应该更加关注源中文语句的那些内容。这就是关于Attention机制的一个完整计算。
最后,将这个contextcontextcontext和上个时刻的输出"love"进行融合作为当前时刻RNN单元的输入。
图1中采用了继续融合上一步的输出结果,例如上述描述中融合了"love",在有些实现中,并没有融入这个上一步的输出,默认 q2q_2q2 中已经携带了"love"的信息,这也是合理的。
2.2 注意力机制的正式引入
前边我们通过机器翻译任务介绍了Attention机制的整体计算。但是还有点小尾巴没有展开,就是那个注意力打分函数的计算,现在我们将来讨论这个事情。但在讲这个函数之前,我们先来对上边的Attention机制的计算做个总结,图2详细地描述了Attention机制的计算原理。

假设现在我们要对一组输入 H=[h1,h2,h3,...,hn]H=[h_1,h_2,h_3,...,h_n]H=[h1,h2,h3,...,hn]使用Attention机制计算重要的内容,这里往往需要一个查询向量 qqq(这个向量往往和你做的任务有关,比如机器翻译中用到的那个 q2q_2q2 ) ,然后通过一个打分函数计算查询向量 qqq 和每个输入 hih_ihi 之间的相关性,得出一个分数。接下来使用softmax对这些分数进行归一化,归一化后的结果便是查询向量 qqq在各个输入 hih_ihi上的注意力分布 a=[a1,a2,a3,...,an]a=[a_1,a_2,a_3,...,a_n]a=[a1,a2,a3,...,an],其中每一项数值和原始的输入H=[h1,h2,h3,...,hn]H=[h_1,h_2,h_3,...,h_n]H=[h1,h2,h3,...,hn]一一对应。以 aia_iai 为例,相关计算公式如下:
ai=softmax(s(hi,q))=exp(s(hi,q))∑j=1nexp(s(hj,q)) \begin{align}a_i = softmax(s(h_i, q))= \frac {exp(s(h_i,q))} {\sum_{j=1}^n exp(s(h_j, q))} \end{align} ai=softmax(s(hi,q))=∑j=1nexp(s(hj,q))exp(s(hi,q))
最后根据这些注意力分布可以去有选择性的从输入信息 HHH 中提取信息,这里比较常用的信息提取方式,是一种"软性"的信息提取(图2展示的就是一种"软性"注意力),即根据注意力分布对输入信息进行加权求和,最终的这个结果 contextcontextcontext 体现了模型当前应该关注的内容:
context=∑i=1nai⋅hi context = \sum_{i=1}^n a_i \cdot h_i context=i=1∑nai⋅hi
现在我们来解决之前一直没有展开的小尾巴-打分函数,它可以使用以下几种方式来计算:
- 加性模型: s(h,q)=vTtanh(Wh+Uq)s(h, q) = v^Ttanh(Wh+Uq)s(h,q)=vTtanh(Wh+Uq)
- 点积模型: s(h,q)=hTqs(h, q) = h^Tqs(h,q)=hTq
- 缩放点积模型: s(h,q)=hTqDs(h, q) =\frac{ h^Tq}{\sqrt D}s(h,q)=DhTq
- 双线性模型: s(h,q)=hTWqs(h, q) = h^TWqs(h,q)=hTWq
以上公式中的参数 WWW、UUU和vvv均是可学习的参数矩阵或向量,DDD为输入向量的维度。下边我们来分析一下这些分数计算方式的差别。
加性模型引入了可学习的参数,将查询向量 qqq 和原始输入向量 hhh 映射到不同的向量空间后进行计算打分,显然相较于加性模型,点积模型具有更好的计算效率。
另外,当输入向量的维度比较高的时候,点积模型通常有比较大的方差,从而导致Softmax函数的梯度会比较小。因此缩放点积模型通过除以一个平方根项来平滑分数数值,也相当于平滑最终的注意力分布,缓解这个问题。
最后,双线性模型可以重塑为s(hi,q)=hTWq=hT(UTV)q=(Uh)T(Vq)s(h_i, q) = h^TWq=h^T(U^TV)q=(Uh)^T(Vq)s(hi,q)=hTWq=hT(UTV)q=(Uh)T(Vq),即分别对查询向量 qqq 和原始输入向量 hhh进行线性变换之后,再计算点积。相比点积模型,双线性模型在计算相似度时引入了非对称性。
3.注意力机制的一些变体
3.1 硬性注意力机制
在经典注意力机制章节我们使用了一种软性注意力的方式进行Attention机制,它通过注意力分布来加权求和融合各个输入向量。而硬性注意力(Hard Attention)机制则不是采用这种方式,它是根据注意力分布选择输入向量中的一个作为输出。这里有两种选择方式:
- 选择注意力分布中,分数最大的那一项对应的输入向量作为Attention机制的输出。
- 根据注意力分布进行随机采样,采样结果作为Attention机制的输出。
硬性注意力通过以上两种方式选择Attention的输出,这会使得最终的损失函数与注意力分布之间的函数关系不可导,导致无法使用反向传播算法训练模型,硬性注意力通常需要使用强化学习来进行训练。因此,一般深度学习算法会使用软性注意力的方式进行计算,
3.2 键值对注意力机制
假设我们的输入信息不再是前边所提到的H=[h1,h2,h3,...,hn]H=[h_1,h_2,h_3,...,h_n]H=[h1,h2,h3,...,hn] ,而是更为一般的键值对(key-value pair)形式 (K,V)=[(k1,v1),(k2,v2),...,(kn,vn)](K,V)=[(k_1,v_1),(k_2,v_2),...,(k_n,v_n)](K,V)=[(k1,v1),(k2,v2),...,(kn,vn)] ,相关的查询向量仍然为 qqq。这种模式下,一般会使用查询向量 qqq和相应的键 kik_iki进行计算注意力权值 aia_iai。
ai=softmax(s(ki,q))=exp(s(ki,q))∑j=1nexp(s(kj,q)) \begin{align} a_i=softmax(s(k_i,q)) = \frac{exp(s(k_i,q))}{\sum_{j=1}^n exp(s(k_j, q))} \end{align} ai=softmax(s(ki,q))=∑j=1nexp(s(kj,q))exp(s(ki,q))
当计算出在输入数据上的注意力分布之后,利用注意力分布和键值对中的对应值进行加权融合计算:
context=∑i=1nai⋅vi context=\sum_{i=1}^n a_i \cdot v_i context=i=1∑nai⋅vi
显然,当键值相同的情况下k=vk=vk=v,键值对注意力就退化成了普通的经典注意力机制。
3.3 多头注意力机制
多头注意力(Multi-Head Attention)是利用多个查询向量 Q=[q1,q2,...,qm]Q=[q_1,q_2,...,q_m]Q=[q1,q2,...,qm],并行地从输入信息(K,V)=[(k1,v1),(k2,v2),...,(kn,vn)](K,V)=[(k_1,v_1),(k_2,v_2),...,(k_n,v_n)](K,V)=[(k1,v1),(k2,v2),...,(kn,vn)]中选取多组信息。在查询过程中,每个查询向量 qiq_iqi 将会关注输入信息的不同部分,即从不同的角度上去分析当前的输入信息。
假设 aija_{ij}aij代表第 iii 各查询向量 qiq_iqi 与第 jjj 个输入信息 kjk_jkj 的注意力权重, contexticontext_icontexti 代表由查询向量qiq_iqi计算得出的Attention输出向量。其计算方式为:
aij=softmax(s(kj,qi))=exp(s(kj,qi))∑t=1nexp(s(kt,qi))contexti=∑j=1naij⋅vj \begin{align} a_{ij}=softmax(s(k_j,q_i)) &= \frac{exp(s(k_j,q_i))}{\sum_{t=1}^n exp(s(k_t, q_i))} \\ context_i &=\sum_{j=1}^n a_{ij} \cdot v_j \end{align} aij=softmax(s(kj,qi))contexti=∑t=1nexp(s(kt,qi))exp(s(kj,qi))=j=1∑naij⋅vj
最终将所有查询向量的结果进行拼接作为最终的结果:
context=context1⊕context2⊕context3⊕...⊕contextm context=context_1 \oplus context_2 \oplus context_3 \oplus...\oplus context_m context=context1⊕context2⊕context3⊕...⊕contextm
公式里的 ⊕\oplus⊕表示向量拼接操作。
4.自注意力机制
在前边所讲的内容中,我们会使用一个查询向量 qqq 和对应的输入 H=[h1,h2,...,hn]H=[h_1,h_2,...,h_n]H=[h1,h2,...,hn] 进行attention计算,这里的查询向量qqq往往和任务相关,比如基于Seq-to-Seq的机器翻译任务中,这个查询向量qqq可以是Decoder端前个时刻的输出状态向量,如图3所示。

然而在自注意力机制(self-Attention)中,这里的查询向量也可以使用输入信息进行生成,而不是选择一个上述任务相关的查询向量。相当于模型读到输入信息后,根据输入信息本身决定当前最重要的信息。
自注意力机制往往采用查询-键-值(Query-Key-Value)的模式,不妨以BERT中的自注意力机制展开讨论,如图4所示。

在图4中,输入信息H=[h1,h2]H=[h_1,h_2]H=[h1,h2],其中蓝色矩阵中每行代表对应一个输入向量,另外图2中有 $W_q,W_k,W_v$3个矩阵,它们负责将输入信息 HHH 依次转换到对应的查询空间 Q=[q1,q2]Q=[q_1,q_2]Q=[q1,q2] ,键空间 K=[k1,k2K=[k_1,k_2K=[k1,k2和值空间V=[v1,v2]V=[v_1,v_2]V=[v1,v2] :
[q1=h1Wqq2=h2Wq]⇒Q=HWq \left[ \begin{matrix} q_1 = h_1W_q \\ q_2=h_2W_q \end{matrix} \right] \Rightarrow Q=HW_q [q1=h1Wqq2=h2Wq]⇒Q=HWq
[k1=h1Wkk2=h2Wk]⇒K=HWk \left[ \begin{matrix} k_1 = h_1W_k \\ k_2=h_2W_k \end{matrix} \right] \Rightarrow K=HW_k [k1=h1Wkk2=h2Wk]⇒K=HWk
[v1=h1Wvv2=h2Wv]⇒V=HWv \left[ \begin{matrix} v_1 = h_1W_v \\ v_2=h_2W_v \end{matrix} \right] \Rightarrow V=HW_v [v1=h1Wvv2=h2Wv]⇒V=HWv
在获得输入信息在不同空间的表达 QQQ 、 KKK 和 VVV 后,这里不妨以 h1h_1h1 这个为例,去计算这个位置的一个attention输出向量 context1context_1context1 ,它代表在这个位置模型应该重点关注的内容,如图5所示。

可以看到在获得原始输入 HHH 在查询空间、键空间和值空间的表达 QQQ 、 KKK 和 VVV 后,计算 q1q_1q1 在 h1h_1h1 和 h2h_2h2 的分数 s11s_{11}s11 和 s12s_{12}s12 ,这里的分数计算采用的是点积操作。然后将分数进行缩放并使用softmax进行归一化,获得在h1h_1h1这个位置的注意力分布: a11a_{11}a11 和 a12a_{12}a12,它们代表模型当前在h1h_1h1这个位置需要对输入信息h1h_1h1和 h2h_2h2的关注程度。最后根据该位置的注意力分布对 v1v_1v1和 v2v_2v2进行加权平均获得最终h1h_1h1这个位置的Attention向量 context1context_1context1 。
同理,你可以获得第2个位置的Attention向量 context2context_2context2,或者继续扩展输入序列获得更多的 contexticontext_icontexti,原理都是一样的。
讨论到这里,相信你已经知道什么是注意力机制了,但是为了正式一点,我们还是重新组织一下注意力机制的计算过程。
假设当前有输入信息H=[h1,h2,...,hn]H=[h_1,h_2,...,h_n]H=[h1,h2,...,hn],我们需要使用自注意力机制获取每个位置的输出context=[context1,context2,...,contextn]context=[context_1, context_2,...,context_n]context=[context1,context2,...,contextn]。
首先,需要将原始输入映射到查询空间QQQ、键空间KKK和值空间VVV,相关计算公式如下:
Q=HWq=[q1,q2,...,qn]K=HWk=[k1,k2,...,kn]V=HWv=[v1,v2,...,vn] Q=HW_q =[q_1,q_2,...,q_n] \\ K=HW_k =[k_1,k_2,...,k_n]\\ V=HW_v =[v_1,v_2,...,v_n] Q=HWq=[q1,q2,...,qn]K=HWk=[k1,k2,...,kn]V=HWv=[v1,v2,...,vn]
接下来,我们将去计算每个位置的注意力分布,并且将相应结果进行加权求和:
contexti=∑j=1nsoftmax(s(qi,kj))⋅vj context_i=\sum_{j=1}^n softmax(s(q_i, k_j)) \cdot v_j contexti=j=1∑nsoftmax(s(qi,kj))⋅vj
其中 s(qi,kj)s(q_i,k_j)s(qi,kj)是经过上述点积、缩放后分数值。
最后,为了加快计算效率,这里其实可以使用矩阵计算的方式,一次性计算出所有位置的的Attention输出向量:
context=softmax(QKTDk)V context=softmax(\frac{QK^T}{\sqrt{D_k}})V context=softmax(DkQKT)V
恭喜,看到这里相信你已经非常清楚自注意力机制的原理了。
更多推荐
所有评论(0)