本文参考: 一步步解析Attention is All You Need 细讲 | Attention Is All You Need 对Attention is all you need 的理解
《Attention Is All You Need 》论文中提出一种只使用Attention的encoder-decoder模型,抛弃了cnn或者rnn。阅读基础是Attention机制的原理,可以参考NLP实践九:Attention原理与文本分类代码实践 整体框架 从图中可以看出,模型主要由左边N个Encoder模型和右边N个Decoder模型组成,论文中N=6。Encoders由6个相同的层堆叠在一起,每一层又有两个支层。第一个支层是一个多头的自注意机制Multi-Head Attention,第二个支层是一个简单的全连接前馈网络Feed Forward。在两个支层外面都添加了一个residual的连接,然后进行了layer nomalization的操作。Decoders也是堆叠了六个相同的层。不过每层除了编码器中那两个支层,解码器还加入了第三个支层,如图中所示同样也用了residual以及layer normalization。 为了便于理解,可以将模型简化成以下三图所描述的Encoder-Decoder模型: Encoder的每一层有两个操作,分别是Self-Attention和Feed Forward; Decoder的每一层有三个操作,分别是Self-Attention、Encoder-Decoder Attention以及Feed Forward操作。 Self-attention 和 Encoder-Decoder Attention 其实都是Multi-Head Attention,取名不同是因为self-attention 的 key,values,query是相同的向量经过线性变换得到的,Encoder-Decoder Attention 的key,value来自Encoder,query来自Decoder。
Position Embedding由于模型不包括Recurrence/Convolution,因此是无法捕捉到序列顺序信息的,为了使用序列的顺序信息,需要将tokens的相对以及绝对位置信息注入到模型中去。论文在输入embeddings的基础上加了一个“位置编码”Position Embedding。位置编码和embeddings由同样的维度都是
d
m
o
d
e
l
d_{model}
dmodel 所以两者可以直接相加。有很多位置编码的选择,既有学习到的也有固定不变的。本文中用了正弦和余弦函数进行编码。
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
/
1000
0
2
i
/
d
m
o
d
e
l
)
PE_{(pos,2i)} = sin(pos/10000^{2i/{d_{model}}})
PE(pos,2i)=sin(pos/100002i/dmodel)
P
E
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
/
1000
0
2
i
/
d
m
o
d
e
l
)
PE_{(pos,2i+1)} = cos(pos/10000^{2i/{d_{model}}})
PE(pos,2i+1)=cos(pos/100002i/dmodel) 其中,pos 表示位置index, i 表示dimension index。 Position Embedding本身是一个绝对位置的信息,但在语言中,相对位置也很重要,Google选择前述的位置向量公式的一个重要原因是,由于我们有:
s
i
n
(
α
+
β
)
=
s
i
n
α
c
o
s
β
+
c
o
s
α
s
i
n
β
sin(\alpha+\beta)=sin\alpha cos\beta+cos\alpha sin\beta
sin(α+β)=sinαcosβ+cosαsinβ
c
o
s
(
α
+
β
)
=
c
o
s
α
c
o
s
β
−
s
i
n
α
s
i
n
β
cos(\alpha+\beta)=cos\alpha cos\beta-sin\alpha sin\beta
cos(α+β)=cosαcosβ−sinαsinβ 这表明位置p+k的向量可以表示成位置p的向量的线性变换,这提供了表达相对位置信息的可能性。 Scaled Dot-Product Attention Scaled Dot-Product Attention是Multi-Head Attention的一个模块。输入为Q(query),K(key),V(values)。attention是基本的点乘的方式,就是多了一个scale。输入包括维度为
d
k
d_k
dk 的query以及key,
d
v
d_v
dv 的values。计算query和所有key的点乘,然后每个都除以
d
k
\sqrt {d_k}
dk (这个操作就是所谓的Scaled)。之后利用一个softmax函数来获取values的权重。 实际操作中,attention函数是在一些列query上同时进行的,将这些query并在一起形成一个矩阵
Q
Q
Q 同时keys以及values也并在一起形成了矩阵
K
K
K以及
V
V
V 。则attention的输出矩阵可以按照下述公式计算:
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
V
Attention(Q,K,V) = softmax({QK^T\over {\sqrt {d_k}}})V
Attention(Q,K,V)=softmax(dkQKT)V 用以下的图来解释实际代码中这个过程怎么实现的:
第一步:给定输入数据,假如输入文本为“机器学习”,首先要转换成对应的 embedding,效果图如下,绿色部分代表填充部分,全0值 第二步:计算Attention首先要有query,key和values,通过线性变换来得到三者。此时的输入是position embedding,过程如下:position embedding乘以不同维度的矩阵
W
Q
W_Q
WQ,
W
V
W_V
WV,
W
K
W_K
WK来获得query,key和values。
第三步:计算相似度,本文中使用的是点乘的方式,所以将Q和K进行点乘即可,过程如下: 这样做其实是得到了一个注意力的矩阵,每一行都是一个query和所有key的相似性,对self-attention来说,其效果如下: 第四步:增加Mask 刚刚得到的注意力矩阵,还需要做一下处理,主要有:
我们首先对key中填充的部分进行屏蔽,在进行embedding时,填充的部分的embedding 直接设置为全0,所以我们直接根据这个来进行屏蔽,即对embedding的向量所有维度相加得到一个标量,如果标量是0,那就代表是填充的部分,否则不是。 经过这一步处理,效果如下,我们下图中用深灰色代表屏蔽掉的部分: 接下来的操作只针对Decoder的self-attention来说,我们首先得到一个下三角矩阵,这个矩阵主对角线以及下方的部分是1,其余部分是0,然后根据1或者0来选择使用output还是很小的数进行填充,得到的效果如下图所示: 接下来,我们对query的部分进行屏蔽,与屏蔽key的思路大致相同,不过我们这里不是用很小的值替换了,而是直接把填充的部分变为0,经过这一步,Encoder和Decoder得到的最终的相似度矩阵如下,上边是Encoder的结果,下边是Decoder的结果: 接下来,我们就可以进行softmax操作了。 第五步:得到最终结果,得到了Attention的相似度矩阵,我们就可以和Value进行相乘,得到经过attention加权的结果:
Multi-Head Attention 作者发现先对query,key以及values进行h次不同的线性映射效果特别好。学习到的线性映射分别映射到
d
k
d_k
dk ,
d
k
d_k
dk以及
d
v
d_v
dv 维。分别对每一个映射之后的得到的query,key以及values进行attention函数的并行操作,生成
d
v
d_v
dv维的output值。具体操作细节如以下公式:
M
u
l
t
i
H
e
a
d
(
Q
,
K
,
V
)
=
C
o
n
c
a
t
(
h
e
a
d
1
,
.
.
.
,
h
e
a
d
h
)
MultiHead(Q,K,V) = Concat(head_1,...,head_h)
MultiHead(Q,K,V)=Concat(head1,...,headh)
w
h
e
r
e
:
h
e
a
d
i
=
A
t
t
e
n
t
i
o
n
(
Q
W
i
Q
,
K
W
i
K
,
V
W
i
V
)
where: head_i = Attention(Q{W_i}^Q,K{W_i}^K,V{W_i}^V)
where:headi=Attention(QWiQ,KWiK,VWiV) 映射的参数矩阵
W
i
Q
∈
R
d
m
o
d
e
l
∗
d
k
,
W
i
K
∈
R
d
m
o
d
e
l
∗
d
k
,
W
i
V
∈
R
d
m
o
d
e
l
∗
d
v
{W_i}^Q \in \Bbb R^{d_{model}*d_k},{W_i}^K \in \Bbb R^{d_{model}*d_k},{W_i}^V \in \Bbb R^{d_{model}*d_v}
WiQ∈Rdmodel∗dk,WiK∈Rdmodel∗dk,WiV∈Rdmodel∗dv,中对并行的attention层(或者成为头)使用了h=8的设定。其中每层都设置为
d
k
=
d
v
=
d
m
o
d
e
l
/
h
=
64
d_k=d_v=d_{model}/h=64
dk=dv=dmodel/h=64 由于每个头都减少了维度,所以总的计算代价和在所有维度下单头的attention是差不多的。Scaled Dot-Product Attention可以看作是只有一个Head的Multi-Head Attention。 这部分的示意图如下所示,我们重复做3次相似的操作,得到每一个的结果矩阵,随后将结果矩阵进行拼接,再经过一次的线性操作,得到最终的结果:
总结模型分析完各个模块的功能,重新来认识一下整体的框架。 Position Embedding Position Embedding给Encoder与Decoder带来了位置信息,它与embedding相加成为 Encoder与Decoder的输入。
Encoder与DecoderSoftmax动画过程
|