文章目录
1 介绍
论文地址:https://arxiv.org/abs/1706.03762v5
论文源码:https://github.com/tensorflow/tensor2tensor
图解:https://jalammar.github.io/illustrated-transformer/
原文的图示说明较少,有些地方描述不是很清楚,所以增加了些图示,更多细节就需要看源码。
3 模型架构
Encoder、Decoder
常见的模型都是encoder-decoder结构。encoder负责把输入序列 ( x 1 , . . . , x n ) (x_1,...,x_n) (x1,...,xn)映射到连续表达 z ( z 1 , . . . , z n ) \mathbf z(z_1,...,z_n) z(z1,...,zn),decoder负责把 z \mathbf z z生成为输出序列 ( y 1 , . . . , y m ) (y_1,...,y_m) (y1,...,ym)(一次一个符号),每一步,模型都是自回归的。
自回归语言模型(Auto-regressive model)就是根据上文信息预测下文信息(反之亦可)
模型结构 | 模型简化示意图 |
---|---|
Transformer也是这样的整体结构,在encoder和decoder中使用堆叠的self-attention、point-wise、全连接。
Encoder:
- 由
N(N=6)
层完全相同的layer堆叠 - 每个layer有两个sub-layers,第一个是multi-head self-attention结构,第二个是简单的position-wise全连接前向网络。
- 每个sub-layer周围都使用了残差链接,后面跟一个layer归一化,即每个sublayer最终的输出为 L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x+Sublayer(x)) LayerNorm(x+Sublayer(x))(也就是图中的Add&Norm的输出)
- 因为残差链接,所以所有的sub-layer,输出维度都是 d m o d e l = 512 d_{model}=512 dmodel=512
Decoder:
- 由
N(N=6)
层完全相同的layer堆叠 - 每个layer有三个sub-layers,第一个是masked multi-head self-attention结构,第二个是multi-head self-attention结构,第三个是简单的position-wise全连接前向网络。
- masked multi-head self-attention结构是为了防止positions关注到后续的positions
- 和encoder一样,每个sub-layer周围都使用了残差链接
以两层堆叠的模型为例,图示说明一下encoder-decoder:
encoder | 2层堆叠的encoder-decoder |
---|---|
Attention
Attention功能可以被描述为:把query
和key,value
映射到一个output
,query
、key-value
、output
都是向量。output
是value
加权的和,每个value
元素对应的权重,由query
和对应的key
计算所得。
attention | multi-head |
---|---|
Scaled Dot-Product Attention
输入有
d
k
d_k
dk维的queries
和keys
,
d
v
d_v
dv维的values
,Attention计算公式为:
Attention
(
Q
,
K
,
V
)
=
softmax
(
Q
K
T
d
k
)
V
\text {Attention}(Q,K,V)=\text {softmax}(\frac {QK^T} {\sqrt{d_k}})V
Attention(Q,K,V)=softmax(dkQKT)V
之前最常见的attention函数有两种:累加和点乘attention,点乘和本文的attention差异只在
1
d
k
\frac 1 {\sqrt{d_k}}
dk1。点乘可以使用优化的矩阵操作代码实现,所以效率更高。
d
k
d_k
dk值小的时候,累加和点乘的性能差不多,但是
d
k
d_k
dk值大的时候,作者认为点乘的结果会非常大,在softmax函数内,会对应到梯度非常小的区域,为了抵消这种负面影响,添加了
1
d
k
\frac 1 {\sqrt{d_k}}
dk1因数
Scaled Dot-Product Attention中,Mask(opt.)是可选的层,对应Decoder中提到的masked multi-head self-attention。
Multi-Head Attention
作者发现,使用学习得到的不同的线性投影,把queries
、keys
、values
投影到
d
k
d_k
dk,
d
k
d_k
dk,
d
v
d_v
dv维h
次,比直接单独用一次attention的效果要好。
在投影后再并行执行attention,得到
d
v
d_v
dv维的输出。
multi-Head attention允许模型共同注意到来自不同位置的不同表示子空间的信息。
MultiHead
(
Q
,
K
,
V
)
=
Concat
(
h
e
a
d
1
,
.
.
.
,
h
e
a
d
h
)
W
O
head
i
=
Attention
(
Q
W
Q
,
K
W
K
,
V
W
V
)
,
i
∈
[
1
,
h
]
\text{MultiHead}(Q,K,V) = \text {Concat}(head_1,...,head_h)W^O \\ \text {head}_i = \text {Attention}(QW^Q,KW^K,VW^V),i\in [1,h]
MultiHead(Q,K,V)=Concat(head1,...,headh)WOheadi=Attention(QWQ,KWK,VWV),i∈[1,h]
线性映射的参数:
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
O
∈
R
h
d
v
×
d
m
o
d
e
l
W^Q_i \in \mathbb R^{d_{model}\times d_k},W^K_i \in \mathbb R^{d_{model}\times d_k},W^V_i \in \mathbb R^{d_{model}\times d_v},W^O \in \mathbb R^{hd_v\times d_{model}}
WiQ∈Rdmodel×dk,WiK∈Rdmodel×dk,WiV∈Rdmodel×dv,WO∈Rhdv×dmodel
本文中,
h
=
8
,
d
k
=
d
v
=
d
m
o
d
e
l
/
h
=
64
h=8,d_k=d_v=d_{model}/h=64
h=8,dk=dv=dmodel/h=64
Q/K/V图示 | multi-head图示 |
---|---|
也就是queries 、keys 、values 的计算方式 | multi-head中, h = 8 h=8 h=8的示例 |
模型中的attention应用
Transformer使用Multi-head attention有三种方式:
- 在“encoder-decoder”层,
queries
来自自前一个decoder层,记忆keys
和values
来自encoder的输出。这样,decoder每个position能注意到输入序列的全部positions,相当于seq-to-seq的模型。 - encoder包含自注意力层。自注意力的所有
keys
,values
,queries
来自于同一处,这种情况下,来自于encoder中的上一层。每个position可以注意到前一层的所有positions。 - 相似的,decoder中的自注意力层,允许position注意直到并包括(up to and including)该position的所有positions。为了防止decoder中的左向信息流,来保持自回归特性,在scaled dot-product attention中,屏蔽掉(masking out)softmax的所有非法链接的输入
values
。
Position-wise 前向网络
为了注意sub-layers,encoder和decoder中每层包含了一个全连接前向网络,分别应用于每个position,且完全一样。包含了两个线性变换,且两个变换之间有一个ReLU激活函数。
FFN
(
x
)
=
max
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
\text{FFN}(x)=\text {max}(0,xW_1+b_1)W_2+b_2
FFN(x)=max(0,xW1+b1)W2+b2
不同position用的线性变换一样,层与层之间参数不同。换一种表述方式,这就是两个kernel size为1的卷积。输入输出的维度
d
m
o
d
e
l
=
512
d_{model}=512
dmodel=512,内部层的维度
d
f
f
=
2048
d_{ff}=2048
dff=2048。
Embeddings and Softmax
与其他序列转换模型类似,使用学习的embedding将输入token转换为向量并输出,向量维度 d m o d e l d_{model} dmodel,使用学习的线性变换和softmax来把decoder的输出转变为预测token的分布。
本文模型中,两个embedding层和pre-softmax层共享了权重矩阵,在embedding层,权重放大了 d m o d e l \sqrt{d_{model}} dmodel。
Positional Encoding
由于模型不包含递推和卷积,为了让模型利用序列的顺序,必须注入一些token在序列中的相对或绝对位置的信息。为此,在encoder和decoder的堆叠的底部,加入了“positional encodeing”,其维度和embedding一样,都是
d
m
o
d
e
l
d_{model}
dmodel,因此可以相加。可选的有不少,本文中用了不同频率的sine和cosine。
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
/
1000
0
2
i
/
d
m
o
d
e
l
)
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)}=sin(pos/10000^{2i/d_{model}})\\ PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{model}})
PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)
其中的
p
o
s
pos
pos是position,
i
i
i是维度。
这样,position的每个维度的编码,对应一个正弦波。波长从2π到10000·2π呈几何级数。作者认为这样可以通过相对positions让模型轻易的学会注意,因为对于任何的固定偏差 k k k, P E p o s + k PE_{pos+k} PEpos+k可以用 P E p o s PE_{pos} PEpos的线性变换来表达。
作者也试了学习的positional embedding,两种版本结果几乎一致,作者选择了正弦曲线版本,为了让模型推断出比训练时的序列更长的序列。
4 为什么是自注意力
本文对比了自注意力、常用的递推、卷积在映射序列 ( x 1 , . . . , x n ) (x_1,...,x_n) (x1,...,xn)到另一个同长度序列 ( z 1 , . . . z n ) (z_1,...z_n) (z1,...zn)时,多个方面的表现。
- 每层的总计算复杂度
- 可以并行的计算量
- 长程依赖(long-range dependencies)的路径长度,路径越短,越容易学习。
5 Training
5.1~5.3 略
5.4 正则化
训练时使用了三种正则化:
- 在每一个sub-layer的输出和sub-layer的输入相加并归一化之前,使用Residual Dropout。
- 在encoder和decoder的堆叠中,对embedding和positional encoding的和使用Residual Dropout。对于base模型,两种dropout的参数都是 P d r o p = 0.1 P_{drop}=0.1 Pdrop=0.1
- 训练时,使用了label smoothing,value
ϵ
l
s
=
0.1
\epsilon _{ls}=0.1
ϵls=0.1。这会使模型训练不稳定,但提高了精度和BLEU分数。
6 Results
略