论文地址:https://arxiv.org/abs/1706.03762
引言
transformer抛弃了CNN和RNN,整个网络有且仅有self-attention和Feed Forward Neural Network组成。作者采用Attention机制的原因是考虑到RNN(或者LSTM,GRU等)的计算限制为是顺序的,也就是说RNN相关算法只能从左向右依次计算或者从右向左依次计算,这种机制带来了两个问题:
1、时间步t的计算依赖于t-1时刻的计算结果,这样限制了模型的并行能力。
2、按照时间步顺序计算的过程,尽管LSTM等门机制一定程度上缓解了依赖问题,但是对于特别长的依赖现象,LSTM仍稍显不足。
因此transformer的提出解决了上面两个问题。
首先它使用了Attention机制,将序列中的任意两个位置之间的距离是缩小为一个常量
其次它不是类似RNN的顺序结构,因此具有更好的并行性,符合现有的GPU框架。
1、Transformer结构详解
Transformer的本质上是一个Encoder-Decoder的结构,用于翻译任务。如该论文设置的那样,Encoder由6个相同的block组成,Decoder也由6个相同的block组成。与所有生成模型相同的是,Encoder的输出会作为Decoder的输入。如下图1所示。
图
1
:
T
r
a
n
s
f
o
r
m
e
r
的
框
架
图1:Transformer的框架
图1:Transformer的框架
transformer的Encoder由Self-Attention+Feed Forward Neural Network组成,而Decoder和Encoder的不同之处在于多了一个Encoder-Decoder Attention,由图2所示。两个Attention分别用于计算输入和输出的权值:
1、Self-Attention:当前翻译和已经翻译的前文之间的关系
1、Encoder-Decoder Attention:当前翻译和编码的特征向量之间的关系
图
2
:
e
n
c
o
d
e
r
和
d
e
c
o
d
e
r
内
部
构
成
图2:encoder和decoder内部构成
图2:encoder和decoder内部构成在Transformer的Encoder中,self-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(\frac{QK^T}{\sqrt{d_k}})V
Attention(Q,K,V)=softmax(dkQKT)V,接下来我们会详细的讲解。Feed Forward Neural Network的全连接有两层,第一层机会函数是Relu,第二层是一个线性激活函数,可以表示为
F
F
N
(
Z
)
=
m
a
x
(
0
,
Z
W
1
+
b
1
)
W
2
+
b
2
FFN(Z)=max(0,ZW_1+b_1)W_2+b_2
FFN(Z)=max(0,ZW1+b1)W2+b2
2、Self-Attention
2.1 初步理解self-attention
Self-Attention的核心内容是为输入句子的每一个单词学习一个权重,例如在下面的例子中我们判断it所指代的内容,颜色越深,所受关注度越高。
The animal didn't cross the street because it was too tired
图
3
:
s
e
l
f
−
a
t
t
e
n
t
i
o
n
可
视
化
图3:self-attention可视化
图3:self−attention可视化在对it进行编码时,自注意力机制在为每个单词分配权重的时候,the animal获得了更大的权重系数,即it指代的是the animal,最终通过加权求和得到it的向量表示。
2.2 self-attention的计算方式
在self attention中,每个单词有3个不同的向量,它们分别是Query向量(
Q
Q
Q),Key向量(
K
K
K)和Value向量(
V
V
V),长度均为64。它们是通过3个不同的权值矩阵由embedding向量
X
X
X乘以三个不同的权值矩阵
W
Q
W^Q
WQ,
W
K
W^K
WK,
W
V
W^V
WV得到,如下图4所示,其中三个矩阵的尺寸是相同的,均是
512
×
64
512\times64
512×64。
图
4
:
Q
,
K
,
V
向
量
的
计
算
方
式
图4:Q,K,V向量的计算方式
图4:Q,K,V向量的计算方式Self-Attention的计算方法可以分成7步。
1、将输入单词转换为词向量
2、根据词向量得到q,k,v(如图4所示)
3、为每一个向量计算一个score:
s
c
o
r
e
=
q
⋅
k
score=q\cdot k
score=q⋅k
4、为了使梯度更稳定,Transformer使用了score归一化,即除以
d
k
\sqrt{d_k}
dk
5、对score进行softmax得到向量v的权重向量v_score
6、v_score点乘Value值v得到
v
′
v'
v′
7、求和得到最终的输出结果
z
=
∑
v
′
z= \sum{v'}
z=∑v′
这里的self attention采用点积的方式计算相似度,主要是点积能转化为矩阵运算,计算速度更快,然而点积也有一个问题,当
d
k
d_k
dk太大时,点积计算得到的内积会太大,这就导致softmax的结果不是0就是1,所以我们需要处一个
d
k
\sqrt{d_k}
dk进行缩放。
上面的计算步骤可以用下图5来表示。
图
5
:
s
e
l
f
−
a
t
t
e
n
t
i
o
n
计
算
过
程
图
示
图5:self-attention计算过程图示
图5:self−attention计算过程图示实际计算过程是采用基于矩阵的计算方式,论文中的Q,K,V的计算方式如下图6。
图
6
:
Q
,
K
,
V
的
计
算
过
程
图6:Q,K,V的计算过程
图6:Q,K,V的计算过程图5可以总结为下图7所示的矩阵形式。
图
7
:
s
e
l
f
−
a
t
t
e
n
t
i
o
n
的
矩
阵
表
示
图7:self-attention的矩阵表示
图7:self−attention的矩阵表示在self-attention中需要强调的一点是其采用了残差网络中的short-cut结构,如下图所示,目的是解决深度学习中的退化问题。
2.3 Encoder-Decoder Attention
在解码器中,Transformer block比编码器中多了个encoder-decoder attention。在encoder-decoder attention中,Q来自于解码器的上一个输出,K和V则来自于编码器的输出,计算方式与图5一致。
由于在机器翻译中,解码过程是一个顺序操作的过程,也就是当解码第k个特征向量时,我们只能看到第k-1及其之前的解码结果,论文中把这种情况下的multi-head attention叫做masked multi-head attention。如下图masked attention所示,当在进行解码的时候,在得到单词I的时候,只能看到自身,同样在解码have的时候只能看到单词I和have,以此类推。
2.4 Multi-head Attention
Multi-head Attention相当于h个不同的self-attention的集成,Transformer中h取8。multi-head attention的输出分为三步:
1、将数据
X
X
X分别输入到8个self-attention中,得到8个加权后的特征矩阵
Z
i
∈
{
1
,
2
,
3
,
…
,
8
}
Z_i\in\{1,2,3,\dots,8\}
Zi∈{1,2,3,…,8}
2、将8个
Z
I
Z_I
ZI按列拼成一个大的特征矩阵;
3、特征矩阵经过一层全连接后得到输出
Z
Z
Z
整个过程如下图所示。
2、位置编码(Position Embedding)
截止到目前,transformer模型并没有捕捉顺序序列的能力,也就是说无论句子的结构怎么打乱,Transformer都会得到类似的结果,换句话说,Transformer只是一个功能更加强大的词袋模型。
为了解决这个问题,论文在编码词向量的时候引入了位置编码(Position Embedding)的特征。具体地说,位置编码会在词向量中加入单词的位置信息,这样transformer就能区分不同位置的单词了。
论文中位置编码是一个长度
d
m
o
d
e
l
d_{model}
dmodel的特征向量,这样便于和词向量进行单位加的操作,如下图所示。
论文中给出的编码公式如下
其中,PE为二维矩阵,行表示词语,列表示位置向量,上式中,pos表示单词的位置,i表示单词的维度,
d
m
o
d
e
l
d_{model}
dmodel表示词向量的维度。
使用上述公式的原因是考虑到除了单词的绝对位置,单词的相对位置也非常重要。上述公式在每个词语的词向量的偶数位置添加sin变量,奇数位置添加cos变量,这样可以考虑到单词的相对位置。
根据:
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
E
(
p
o
s
+
k
,
2
i
)
=
P
E
(
p
o
s
,
2
i
)
×
P
E
(
k
,
2
i
+
1
)
+
P
E
(
p
o
s
,
2
i
+
1
)
×
P
E
(
k
,
2
i
)
PE(pos+k,2i)=PE(pos,2i)\times PE(k,2i+1)+PE(pos,2i+1)\times PE(k,2i)
PE(pos+k,2i)=PE(pos,2i)×PE(k,2i+1)+PE(pos,2i+1)×PE(k,2i)
P
E
(
p
o
s
+
k
,
2
i
+
1
)
=
P
E
(
p
o
s
,
2
i
+
1
)
×
P
E
(
k
,
2
i
+
1
)
−
P
E
(
p
o
s
,
2
i
)
×
P
E
(
k
,
2
i
)
PE(pos+k,2i+1)=PE(pos,2i+1)\times PE(k,2i+1)-PE(pos,2i)\times PE(k,2i)
PE(pos+k,2i+1)=PE(pos,2i+1)×PE(k,2i+1)−PE(pos,2i)×PE(k,2i)
因此当求PE(pos+k,2i)的向量时,可表示为对PE(pos,2i)上的线性表示,这样边考虑到了单词之间的相对位置信息。
总结
1、Transformer的设计最大的亮点是将任意两个单词之间的距离都变成了1,这对解决较长依赖问题非常有效
2、算法的并行性非常好,比较符合目前的以GPU为主的硬件环境。
3、模型丧失了捕捉局部特征的能力,因为它将短期依赖和长期依赖看的同等重要。
4、Transformer失去的位置信息在nlp中非常重要,论文中在特征向量上加入Position Embedding只是权宜之计。
参考链接
https://zhuanlan.zhihu.com/p/48508221
http://jalammar.github.io/illustrated-transformer/
https://blog.csdn.net/zhulinniao/article/details/104462228/
https://www.jianshu.com/p/0c196df57323
https://blog.csdn.net/Flying_sfeng/article/details/100996524