NLP --- > The Illustrated Transformer (翻译)
transformRef: https://jalammar.github.io/illustrated-transformer/自注意模型细节:输入词向量矩阵,n*e,其中n为词的个数,e为向量长度设定三个参数矩阵分别为WQ,WK,WVW^Q,W^K, W^VWQ,WK,WV,为了减少参数,该三个矩阵共享参数将三个矩阵分布为词向量矩阵相乘,得到Query, Key, Value m...
文章目录
本文是一篇非常好的transformer的翻译,此处为 原文链接。
preface
我们知道,attention目前已经深度学习中一种普通的方法。在这篇文章中,我们将介绍Transformer,一种在使用attention时能够加速训练的模型,不仅如此,在一些任务上,它的效果还要比 Google Neural Machine Translation model出色,下面我们拆分详细分析下这个模型。
The Transformer是2017年由Google的一篇问题Attention is all you need 提出, 其中此处是tensorflow的实现,其作为Tensor2Tensor的一个子模块,pytorch的一个由Harvard’s NLP groups的实现这里。
A High-level Look
当我们做机器翻译的时候,即如下图,存在若干encoders 和decoders
其中encoders和decoders均由几个相同的encoder或decoder层堆叠组成,这些encoder的结构完全相同,只是其参数不同。
每个encoder可分解为两层,其输入分别经过self-attention—该层能够获取输入的各词两两之间的相关信息,具体后面分析,然后经过一个普通的前馈神经网络,每个输入位置对应的网络是独立互不干扰的。
每个decoder同样具有与encoder相同的两层,但其在两层直接又夹了一attention 层,能够帮助decoder集中于输入句子的相关部分(其作用于seq2seq model中的attention相似)
Bring the Tensors into the Picture
从上面我们大致看出翻译的基本机构,下面我们具体从更细的张量角度来看整个流程是怎么运作的。最开始,我们通过embedding algorithm将输入的词转化为向量,即:
Encoding
对于最底层的encoder, 其输入的是一个句子中所有词向量的list, 如果我们的训练集句子长度不一,我们以句子的最大长度作为list 的容量,其他较短的句子中进行padding(填充)以达到相同的长度,这样对于每个句子,其输入的维度都将保持一致。对于list中每个词的向量,其维度我们事先进行训练设置的参数保持一致。
对于其他层的encoder,其输入为上一层encoder的输出,每层的输入输出的张量维度信息都保持一致。
Self-Attention at a High Level
当我们想将下面的句子翻译时:
”The animal didn't cross the street because it was too tired”
单词‘it’指的是什么?是街道还是动物?对于人类很简单,对于算法并不容易理解;
这里模型处理方式是,对于一个输入句子的每个词,self-attention允许它“看”该句子的所有的其他词,通过这种方式,能够“理解”该句子中其他相关的词。具体可视化关联性,可参考Tensor2Tensor notebook
Self-Attention in Detail
下面我们具体看一下一个词怎么和其他词进行联系,具体的过程是什么样的。
-
第一步:首先创建三个矩阵 W Q , W K , W V W^Q, W^K,W^V WQ,WK,WV,其维度为512*64(512为词向量维度,64为attention维度),然后对每一次词,将创建的矩阵与词向量相乘得到对应的Query Vector, Key Vector和Value Vector。
-
第二步:对于每个词,计算一个分数。比如这个例子中,对于第一个词“Thinking”,我们需要分别计算句子中每个词(包括它自己)与该词的关联性分值,如图所示:
-
第三步:将上述得到的分值再除以一个共同的值 d k \sqrt{d_k} dk,这里为8,其目的在于有更稳定的梯度,也其他为其他数值。
-
第四步:计算上述值的softmax值,当然,在原位的分值最高,但有时候也能找到其他更相关的词。
-
第五步:将softmax的值与values值求积
-
第六步:将上述得到的值相加,为这个新生成一个向量。
我们然后将为该词新生成的向量传给下一层进行计算。
上述过程可以用矩阵成绩来完成:
如第一步,直接使用一个句子所有词相乘,其中矩阵X中每一行代码输入句子的一个词:
剩下步骤:如图所示,直接得到句子中每个词新向量的表达:
The Beast With Many Heads
论文中进一步优化self-attention, 通过多头(“multi-headed”)机制,它通过两种方式提升attention layer的表现。
- 它扩展了模型聚焦不同位置的能力,在上面的例子中,Z包含了每一个其他位置的信息,但是它也可能被它自己主导;但我们想知道“The animal didn’t cross the street because it was too tired””中“it”代表的含义时,多头能提供更多的信息,更可能聚集到正确的位置。
- 它给attention layer多个表示"子空间",这种机制使得我们有多套Query/Key/Value 权重矩阵,在使用时每一套被随机初始化,训练后,每一套都能用户将输入向量转化为 一个不同的表示子空间。
如果像上述提到的计算方式,当我们使用 8个heads时,将会得到8个不同的Z矩阵。
此时有些问题,就是下一层的输入要求的是一个矩阵,而我们现在有8个,因此我们需要将其压缩为一个。怎样做呢,如下图所示:
- 首先将所得到的z矩阵拼接在一起
- 将拼接好的矩阵乘以一个权重矩阵 W 0 W^0 W0
- 将结果作为encoder层的最终输出层进入下一层。
小结
在整个过程中有很多矩阵,让我们在一起看整个流程
经过“multi-head”学习后,让我们重新修正上述中的例子,看句子中“it”表示的含义
看一看出其中一个head聚集在“tired”上,一个聚集在“the animal”上。某种意义上,在这个模型中,“it”含有同时含有“animal”和“tired”的表示。 然而,当我们把所有的head加上后,结果有点难以解释:Representing The Order of The Sequence Using Positional Encoding
在上述模型中,还有词的顺序信息没有被利用,被模型丢弃,为了解决上述方法,the transform对于每个词增加 了一个位置向量,这个向量能够通过学习表征到一些特定的模式,帮助决定每个词的位置,或者不同词之间的距离。
如果向量的维度是4,那个真实的位置向量看起来是这样的:
那么特定的模式是什么样子呢:
在下面图中,每一行代表一个位置编码,其中共有20个词,每个词的词向量维度为512。为什么看起来是中间分裂的,是因为左半部是由于sine函数产生,右半部分由cose函数产生,他们然后拼接形成每个词的位置编码。
位置编码的具体公式见原论文,虽然它并不是仅有的位置编码方式,但也能够对未知长度的序列进行编码,比如当我们进行翻译比我们训练集更长的句子时。
residuals
值得注意的是,在每一个encoder层,都有一个残差连接,然后接一个lay-normalization层:
具体来看,即是
该残差结构同样对decoder有效,当我们考虑到两层的encoders和decoders时,结果如下:
The Decoder Side
通过对encoder部分的分析,我们已了解大部分概念,下面详细了解decoder层是如何工作的。首先值得encoder层初始的输入为句子中词的向量;顶层的encoder输出为一套attention 向量 K和V;它能够被每一个decoder的encoder-decoder attention 层来使用,以帮助decoder集中在输入句子中合适的位置,如图所示:
decoder部分中每一步的输出用于底层decoder层的输入,正如encoder所做的,decoder中我们也将位置向量作为输入来表示每个词的位置,如图所示
在解码器中的self attention 层与编码器中的稍有不同,在解码器中,self-attention 层仅仅允许关注早于当前输出的位置。在softmax之前,通过遮挡未来位置(将它们设置为-inf)来实现。
"Encoder-Decoder Attention "层工作方式跟multi-headed self-attention是一样的,除了它从前层获取输出转成query矩阵,接收最后encoder层的key和value矩阵做key和value矩阵作为相应矩阵。
Final Linear and softmax layer
最后decoder层输入一个浮点型的向量,怎么把它转成一个词呢,这就是最后线性层和softmax层的作用。
线性层是一个简单的全连接层,通过将decorders的输出投射到一个更加大的向量,称为“logits vector”,其大小和词汇保持一致,然后通过softmax输出一个概率分值,并选择概率最高的作为下一个词。
The Loss Function
当我们进行训练的时候,需要表征预测的词和真实词的差异,怎么比较这两概率分布呢,我们简单地将两个分布相减。也可参考交叉熵和KL散度的计算。
上述仅考虑一个词,当我们对一个句子进行训练时,比如
输入:“je suis étudiant”
输出: “i am a student”
此时我们的目标输出为:
在一个大的训练集上训练足够多的次数后,我们希望模型输出的结果:
现在,因为模型每步只产生一组输出,假设模型选择最高概率的,去除其他的部分,这种产生的预测结果的方法,称为greedy解码。
另一种是每一步保留头部高概率的两个输出,根据这两个输出在预测下一步,再保留头部高概率的两个输出,重复直到结束,即beam-search,该过程只在预测阶段需要。
Go Forth And Transform
如果想了解更深,下面是一些步骤:
- 阅读Attention Is All You Need 原文,the transform 博客,以及Tensor2Tensor announcement。
- 查看Łukasz Kaiser’s talk 模型以及它的细节
- play with Jupyter Notebook provided as part of the Tensor2Tensor repo
- explore the Tensor2Tensor repo
后续工作:
- Depthwise Separable Convolutions for Neural Machine Translation
- One Model To Learn Them All
- Discrete Autoencoders for Sequence Models
- Generating Wikipedia by Summarizing Long Sequences
- Image Transformer
- Training Tips for the Transformer Model
- Self-Attention with Relative Position Representations
- Fast Decoding in Sequence Models using Discrete Latent Variables
- Adafactor: Adaptive Learning Rates with Sublinear Memory Cost
更多推荐
所有评论(0)