最近Transformer在CV领域很火,Transformer是2017年Google发表的Attention Is All You Need,主要是针对自然语言处理领域提出的。本系列文章介绍Transformer及其在各种领域引申出的应用。
自我注意(Self-attention),有时也称为内部注意(intra-attention),是一种将单个序列的不同位置联系起来,以计算该序列的表示的注意机制。Transformer是第一个完全依靠自我注意来计算其输入和输出的表示,而不使用RNN的模型。
论文指出,Transformer优势在于:
- 在传统模型中,将两个任意输入或输出位置的信号关联起来所需的操作数量随着位置之间的距离增长,ConvS2S呈线性增长,ByteNet呈对数增长。这使得学习遥远位置之间的依赖性变得更加困难。在Transformer中,这被减少到一个固定的操作数量(尽管这是以由于平均注意力加权位置而降低的有效分辨率为代价的)。
- 不使用传统RNN。RNN模型记忆长度有限且无法并行化,只有计算完 t i t_i ti时刻后的数据才能计算 t i + 1 t_{i+1} ti+1时刻的数据,但Transformer都可以做到并行化。
1. 编码器和解码器堆栈
Transformer遵循编码器-解码器结构,编码器和解码器都分别如下图的左右两部分所示:
编码器:编码器由
N
=
6
N= 6
N=6个相同的层组成。每一层有两个子层。第一种是多头自注意机构,第二种是简单的位置全连接网络。作者对两个子层使用残差连接,并加入层归一化。也就是说,每个子层的输出是:
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)),其中
S
u
b
l
a
y
e
r
(
x
)
Sublayer(x)
Sublayer(x)是子层本身实现的函数。
解码器:解码器也由 N = 6 N= 6 N=6个相同层组成。除每个编码器层中的两个子层外,解码器还插入第三个子层,该子层对编码器的输出执行多头注意。与编码器类似,作者对每个子层使用残差连接,然后进行层归一化。并且在解码器中的自注意子层种加入掩蔽并将输出被位置偏移,以确保位置 i i i的预测只依赖于小于 i i i位置的已知输出。
2. 注意力机制
注意函数可以描述为将查询键和一组键值对映射到输出,其中查询 Q Q Q、键 K K K、值 V V V和输出都是向量。输出是作为值 V V V的加权和计算的,其中分配给每个值 V V V的权重是通过查询 Q Q Q与相应键 K K K的兼容性函数计算的,如下图所示。
Scaled Dot-Product Attention: 对于上左图模块,输入包括维度
d
k
d_k
dk的查询
Q
Q
Q和键
V
V
V,以及维度
d
v
d_v
dv的值。我们计算查询
Q
Q
Q与所有键
K
K
K的点积,每个键除以
d
k
\sqrt{d_k}
dk,并应用softmax函数获得值
V
V
V的权重。我们计算输出矩阵为:
Multi-Head Attention:如上右图模块,由于Transformer出色的并行运算能力,可以将单一的注意功能,转变为线性投影来并行地执行注意功能,生成
d
v
d_v
dv维的输出值,将它们连接起来并再次进行投影,得到最终的值。多头注意使得模型能够在不同位置共同关注来自不同表示子空间的信息:
Transformer在以下三处使用多头注意力:
- 在编码器-解码器注意层中,查询前面的解码器层,而内存键和值来自编码器的输出。这使得译码器中的每个位置都可以参加输入序列中的所有位置。
- 在编码器自注意层中,所有的键、值和查询都来自前一层的输出。编码器中的每个位置都可以对应上一层的所有位置。
- 在解码器中自注意层中,同样允许解码器中的每个位置关注解码器中之前的所有位置。
3. 前馈网络
除了注意子层,编码器和解码器中的每一层都包含一个完全连接的前馈网络,它分别应用于每个位置。这包括两个线性变换,中间有一个ReLU激活:
4. 嵌入和Softmax
与其他序列转换模型类似,Transformer使用学习嵌入将输入标记和输出标记转换为维数模型向量,并使用通常学到的线性变换和softmax函数将解码器输出转换为预测的下一个概率。在Transformer的两个嵌入层之间共享相同的权矩阵和softmax线性变换。在嵌入层中,作者将这些权重乘以 d m o d e l \sqrt{d_model} dmodel。
5. 位置编码
由于Transformer不包含递归和卷积,为了使模型利用序列的顺序,我们必须在序列中注入一些关于位置的信息。为此,作者在编码器和解码器堆栈底部的输入嵌入中添加了位置编码。位置编码与嵌入编码具有相同的维数模型,两者可以相加。在本文中,作者使用不同频率的正弦和余弦函数作为位置编码:
其中位置为 p o s pos pos,维度为 i i i。也就是说,位置编码的每个维度对应于一个正弦信号。波长从 2 π 2\pi 2π到 20000 π 20000\pi 20000π呈几何级数。作者选择这个函数是因为假设它可以让模型很容易通过相对位置来学习,因为对于任何固定偏移 k k k, P E ( p o s + k ) PE_{(pos+k)} PE(pos+k)都可以表示为 P E ( p o s ) PE_{(pos)} PE(pos)的线性函数。
6. 为什么使用注意力机制
在本节中,作者将自注意层的各个方面与循环层和卷积层进行比较。这些层通常用于映射一个变长符号表示序列 ( x 1 , … , x n ) (x_1,…, x_n) (x1,…,xn)到另一个等长序列 ( z 1 , … , z n ) , x i , z i ∈ R d (z_1,…, z_n), x_i, z_i\in R^d (z1,…,zn),xi,zi∈Rd,如典型序列转换编码器或解码器中的隐藏层。作者使用自注意,主要是考虑三个需要:
- 每层的总计算复杂度。
- 可以并行化的计算量,由所需的最小顺序操作数来衡量。
- 网络中远程依赖关系之间的路径长度。
学习长期依赖是许多序列转导任务的关键挑战。影响学习这种依赖关系的一个关键因素是信号在网络中向前和向后穿越的路径长度。在输入和输出序列中任何位置组合之间的这些路径越短,就越容易学习长期依赖关系。因此,作者还列举了由不同层类型组成的网络中任意两个输入和输出位置之间的最大路径长度。如下表所示: