文章目录
1. 自注意力机制概述
有时候我们期望网络能够看到全局,但是又要聚焦到重点信息上。比如在在做自然语言处理时,句子中的一个词往往不是独立的,和它上下文相关,但是和上下文中不同的词的相关性是不同的,所以我们在处理这个词时,在看到它的上下文的同时也要更加聚焦与它相关性更高的词,这就要用到常说的自注意力机制。比如下面这两幅图,通过自注意力机制处理后,计算出了词间的相关性,可以看到第一个图的it与animal的相关性很强,第二个图it与street的相关性很强。那么如何实现自注意力机制呢?
2. 向量相关性计算
自注意力机制的核心是捕捉向量之间的相关性。比如下面这幅图,输出一个向量
b
1
b^1
b1不只看
a
1
a^1
a1本身,还要看
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4,但是看它们的程度不一样。这就需要分别计算
a
1
a^1
a1与
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4之间的相关性
α
\alpha
α,
α
\alpha
α越大,相关性越高,给予的重视程度就越高。那么如何让网络自动计算出两个向量之间的相关性呢?
计算两个向量之间的相关性的常见方法是求点积(dot-product),如下图所示。具体的做法是左边的向量乘以一个变换矩阵
W
q
W^q
Wq得到向量
q
q
q,右边的向量乘以一个变换矩阵
W
k
W^k
Wk得到向量
k
k
k,然后将向量
q
q
q和向量
k
k
k点积就可以得到相关性
α
\alpha
α。由点积的性质可知,两个向量的相似度越高,点积的值就会越大。当然,计算向量相关性的方法不只点积这一种,也有其他方式,但是点积这种是最常见的。
基于点积计算,我们就可以向量两两之间的关联性了,比如首先分别计算
a
1
a^1
a1与
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4之间的相关性。我们首先将
a
1
a^1
a1乘以变换矩阵
W
q
W^q
Wq得到向量
q
1
q^1
q1,这里的
q
1
q^1
q1向量有个专门的名字,叫做 “query” 。然后将
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4分别乘以变换矩阵
W
k
W^k
Wk得到向量
k
1
,
k
2
,
k
3
,
k
4
k^1,k^2,k^3,k^4
k1,k2,k3,k4,这里的
k
i
k^i
ki向量也有个专门的名字,叫做 “key”。然后将
q
1
q^1
q1和这四个key分别做点积,就得到四个相关性数值
α
1
,
1
,
α
1
,
2
,
α
1
,
3
,
α
1
,
4
\alpha_{1,1},\alpha_{1,2},\alpha_{1,3},\alpha_{1,4}
α1,1,α1,2,α1,3,α1,4。求出这四个相关性的值后,然后通过一个Soft-max层进行归一化,得到
α
1
,
1
′
,
α
1
,
2
′
,
α
1
,
3
′
,
α
1
,
4
′
\alpha^{'}_{1,1},\alpha^{'}_{1,2},\alpha^{'}_{1,3},\alpha^{'}_{1,4}
α1,1′,α1,2′,α1,3′,α1,4′,这是最后输出的相关性值,我们将这些值又称为**“注意力分数”**。现在我们得到了
a
1
a^1
a1对
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4之间的注意力分数,那么如何做到考虑全局又聚焦重点呢?
3. 基于注意力分数抽取向量信息
通过上面计算出的注意力分数
α
1
,
1
′
,
α
1
,
2
′
,
α
1
,
3
′
,
α
1
,
4
′
\alpha^{'}_{1,1},\alpha^{'}_{1,2},\alpha^{'}_{1,3},\alpha^{'}_{1,4}
α1,1′,α1,2′,α1,3′,α1,4′,我们已经知道
a
1
a^1
a1要给予
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4的关注程度了,接下来我们抽取这些向量中重要的信息以输出
b
1
b^1
b1了。具体的做法如下图所示。首先我们再将
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4乘以一个新的变换矩阵
W
v
W^v
Wv得到向量
v
1
,
v
2
,
v
3
,
v
4
v^1,v^2,v^3,v^4
v1,v2,v3,v4,这里的
v
i
v^i
vi向量也有个专门的名字,叫做 “value”。然后将向量
v
1
,
v
2
,
v
3
,
v
4
v^1,v^2,v^3,v^4
v1,v2,v3,v4分别乘以对应的注意力分数
α
1
,
1
′
,
α
1
,
2
′
,
α
1
,
3
′
,
α
1
,
4
′
\alpha^{'}_{1,1},\alpha^{'}_{1,2},\alpha^{'}_{1,3},\alpha^{'}_{1,4}
α1,1′,α1,2′,α1,3′,α1,4′,并进行求和,输出向量
b
1
b^1
b1。从这里可以看出,所有向量都有参与计算,这样就做到了看全局。但是各向量参与计算的程度不一样,
α
1
,
i
′
\alpha^{'}_{1,i}
α1,i′就相当权重值,权重值越大的,对应向量参与计算的程度就越大,最后得到的输出向量
b
1
b^1
b1就和该向量越相似。这样就做到了看全局又聚焦重点。通过上述同样的计算方式,也可以计算得到
b
2
,
b
3
,
b
4
b^2,b^3,b^4
b2,b3,b4,而且
b
1
,
b
2
,
b
3
,
b
4
b^1,b^2,b^3,b^4
b1,b2,b3,b4是可以并行计算的。以上就是自注意力机制的全部了,但是对自注意力机制的解析并没有结束,下面从矩阵计算的角度来看自注意力机制。
4. 自注意力机制中的矩阵计算
4.1 计算矩阵 K 、 V 、 Q K、V、Q K、V、Q
前面提到将
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4分别乘以变换矩阵
W
k
W^k
Wk得到向量
k
1
,
k
2
,
k
3
,
k
4
k^1,k^2,k^3,k^4
k1,k2,k3,k4。我们将输入向量
a
1
a^1
a1、
a
2
a^2
a2、
a
3
a^3
a3、
a
4
a^4
a4拼在一起,得到一个矩阵用
I
I
I表示,即,
I
=
[
a
1
a
2
a
3
a
4
]
I=[a^1a^2a^3a^4]
I=[a1a2a3a4]将key向量
k
1
k^1
k1、
k
2
k^2
k2、
k
3
k^3
k3、
k
4
k^4
k4拼在一起得到一个矩阵用
K
K
K表示,即,
K
=
[
k
1
k
2
k
3
k
4
]
K=[k^1k^2k^3k^4]
K=[k1k2k3k4]用矩阵相乘表示
K
K
K矩阵的计算过程即,
K
=
W
k
I
K=W^kI
K=WkI同理,query向量拼成的矩阵
Q
Q
Q等于,
Q
=
W
q
I
Q=W^qI
Q=WqIvalue向量拼成的矩阵
V
V
V等于,
V
=
W
v
I
V=W^vI
V=WvI。下图展示了上述计算过程。
4.2 计算注意力分数矩阵 A ′ A' A′
前面提到将
q
1
q^1
q1和四个key向量
k
1
,
k
2
,
k
3
,
k
4
k^1,k^2,k^3,k^4
k1,k2,k3,k4分别做点积,得到四个相关性数值
α
1
,
1
,
α
1
,
2
,
α
1
,
3
,
α
1
,
4
\alpha_{1,1},\alpha_{1,2},\alpha_{1,3},\alpha_{1,4}
α1,1,α1,2,α1,3,α1,4。注意这里的向量都是列向量,所以点积可以写成,
α
1
,
1
=
q
1
⋅
k
1
=
(
k
1
)
T
q
1
\alpha_{1,1}=q^1 \cdot k^1 =(k^1)^Tq^1
α1,1=q1⋅k1=(k1)Tq1
α
1
,
2
=
q
1
⋅
k
2
=
(
k
2
)
T
q
1
\alpha_{1,2}=q^1 \cdot k^2 =(k^2)^Tq^1
α1,2=q1⋅k2=(k2)Tq1
α
1
,
3
=
q
1
⋅
k
3
=
(
k
3
)
T
q
1
\alpha_{1,3}=q^1 \cdot k^3 =(k^3)^Tq^1
α1,3=q1⋅k3=(k3)Tq1
α
1
,
4
=
q
1
⋅
k
4
=
(
k
4
)
T
q
1
\alpha_{1,4}=q^1 \cdot k^4 =(k^4)^Tq^1
α1,4=q1⋅k4=(k4)Tq1
用矩阵计算表示上述计算过程为
[
α
1
,
1
α
1
,
2
α
1
,
3
α
1
,
4
]
=
[
(
k
1
)
T
(
k
2
)
T
(
k
3
)
T
(
k
4
)
T
]
q
1
=
K
T
q
1
\begin{bmatrix}\alpha_{1,1} \\\alpha_{1,2} \\\alpha_{1,3} \\\alpha_{1,4}\end{bmatrix}=\begin{bmatrix}(k^1)^T\\(k^2)^T\\(k^3)^T\\(k^4)^T\end{bmatrix}q^1=K^Tq^1
⎣⎢⎢⎡α1,1α1,2α1,3α1,4⎦⎥⎥⎤=⎣⎢⎢⎡(k1)T(k2)T(k3)T(k4)T⎦⎥⎥⎤q1=KTq1将
K
T
K^T
KT与
q
2
、
q
3
、
q
4
q^2、q^3、q^4
q2、q3、q4相乘可以得到相似的结果,即,
A
=
[
α
1
,
1
α
2
,
1
α
3
,
1
α
4
,
1
α
1
,
2
α
2
,
2
α
3
,
2
α
4
,
2
α
1
,
3
α
2
,
3
α
3
,
3
α
4
,
3
α
1
,
4
α
2
,
4
α
3
,
4
α
4
,
4
]
=
[
(
k
1
)
T
(
k
2
)
T
(
k
3
)
T
(
k
4
)
T
]
[
q
1
q
2
q
3
q
4
]
=
K
T
Q
A=\begin{bmatrix} \alpha_{1,1}&\alpha_{2,1} &\alpha_{3,1} &\alpha_{4,1} \\ \alpha_{1,2}&\alpha_{2,2} &\alpha_{3,2} &\alpha_{4,2} \\ \alpha_{1,3}&\alpha_{2,3} &\alpha_{3,3} &\alpha_{4,3} \\ \alpha_{1,4}&\alpha_{2,4} &\alpha_{3,4} &\alpha_{4,4} \end{bmatrix}=\begin{bmatrix}(k^1)^T\\(k^2)^T\\(k^3)^T\\(k^4)^T\end{bmatrix}[q^1q^2q^3q^4]=K^TQ
A=⎣⎢⎢⎡α1,1α1,2α1,3α1,4α2,1α2,2α2,3α2,4α3,1α3,2α3,3α3,4α4,1α4,2α4,3α4,4⎦⎥⎥⎤=⎣⎢⎢⎡(k1)T(k2)T(k3)T(k4)T⎦⎥⎥⎤[q1q2q3q4]=KTQ
A
A
A矩阵通过softmax层归一化后得到
A
′
A'
A′ 。上述计算过程如下图所示。
4.3 计算输出矩阵 O O O
前面讲到将向量
v
1
,
v
2
,
v
3
,
v
4
v^1,v^2,v^3,v^4
v1,v2,v3,v4分别乘以对应的注意力分数
α
1
,
1
′
,
α
1
,
2
′
,
α
1
,
3
′
,
α
1
,
4
′
\alpha^{'}_{1,1},\alpha^{'}_{1,2},\alpha^{'}_{1,3},\alpha^{'}_{1,4}
α1,1′,α1,2′,α1,3′,α1,4′,并进行求和,输出向量
b
1
b^1
b1,这个过程用矩阵计算可表示为,
b
1
=
[
v
1
v
2
v
3
v
4
]
[
α
1
,
1
′
α
1
,
2
′
α
1
,
3
′
α
1
,
4
′
]
=
V
[
α
1
,
1
′
α
1
,
2
′
α
1
,
3
′
α
1
,
4
′
]
b^1=[v^1v^2v^3v^4]\begin{bmatrix}\alpha^{'}_{1,1} \\\alpha^{'}_{1,2} \\\alpha^{'}_{1,3} \\\alpha^{'}_{1,4}\end{bmatrix}=V\begin{bmatrix}\alpha^{'}_{1,1} \\\alpha^{'}_{1,2} \\\alpha^{'}_{1,3} \\\alpha^{'}_{1,4}\end{bmatrix}
b1=[v1v2v3v4]⎣⎢⎢⎢⎡α1,1′α1,2′α1,3′α1,4′⎦⎥⎥⎥⎤=V⎣⎢⎢⎢⎡α1,1′α1,2′α1,3′α1,4′⎦⎥⎥⎥⎤
通过相似的计算,也可以得到
b
2
、
b
3
、
b
4
b^2、b^3、b^4
b2、b3、b4,即,
O
=
[
b
1
b
2
b
3
b
4
]
=
[
v
1
v
2
v
3
v
4
]
[
α
1
,
1
′
α
2
,
1
′
α
3
,
1
′
α
4
,
1
′
α
1
,
2
′
α
2
,
2
′
α
3
,
2
′
α
4
,
2
′
α
1
,
3
′
α
2
,
3
′
α
3
,
3
′
α
4
,
3
′
α
1
,
4
′
α
2
,
4
′
α
3
,
4
′
α
4
,
4
′
]
=
V
A
′
O=[b^1b^2b^3b^4]=[v^1v^2v^3v^4]\begin{bmatrix} \alpha^{'}_{1,1}&\alpha^{'}_{2,1} &\alpha^{'}_{3,1} &\alpha^{'}_{4,1} \\ \alpha^{'}_{1,2}&\alpha^{'}_{2,2} &\alpha^{'}_{3,2} &\alpha^{'}_{4,2} \\ \alpha^{'}_{1,3}&\alpha^{'}_{2,3} &\alpha^{'}_{3,3} &\alpha^{'}_{4,3} \\ \alpha^{'}_{1,4}&\alpha^{'}_{2,4} &\alpha^{'}_{3,4} &\alpha^{'}_{4,4} \end{bmatrix}=VA'
O=[b1b2b3b4]=[v1v2v3v4]⎣⎢⎢⎢⎡α1,1′α1,2′α1,3′α1,4′α2,1′α2,2′α2,3′α2,4′α3,1′α3,2′α3,3′α3,4′α4,1′α4,2′α4,3′α4,4′⎦⎥⎥⎥⎤=VA′
4.4 自注意力矩阵计算总结
综上,自注意力机制的计算过程可总结为,
(1)计算
Q
、
K
、
V
Q、K、V
Q、K、V矩阵
Q
=
W
q
I
Q=W^qI
Q=WqI
K
=
W
k
I
K=W^kI
K=WkI
V
=
W
v
I
V=W^vI
V=WvI
(2)计算注意力分数矩阵
A
′
A'
A′
A
=
K
T
Q
A=K^TQ
A=KTQ
A
′
=
softmax
(
A
)
A'=\text{softmax}(A)
A′=softmax(A)
(3)计算输出矩阵
O
O
O
O
=
V
A
′
O=VA'
O=VA′
可以看出,自注意力机制看起来比较复杂,其实计算过程并不复杂,需要学习的参数只有
W
q
、
W
k
、
W
v
W^q、W^k、W^v
Wq、Wk、Wv。
5. 多头自注意力机制
自注意力机制还有一个进阶版,叫多头自注意力机制(multi-head self-attention)。为什么要多头呢?自注意力机制实质上是用过
q
q
q向量去找相关的
k
k
k向量,但是相关性可能有多种,一个
q
q
q只能找到一种相关的
k
k
k向量,因此就要引入多个
q
q
q向量和
k
k
k向量来捕捉多种相关性。多头自注意力机制很简单,设置多组矩阵
W
q
,
i
、
W
k
,
i
、
W
v
,
i
W^{q,i}、W^{k,i}、W^{v,i}
Wq,i、Wk,i、Wv,i,每一组
W
q
,
i
、
W
k
,
i
、
W
v
,
i
W^{q,i}、W^{k,i}、W^{v,i}
Wq,i、Wk,i、Wv,i只进行内部计算,得到相应的输出
O
i
O^i
Oi,如下图所示。
在得到不同的输出
O
i
O^i
Oi后,再将其拼到一起,形成一个大的矩阵。如果是2头,就将这2个输出直接拼到一起。然后通过一个转换矩阵
W
o
W^o
Wo将拼接的矩阵转换成原输出的长度的向量,即,
O
=
W
o
[
O
1
O
2
]
O=W^o\begin{bmatrix}O^1\\O^2 \end{bmatrix}
O=Wo[O1O2]
因此,多头注意力机制要多一个参数矩阵,即
W
o
W^o
Wo。