【NLP】Transformer 模型原理&论文回顾
不积硅步,无以至千里。不积小流,无以成江海。 ————荀子
1.1 Transformer 模型的由来
2017年Google研究院发表了一篇《Attention is all you need》论文中提出了Transformer模型,其使用self-attention的结构取代了当时NLP任务中最常用的RNN网络结构。相较于RNN网络结构,其最大的优点则是可以进行并行计算。Transformer的整体模型架构如图1所示。
1.2 Transformer 模型介绍
不论是在NLP的领域还是在图像生成的范畴,Transformer模型的出现都为现在AI的发展刮起的飓风打下了基础和铺垫。像现在最火的chatgpt模型,NLP范畴中的Bert模型都是包含了Transformer作为其中的架构,特别它优秀的编码\解码能力,在机器翻译和映射上有非常好的效果,更方便了机器学习人类的语言语义特征的多样性。
2.1 Transformer 模型概览
和大多数seq2Seq模型一样,Transformer模型的结构也是有Decoder和Encoder组成的。
Encoder:Transformer的encoder编码器是由6个相同的layer组成,layer指的是上图中“Nx”的单元结构,其中x在此处为6。每个layer由2个sub-layer组成,分别是multi-head self-attention mechanism(多头注意力机制)和fully connected feed-forward network(前馈网络,缩写为 FFN)。其中每个sub-layer都加了residual connection和normalisation,因此可以将sub-layer的输出表示为:
S
u
b
_
L
a
y
e
r
_
O
u
t
p
u
t
=
L
a
y
e
r
N
o
r
m
(
x
+
S
u
b
l
a
y
e
r
(
x
)
)
Sub\_Layer\_Output = LayerNorm(x + Sublayer(x))
Sub_Layer_Output=LayerNorm(x+Sublayer(x))
Decoder:Decoder和Encoder的结构差不多,但是多了一个attention的sub-layer,这里先明确一下decoder的输入输出和解码过程:
输出:对应i位置的输出词的概率分布
输入:encoder的输出 & 对应i-1位置decoder的输出。所以中间的attention不是self-attention,它的K,V来自encoder,Q来自上一位置decoder的输出
解码:这里要注意一下,训练和预测是不一样的。在训练时,解码是一次全部decode出来,用上一步的ground truth来预测(mask矩阵也会改动,让解码时看不到未来的token);而预测时,因为没有ground truth了,需要一个个预测。
2.2 Decoder与Encoder中的Sub-layer模块
正如上面所提及,Decoder模块与Encoder具有类似的结构组成,每个编码器的结构都是相同的,但是它们使用不同的权重参数。编码器的输入会先流入 Self-Attention 层。它可以让编码器在对特定词进行编码时使用输入句子中的其他词的信息(可以理解为:当我们翻译一个词时,不仅只关注当前的词,而且还会关注其他词的信息)。后面我们将会详细介绍 Self-Attention 的内部结构。然后,Self-Attention 层的输出会流入前馈网络,如下图2所示。
Self-Attention模块精讲摘选
首先我们通过一个例子,来对 Self-Attention 有一个直观的认识。假如,我们要翻译下面这个句子:
The animal didn’t cross the street because i t \color{red} {it} it was too tired
这个句子中的 i t \color{red} {it} it 指的是什么?是指 animal 还是 street ?对人来说,这是一个简单的问题,但是算法来说却不那么简单。
当模型在处理 i t \color{red} {it} it 时,Self-Attention 机制使其能够将 it 和 animal 关联起来。
当模型处理每个词(输入序列中的每个位置)时,Self-Attention 机制使得模型不仅能够关注当前位置的词,而且能够关注句子中其他位置的词,从而可以更好地编码这个词。
如果你熟悉 RNN,想想如何维护隐状态,使 RNN 将已处理的先前词/向量的表示与当前正在处理的词/向量进行合并。Transformer 使用 Self-Attention 机制将其他词的理解融入到当前词中。
此处引用博客Transformer 模型详解的self-attention计算详解内容
解码器也有编码器中这两层,但是它们之间还有一个注意力层(即 Encoder-Decoder Attention),其用来帮忙解码器关注输入句子的相关部分(类似于 seq2seq 模型中的注意力)。
根据论文中的公式推导,Attention可以由以下公式表示:
A
t
t
e
n
t
i
o
n
_
O
u
t
p
u
t
=
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
Attention\_Output = Attention(Q, K, V)
Attention_Output=Attention(Q,K,V)
Multi-head Attention
通过h个不同的线性变换对Q,K,V进行投影,最后将不同的Attention结果拼接起来,self-attention则是取Q,K,V相同。 另外,文章中attention的计算采用scaled dot-product,如图3所示。
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/\sqrt{d_k})V Attention(Q,K,V)=softmax(QKT/dk)V
作者同样提到了另一种复杂度相似但计算方法additive attention,在 d k d_k dk很小的时候和dot-product结果相似, d k d_k dk大的时候,如果不进行缩放则表现更好,但dot-product的计算速度更快,进行缩放后可减少影响(由于softmax使梯度过小,具体可见论文中的引用)。
Position-wise feed-forward networks
位置前馈网络就是一个全连接前馈网络,每个位置的词都单独经过这个完全相同的前馈神经网络。其由两个线性变换组成,即两个全连接层组成,第一个全连接层的激活函数为 ReLU 激活函数。可以表示为:
F
F
N
(
x
)
=
m
a
x
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x) = max(0, xW_1+b_1)W_2+b_2
FFN(x)=max(0,xW1+b1)W2+b2
在每个编码器和解码器中,虽然这个全连接前馈网络结构相同,但是不共享参数。整个前馈网络的输入和输出维度都是
d
_
m
o
d
e
l
=
512
d\_model=512
d_model=512,第一个全连接层的输出和第二个全连接层的输入维度为
d
f
f
=
2048
d_{ff}= 2048
dff=2048 。
2.3 Positional Encoding 位置编码
除了主要的Encoder和Decoder,还有数据预处理的部分。Transformer抛弃了RNN,而RNN最大的优点就是在时间序列上对数据的抽象,所以文章中作者提出两种Positional Encoding的方法,将encoding后的数据与embedding数据求和,加入了相对位置信息。Transformer 模型为每个输入的词嵌入向量添加一个向量。这些向量遵循模型学习的特定模式,有助于模型确定每个词的位置,或序列中不同词之间的距离。具体的数学公式如下:
- 任意位置的 P E p o s + k PE_{pos+k} PEpos+k都可以被 P E p o s PE_{pos} PEpos的线性函数表示。
- 可以扩展到未知的序列长度。例如,当我们训练后的模型被要求翻译一个句子,而这个句子的长度大于训练集中所有句子的长度。
2.4 Mask掩码
Mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 Padding Mask 和 Sequence Mask。其中,Padding Mask 在所有的 scaled dot-product attention 里面都需要用到,而 Sequence Mask 只有在 Decoder 的 Self-Attention 里面用到。
2.4.1 Padding Mask
什么是 Padding mask 呢?因为每个批次输入序列的长度是不一样的,所以我们要对输入序列进行对齐。具体来说,就是在较短的序列后面填充 0(但是如果输入的序列太长,则是截断,把多余的直接舍弃)。因为这些填充的位置,其实是没有什么意义的,所以我们的 Attention 机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。
具体的做法:把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 Softmax 后,这些位置的概率就会接近 0。
2.4.2 Sequence Mask
Sequence Mask 是为了使得 Decoder 不能看见未来的信息。也就是对于一个序列,在 t tt 时刻,我们的解码输出应该只能依赖于 t tt 时刻之前的输出,而不能依赖 t tt 之后的输出。因为我们需要想一个办法,把 t tt 之后的信息给隐藏起来。
具体的做法:产生一个上三角矩阵,上三角的值全为 0。把这个矩阵作用在每个序列上,就可以达到我们的目的。
总结:对于 Decoder 的 Self-Attention,里面使用到的 scaled dot-product attention,同时需要 Padding Mask 和 Sequence Mask,具体实现就是两个 Mask 相加。其他情况下,只需要 Padding Mask。
2.5 Linear线性层与Softmax层
解码器栈的输出是一个 float 向量。我们怎么把这个向量转换为一个词呢?通过一个线性层再加上一个 Softmax 层实现。
线性层是一个简单的全连接神经网络,其将解码器栈的输出向量映射到一个更长的向量,这个向量被称为 logits 向量。
现在假设我们的模型有 10000 个英文单词(模型的输出词汇表)。因此 logits 向量有 10000 个数字,每个数表示一个单词的分数。
然后,Softmax 层会把这些分数转换为概率(把所有的分数转换为正数,并且加起来等于 1)。最后选择最高概率所对应的单词,作为这个时间步的输出。(归一化过程)
2.6 Dropout 正则化操作
在原文中,为了训练更好的Transformr模型,在训练过程中执行了如下操作:
- Dropout。对编码器和解码器的每个子层的输出使用 Dropout 操作,是在进行残差连接和层归一化之前。词嵌入向量和位置编码向量执行相加操作后,执行 Dropout 操作。
- Label Smoothing(标签平滑)
3. 总结
Transformer是第一个用纯attention搭建的模型,不仅计算速度更快,在翻译任务上获得了更好的结果,也为后续的BERT模型做了铺垫。