这里写自定义目录标题
至今,transformer结构的网络可以说已经占据了RNN领域的大半壁江山,在各大RNN竞赛中基本都出现了霸榜的情况。
本文主要作transformer的开山之作《Attention is All you Need》的解读.
一、transformer整体结构
首先先来看一看论文原文中整体结构图。论文中给出的结构可以看成是一个用于机器翻译的Transformer的结构。
相信大部分第一次看的人肯定都是很懵逼的,因为它和我们之前看的大部分以卷积为基本单位的RNN系列网络不同,他有很多奇奇怪怪的分支箭头。但是相信在完整了解了Transformer的整体结构后,会发现其实这张图十分简洁且清晰(不过还是想吐槽一下这个画的像太极一样的Positional Encoding)。
可以看到,Transformer可以从中间切为两半,左边的那部分是Encoder(编码器),右边那部分是Decoder(解码器)。编码器和解码器都拥有一个输入,但是输入的内容略有不同,编码器部分的输入是待翻译的句子,而解码器的输入是已经翻译了一部分的翻译过后的句子,这个地方有一点绕,本文将在后面进行解释。最后,在解码器最上方还有一个输出层,用来进行输出。
二、why Transformer
事实证明,transformer在nlp的各个领域都能大放异彩,成为了后起之秀。那么transformer到底为什么会比RNN效果要好呢?可以先看看下图:
图源自于一文搞懂RNN(循环神经网络)基础篇
如图,RNN系的模型中,最基本的结构是一个cell,如图中左侧所示。RNN的计算过程就是输入的数据分时序的反复经过相同的cell结构。
如输入:[我,爱,学,习],这四个字符会按顺序依次投入网络中进行计算。
图中的 X X X表示某个输入的字符,如 【我】 或者是 【爱】, O O O表示的是输出,放在机器翻译的场景中, X X X:【我】输入对应的输出 O O O是英文【i】。 S S S表示的是隐藏层,其中蕴含着本次输入和之前输入的信息。 W W W, V V V, U U U都是参数,其中 U U U用于对输入进行编码, W W W用于对隐藏层编码, V V V用于进行解码。
RNN的输入通常会取上一个隐藏层的输出 S t − 1 S_{t-1} St−1经过 W W W编码作为本层来源于之前信息的输入, X t X_{t} Xt进行 U U U编码后作为本层的信息输入,二者经过融合后得到本隐藏层 S t S_{t} St,经过 V t V_{t} Vt的解码后的到输出 O t O_{t} Ot,而 S t S_{t} St又将继续传递下去。
值得注意的是RNN使用的是一套参数,也就是 W W W, V V V, U U U在所有的timestep(可以理解为每个输入的字)中是一致的。不难想想RNN来源于上层的 S t − 1 S_{t-1} St−1信息在经过后续无数次的循环后可能会有所丢失。通俗意义上讲,对于一个句子而言,后面的部分在翻译的时候很可能就会无法顾及开头的信息,因为信息在传递的过程中丢失了。
【无法顾及全局的信息】是RNN的一大缺点,同时,因为需要进行序列化的一个个输入,导致 【训练和计算时间慢】,是RNN的另一个缺点。
而这两个缺点,在transformer引入了其attention机制进行并行化处理后,都得到了一定程度的解决。
三、Transformer逐层剖析
transformer的整体结构可以大概分为编码器和解码器两部分,本部分将分别介绍这两个主要构件。
1.Encoder 编码器
为了更加直观的说明,还是以【我,爱,学,习】为例。
词嵌入
首先,一般在nlp中输入是one-hot表示的,随后进入word embedding(词嵌入)层进行降维,得到最终的输入。词嵌入可以理解为将字的表示进行降维,从稀疏矩阵转为稠密矩阵,使每个表示字的向量在减少占据的空间的同时具有语义性。
大概转化如下图。
t t t是输入的字的个数,也就是timestep, d i c _ l e n dic\_{}len dic_len是字典长度, d m o d e l d_{model} dmodel对应了论文中的表述,是词嵌入后用来表示每个字的向量的维度。(注意:本文为了简化说明,省略了batch_size)。
最终输入大小为 t × d m o d e l t \times d_{model} t×dmodel。
位置编码
随后输入将进入位置编码层。那么为什么需要位置编码呢?
之前提到过,transformer的一大特点,它把计算给并行化了。他固然带来了计算速度和全局信息传递上的优势,但是也带来了一个缺点:
整个句子计算同时进行的,所以句子前后的时序信息被抹除了。
比如,本来我们的输入是【我爱学习】,但是时序信息和前后关系莫得了,它便等价于输入【学习爱我】,这显然不是我们想要的。
因此transformer便想出了一个办法解决这个问题:引入位置编码,给每个输入附加上它本来的位置信息。原论文中的公式如下:
P E ( p o s , 2 i ) =