我们在《Seq2seq Attention模型详解》中,详细地回顾了以 RNN 为基础模块的Seq2seq模型。本文所讲述的Transformer也采用Seq2seq式的编码器-解码器结构,不过它摒弃了经典的 RNN,采用 self-Attention。由于并行计算、长时序建模、模型容量大等优势,它受到BERT、GPT、T5等众多预训练模型的青睐。Transformer的模型结构简单,但细节较多,本文会用尽可能深入而明了的方式进行讲述。
0.序
进入正文前,我们先对上述的3个Transformer优势进一步说明。其一,RNN 的串行结构无法支持并行计算,而Transformer的同一层的多个self-Attention完全独立,即多个head,可并行计算。其二,RNN 的串行结构会"遗忘"位于时序输入靠前位置的内容,而Transformer的self-Attention只需一步计算,就能得出时序输入中的任意两个位置的内容的联系,缓解了长距离依赖问题;其三,Transformer的参数量更多,对数据分布的建模能力更强,满足海量数据场景的要求。
1. 总体结构:Encoder与Decoder
Encoder由多层结构一致的layer串联而成(默认6层),每个layer包含两个sublayer:“多头self-Attention"和"前馈神经网络”。
Decoder同样由多层结构一致的layer串联而成,每个layer包含三个sublayer:“Masked多头self-Attention”、“多头self-Attention"和"前馈神经网络”。
2. 输入
Encoder和Decoder的输入,皆由Embedding和位置编码组成。
2.1 Embedding
Encoder的Embedding层是一个look-up表,用于得到输入序列经过tokenizer后的各个token的嵌入表示。Decoder的Embedding层通常与Encoder共享参数,用于得到Decoder前一时刻的预测输出的token的嵌入表示。如果采用Teacher Forcing,这里变为用于得到Decoder前一时刻的真实标签的token的嵌入表示。
2.2 位置编码
在Transformer中,self-Attention把任意两个字之间计算距离缩小为1,因此丢失了序列顺序。
位置不敏感的模型,例如Transformer、CNN,无法捕捉输入顺序,即在序列顺序打乱后,模型的输出保持不变。所以,通过额外加入位置编码,补偿输入的顺序关系。
根据不同位置是否存在相对关系,分为绝对位置编码和相对位置编码。绝对位置编码能够反映位置k的信息,通常直接加在输入x_k上;相对位置编码能够反映不同位置i和j的距离关系,通常加在Attention计算中。
Transformer采用了固定式位置编码,即三角函数cos和sin,公式如下:
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(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) \\ PE_{(pos,2i+1)}=cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}})
PE(pos,2i)=sin(10000dmodel2ipos)PE(pos,2i+1)=cos(10000dmodel2ipos)
其中,
p
o
s
pos
pos表示token在输入序列中的位置,2i表示PE向量的第2i个分量,
d
m
o
d
e
l
d_model
dmodel表示位置编码的维度(与embedding维度相等)。
由此,绝对位置编码可表示为位置的线性函数。
此外,受益于三角函数特性,模型能学习到不同token的相对位置关系,推导如下:
利用和差公式:
sin
(
α
+
β
)
=
sin
α
⋅
cos
β
+
cos
α
⋅
sin
β
cos
(
α
+
β
)
=
cos
α
⋅
cos
β
−
sin
α
⋅
sin
β
\begin{aligned} &\sin (\alpha+\beta)=\sin \alpha \cdot \cos \beta+\cos \alpha \cdot \sin \beta \\ &\cos (\alpha+\beta)=\cos \alpha \cdot \cos \beta-\sin \alpha \cdot \sin \beta \end{aligned}
sin(α+β)=sinα⋅cosβ+cosα⋅sinβcos(α+β)=cosα⋅cosβ−sinα⋅sinβ
代入pos+k的位置编码计算中,设 w i = 1 1000 0 2 i d m o d e l w_i=\frac{1}{10000^{\frac{2i}{d_{model}}}} wi=10000dmodel2i1:
{ P E ( p o s + k , 2 i ) P E ( p o s + k , 2 i + 1 ) = { sin ( w i ⋅ ( pos + k ) ) cos ( w i ⋅ ( pos + k ) ) = { sin ( w i ⋅ p o s ) cos ( w i ⋅ k ) + cos ( w i ⋅ p o s ) sin ( w i ⋅ k ) cos ( w i ⋅ p o s ) cos ( w i ⋅ k ) − sin ( w i ⋅ p o s ) sin ( w i ⋅ k ) = { P E ( p o s , 2 i ) cos ( w i ⋅ k ) + P E ( p o s , 2 i + 1 ) sin ( w i ⋅ k ) P E ( p o s , 2 i + 1 ) cos ( w i ⋅ k ) − P E ( p o s , 2 i ) sin ( w i ⋅ k ) \begin{aligned} \begin{cases} PE_{(pos+k, 2 i)} \\ PE_{(pos+k, 2i+1)} \end{cases} &= \begin{cases} \sin \left(w_{i} \cdot (\text{pos}+k)\right) \\ \cos \left(w_{i} \cdot(\text { pos }+k)\right) \end{cases} \\ &= \begin{cases}\sin \left(w_{i} \cdot pos\right) \cos \left(w_{i} \cdot k\right)+\cos \left(w_{i} \cdot pos\right) \sin \left(w_{i} \cdot k\right) \\ \cos \left(w_{i} \cdot pos\right) \cos \left(w_{i} \cdot k\right) - \sin \left(w_{i} \cdot pos \right) \sin \left(w_{i} \cdot k\right) \end{cases} \\ &= \begin{cases}PE_{(pos,2i)} \cos \left(w_{i} \cdot k\right) + PE_{(pos,2i+1)} \sin \left(w_{i} \cdot k\right) \\ PE_{(pos,2i+1)} \cos \left(w_{i} \cdot k\right) - PE_{(pos,2i)} \sin \left(w_{i} \cdot k\right) \end{cases} \\ \end{aligned} {PE(pos+k,2i)PE(pos+k,2i+1)={sin(wi⋅(pos+k))cos(wi⋅( pos +k))={sin(wi⋅pos)cos(wi⋅k)+cos(wi⋅pos)sin(wi⋅k)cos(wi⋅pos)cos(wi⋅k)−sin(wi⋅pos)sin(wi⋅k)={PE(pos,2i)cos(wi⋅k)+PE(pos,2i+1)sin(wi⋅k)PE(pos,2i+1)cos(wi⋅k)−PE(pos,2i)sin(wi⋅k)
由于相对距离
k
k
k是常数,设
u
=
cos
(
w
i
⋅
k
)
,
v
=
sin
(
w
i
⋅
k
)
u=\cos \left(w_{i} \cdot k\right), v=\sin \left(w_{i} \cdot k\right)
u=cos(wi⋅k),v=sin(wi⋅k),可得:
[
P
E
(
p
o
s
+
k
,
2
i
)
P
E
(
p
o
s
+
k
,
2
i
+
1
)
]
=
[
u
v
−
v
u
]
×
[
P
E
(
p
o
s
,
2
i
)
P
E
(
p
o
s
,
2
i
+
1
)
]
\begin{bmatrix} PE_{(pos+k, 2 i)} \\ PE_{(pos+k, 2i+1)} \end{bmatrix}=\begin{bmatrix} u& v \\ -v& u\end{bmatrix} \times \begin{bmatrix} PE_{(pos, 2 i)} \\ PE_{(pos, 2i+1)} \end{bmatrix}
[PE(pos+k,2i)PE(pos+k,2i+1)]=[u−vvu]×[PE(pos,2i)PE(pos,2i+1)]
由此, P E ( p o s + k , 2 i ) PE_{(pos+k, 2 i)} PE(pos+k,2i)可表示为 P E ( p o s , 2 i ) PE_{(pos, 2 i)} PE(pos,2i)的线性函数。
固定式位置编码的优点是,推理时支持任意长度的输入(不受训练时输入长度的限制)。
BERT采用了可训练式位置编码,训练前,位置编码随机初始化,并和词嵌入加在一起送入模型,作为参数进行训练。推理时,以查表的方式找到特定位置的编码向量。
可训练式位置编码的优点是,在大语料上准确性比较好,缺点是推理时限制了输入的长度(超过的position无法查表得到编码),超出部分可随机初始化,但效果依赖于数据量。
3. 多头Attention
本小节由3个问题展开,问题一是“Attention的计算细节?”,问题二是“multi-head的计算细节?”,问题三是“不同类型Attention的计算细节?”。
问题1. Attention的计算细节?
Q, K, V矩阵是Attention计算的关键。不同类型的Attention的Query、Key、Value来源不同,具体差别将在下文"问题3. 不同类型Attention的计算细节"中详细说明。
此处假设已经确定Query、Key、Value,分别通过线性变换,即可得到Q、K、V矩阵,再按如下公式计算Attention:
Attention(Q,K,V)
=
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
⋅
V
\text{Attention(Q,K,V)} = softmax(\frac{QK^T}{\sqrt{d_k}})·V
Attention(Q,K,V)=softmax(dkQKT)⋅V
其中,Q、K的维度为[batch_size, seq_len, d_k] ,V的维度为[batch_size, seq_len, d_v]。分母
1
d
k
\frac{1}{\sqrt{d_k}}
dk1 是一个放缩因子,防止d_k增大时,Q和K的点积值过大,方差变成原来的 d_k 倍,导致softmax梯度变得非常小。
D
(
q
⋅
k
d
k
)
=
d
k
(
d
k
)
2
=
1
D(\frac{q·k}{\sqrt{d_k}}) = \frac{d_k}{(\sqrt{d_k})^2} = 1
D(dkq⋅k)=(dk)2dk=1
放缩因子 1 d k \frac{1}{\sqrt{d_k}} dk1 将方差控制为1,有效缓解了梯度消失问题。
问题2. multi-head的计算细节?
我们将Attention视为一个头。Encoder和Decoder的每一层中,都有多个头。这样做的好处有,多个头之间相互独立,可以并行计算;并且可以关注到不同子空间的信息。
在单头Attention中,我们只计算一组Q, K, V矩阵。在多头Attention中,Query、Key、Value分别通过n次线性变换得到n组Qi、Ki、Vi矩阵,其中n是头的个数。此时,以K矩阵为例,维度由单头的[nbatches, seq_len, d_model],变为了[nbatches, seq_len, num_head, d_k],其中d_k=d_model/num_head。
每一组Qi、Ki、Vi,分别经过Attention计算,得到单头输出Zi。最后,所有的Z0 ~ Zn拼接在一起,此时维度变回了[nbatches, seq_len, d_model],并通过线性变换得到最终输出Z。
问题3. 不同类型Attention的计算细节?
Encoder和Decoder中,共包含"多头self-Attention"、"masked 多头self-Attention"和"多头cross-Attention"三种Attention机制。
其一,多头self-Attention位于Encoder中,即上图左侧橘色模块。它的输入Query、Key、Value均来源于同一文本,即Encoder的输入(从Encoder第二层开始,此处变为前一层的输出)。多头self-Attention的作用是建模输入中的各个单词的依存关系(e.g.语法特征)。
其二,masked 多头self-Attention位于Decoder中,即上图右侧下方橘色模块。它的Query、Key、Value都来源于前一时刻的Decoder的输出(若采用Teacher Forcing,此处变为前一时刻的ground truth)。
为了在推理过程中,避免模型看到要预测的信息,防止泄露,采用了Sequence Mask。
Transformer所采用的的mask分为Padding Mask和Sequence Mask。其中,Padding Mask(可用于encoder和decoder)用于将被PAD为0的位置上的值成为一个非常小的负数-1e9(可以是负无穷),经过softmax之后,这些位置的概率就变为了0。由此,相当于把[PAD]的无用信息给mask掉了。Sequence Mask(只用于decoder)则使用和原Tensor大小相同的下三角形掩码Tensor,即上三角部分全为非常小的负数(可以是负无穷),经过softmax之后,这些位置的概率就变为了0。由此,相当于把序列尾端元素给mask掉了。
其三,多头cross-Attention,又称为多头encoder-decoder Attention,位于Decoder中,即上图右侧上方橘色模块。它的query来自前一层decoder的输出,它的key和value来自encoder的输出。多头cross-Attention是Source各单词和Target各单词的对齐机制。
4. 残差模块
每个sublayer中,都包含一个 Add&Norm 模块。其中Add是残差连接;Norm是层归一化;还包含dropout。
以Encoder为例,如下图,残差模块的计算顺序是:step 1.对原始输入进行层归一化;step 2.把层归一化的输出,送入自注意或前馈神经网络;step 3.把自注意或前馈神经网络的输出,送入dropout;step 4.把dropout的输出与未经过层归一化的原始输入直接相加。
层归一化的优点是,避免数据落入激活函数的饱和区,减缓梯度消失问题。
残差连接的优点是,可以加快模型收敛,解决随着层数加深,误差传播的值越来越小的问题。
5. 输出
位于最后的 linear layer 将 decoder 的输出扩展到与 vocabulary size 一样的维度上。
FFN
(
x
)
=
m
a
x
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
\text{FFN}(x)=max(0, xW_1+b_1)W_2+b_2
FFN(x)=max(0,xW1+b1)W2+b2
经过 softmax 后,得到词表中各个 word 作为预测结果的概率。采用beam search,得到生成序列。
附:训练小技巧
技巧1. 标签平滑,公式如下,防止过拟合;
技巧2. 学习率先线性增长,前5000步预热,再指数衰减;
Reference
[1] The Illustrated Transformer
[2] The Annotated Transformer
[3] 图解Transformer(完整版)
[4] positional encoding位置编码详解
[5] 让研究人员绞尽脑汁的Transformer位置编码