原文链接:http://jalammar.github.io/illustrated-transformer/

高级外观

让我们首先将模型看作一个黑盒子。在机器翻译应用程序中,它将使用一种语言的句子,并将其翻译输出到另一种语言中。

弹出Optimus Prime的优点,我们看到了编码组件,解码组件以及它们之间的连接。

编码组件是一堆编码器(纸张堆叠其中六个相互叠加 - 没有什么神奇的六号,一个肯定可以尝试其他安排)。解码组件是相同数量的解码器的堆栈。

编码器的结构完全相同(但它们不共享权重)。每一个都分为两个子层:

编码器的输入首先流经自我关注层 - 这一层帮助编码器在输入句子中对其他单词进行编码时对其进行编码。我们会在帖子后面仔细观察自我关注。

自我关注层的输出被馈送到前馈神经网络。完全相同的前馈网络独立应用于每个位置。

解码器具有这两个层,但它们之间是一个关注层,帮助解码器关注输入句子的相关部分(类似于seq2seq模型中的注意事项)。

将张量引入图片

现在我们已经看到了模型的主要组成部分,让我们开始研究各种向量/张量以及它们如何在这些组件之间流动,以将训练模型的输入转换为输出。

与NLP应用程序中的情况一样,我们首先使用嵌入算法将每个输入字转换为矢量。

 
每个单词都嵌入到大小为512的向量中。我们将用这些简单的框表示这些向量。

嵌入仅发生在最底部的编码器中。所有编码器通用的抽象是它们接收每个大小为512的向量列表 - 在底部编码器中将是嵌入字,但在其他编码器中,它将是编码器的输出直接在下面。这个列表的大小是我们可以设置的超参数 - 基本上它是我们训练数据集中最长句子的长度。

在我们的输入序列中嵌入单词后,它们中的每一个都流过编码器的两个层中的每一层。

在这里,我们开始看到Transformer的一个关键属性,即每个位置的单词在编码器中流经自己的路径。自我关注层中的这些路径之间存在依赖关系。然而,前馈层不具有那些依赖性,因此各种路径可以在流过前馈层时并行执行。

接下来,我们将示例切换为更短的句子,我们将查看编码器的每个子层中发生的情况。

现在我们正在编码!

正如我们已经提到的,编码器接收矢量列表作为输入。它通过将这些向量传递到“自我关注”层,然后传递到前馈神经网络,然后将输出向上发送到下一个编码器来处理该列表。


每个位置的单词都经过自编码过程。然后,它们各自通过一个前馈神经网络 - 完全相同的网络,每个矢量分别流过它。

高水平的自我关注

不要被我愚弄“自我关注”这个词,这是每个人都应该熟悉的概念。在阅读Attention is All You Need论文之前,我个人从未遇到过这个概念。让我们提炼它是如何工作的。

假设以下句子是我们要翻译的输入句子:

“ The animal didn't cross the street because it was too tired

这句话中的“它”是指什么?它指的是街道还是动物?这对人类来说是一个简单的问题,但对算法来说并不简单。

当模型处理单词“it”时,自我关注允许它将“it”与“animal”相关联。

当模型处理每个单词(输入序列中的每个位置)时,自我注意允许它查看输入序列中的其他位置以寻找可以帮助更好地编码该单词的线索。

如果您熟悉RNN,请考虑如何保持隐藏状态允许RNN将其已处理的先前单词/向量的表示与其正在处理的当前单词/向量合并。自我关注是变形金刚用来将其他相关单词的“理解”融入我们当前正在处理的单词中的方法。

 
当我们在编码器#5(堆栈中的顶部编码器)中编码单词“it”时,注意机制的一部分集中于“动物”,并将其表示的一部分烘焙到“它”的编码中。

请务必查看Tensor2Tensor笔记本,您可以在其中加载Transformer模型,并使用此交互式可视化对其进行检查。

详细的自我关注

让我们首先看看如何使用向量计算自我注意力,然后继续查看它是如何实际实现的 - 使用矩阵。

第一步骤中计算自关注的是从每个编码器的输入向量的创建三个矢量(在这种情况下,每个字的嵌入)。因此,对于每个单词,我们创建一个Query向量,一个Key向量和一个Value向量。这些向量是通过将嵌入乘以我们在训练过程中训练的三个矩阵而创建的。

请注意,这些新向量的尺寸小于嵌入向量。它们的维数为64,而嵌入和编码器输入/输出向量的维数为512.它们不必更小,这是一种架构选择,可以使多头注意力计算(大多数)不变。

 
乘以X1WQ权重矩阵产生Q1,与该字相关联的“查询”载体。我们最终在输入句子中创建每个单词的“查询”,“键”和“值”投影。

什么是“查询”,“关键”和“值”向量?

它们是抽象,有助于计算和思考注意力。一旦你继续阅读下面如何计算注意力,你就会知道你需要知道的每个这些向量的作用。

第二个步骤中计算自注意的是,计算得分。假设我们正在计算这个例子中第一个单词“思考”的自我关注。我们需要根据这个词对输入句子的每个单词进行评分。当我们在某个位置编码单词时,分数决定了对输入句子的其他部分放置多少焦点。

通过将查询向量的点积与我们得分的相应单词的关键向量计算得分。因此,如果我们处理位置#1中单词的自我关注,则第一个分数将是q1k1的点积。第二个分数是q1k2的点积。

第三和第四步骤是由8(在造纸中使用的密钥向量的维数的平方根来划分的分数。 - 64。这导致具有更稳定的梯度有可能是这里其他可能的值,但这是默认),然后通过softmax操作传递结果。Softmax将分数标准化,因此它们都是正数并且加起来为1。

该softmax分数确定每个单词在该位置表达的程度。很明显,这个位置的单词将具有最高的softmax分数,但有时候关注与当前单词相关的另一个单词是有用的。

所述第五步骤是由SOFTMAX得分乘以每个值向量(准备中总结起来)。这里的直觉是保持我们想要关注的单词的值不变,并淹没不相关的单词(例如,通过将它们乘以像0.001这样的小数字)。

第六步骤是要总结的加权值向量。这会在此位置产生自我关注层的输出(对于第一个单词)。

结论是自我关注计算。得到的矢量是我们可以发送到前馈神经网络的矢量。然而,在实际实现中,该计算以矩阵形式完成,以便更快地进行处理。现在让我们看一下,我们已经看到了单词级别计算的直觉。

自我注意的矩阵计算

第一步是计算Query,Key和Value矩阵。我们通过将嵌入包装到矩阵X中,并将其乘以我们训练过的权重矩阵(WQWKWV)来实现。

 
X矩阵 中的每一行对应于输入句子中的一个单词。我们再次看到嵌入向量的大小差异(图中512或4个方框)和q / k / v向量(图中64或3个方框)

最后,由于我们正在处理矩阵,我们可以在一个公式中浓缩步骤2到6来计算自我关注层的输出。

 
矩阵形式的自我关注计算

有许多头的野兽

本文通过增加一种称为“多头”关注的机制,进一步完善了自我关注层。这以两种方式改善了关注层的性能:

  1. 它扩展了模型关注不同位置的能力。是的,在上面的例子中,z1包含了所有其他编码的一点点,但它可能由实际的单词本身支配。如果我们翻译一句“动物没有过马路,因为它太累了”,我们会想知道“它”指的是哪个词,这将是有用的。

  2. 它给予关注层多个“表示子空间”。正如我们接下来将看到的,我们不仅有一个,而且还有多组Query / Key / Value权重矩阵(Transformer使用8个注意头,因此我们最终为每个编码器/解码器设置了8个) 。这些集合中的每一个都是随机初始化的。然后,在训练之后,每组用于将输入嵌入(或来自较低编码器/解码器的矢量)投影到不同的表示子空间中。


通过多头注意,我们为每个磁头维护单独的Q / K / V权重矩阵,从而得到不同的Q / K / V矩阵。正如我们之前所做的那样,我们将X乘以WQ / WK / WV矩阵以产生Q / K / V矩阵。

如果我们进行上面概述的相同的自我关注计算,只有八个不同的时间使用不同的权重矩阵,我们最终得到八个不同的Z矩阵

这让我们面临一些挑战。前馈层不期望八个矩阵 - 它期望单个矩阵(每个字的向量)。所以我们需要一种方法将这八个压缩成一个矩阵。

我们怎么做?我们将矩阵连接起来然后通过另外的权重矩阵WO将它们多个。

这就是多头自我关注的全部内容。我意识到这是一小部分矩阵。让我尝试将它们全部放在一个视觉中,这样我们就可以在一个地方看到它们

现在我们已经触及了注意力的头,让我们重新审视我们之前的例子,看看不同的注意力头在哪里聚焦,因为我们在我们的例句中编码“it”这个词:

 
当我们对“它”这个词进行编码时,一个注意力的焦点主要集中在“动物”上,而另一个注意力集中在“疲惫” - 从某种意义上说,模型对“它”这个词的表现形式在某些表现形式中有所表现。 “动物”和“疲倦”。

但是,如果我们将所有注意力添加到图片中,那么事情可能更难理解:

使用位置编码表示序列的顺序

到目前为止,模型中缺少的一件事就是考虑输入序列中单词顺序的一种方法。

为了解决这个问题,变换器为每个输入嵌入添加了一个向量。这些向量遵循模型学习的特定模式,这有助于确定每个单词的位置,或者序列中不同单词之间的距离。这里的直觉是,将这些值添加到嵌入中,一旦它们被投影到Q / K / V向量中并且在点积注意期间,就在嵌入向量之间提供有意义的距离。


为了给模型一个单词顺序的感觉,我们添加位置编码向量 - 其值遵循特定模式。

如果我们假设嵌入的维数为4,那么实际的位置编码将如下所示:


玩具嵌入大小为4的位置编码的真实示例

这种模式可能是什么样的?

在下图中,每行对应矢量的位置编码。因此第一行将是我们添加到输入序列中嵌入第一个单词的向量。每行包含512个值 - 每个值的值介于1和-1之间。我们对它们进行了颜色编码,使图案可见。


嵌入大小为512(列)的20个字(行)的位置编码的真实示例。你可以看到它在中心区域分成两半。这是因为左半部分的值由一个函数(使用正弦)生成,而右半部分由另一个函数(使用余弦)生成。然后将它们连接起来以形成每个位置编码矢量。

位置编码的公式在论文(第3.5节)中描述。您可以在中查看用于生成位置编码的代码get_timing_signal_1d()。这不是位置编码的唯一可能方法。然而,它具有能够扩展到看不见的序列长度的优点(例如,如果要求我们训练的模型翻译句子的时间长于训练集中的任何一个句子)。

剩余物

在继续之前我们需要提到的编码器架构中的一个细节是每个编码器中的每个子层(自注意,ffnn)在其周围具有残余连接,然后是层规范化步骤。

如果我们要将矢量和与自我关注相关的图层规范操作可视化,它将如下所示:

这也适用于解码器的子层。如果我们想到2个堆叠编码器和解码器的变压器,它看起来像这样:

解码器端

既然我们已经涵盖了编码器方面的大多数概念,我们基本上都知道解码器的组件是如何工作的。但是让我们来看看它们如何协同工作。

编码器通过处理输入序列开始。然后将顶部编码器的输出变换成一组关注矢量K和V.这些将由每个解码器在其“编码器 - 解码器关注”层中使用,这有助于解码器关注输入序列中的适当位置:


完成编码阶段后,我们开始解码阶段。解码阶段中的每个步骤输出来自输出序列的元素(在这种情况下为英语翻译句子)。

以下步骤重复此过程,直至特殊 到达符号表示变压器解码器已完成其输出。在下一个时间步骤中,每个步骤的输出被馈送到底部解码器,并且解码器像编码器那样冒泡它们的解码结果。就像我们对编码器输入所做的那样,我们在这些解码器输入中嵌入并添加位置编码,以指示每个字的位置。

解码器中的自关注层以与编码器中的自注意层略有不同的方式操作:

在解码器中,仅允许自我关注层关注输出序列中的较早位置。这是通过-inf在自我关注计算中的softmax步骤之前屏蔽未来位置(将它们设置为)来完成的。

“编码器 - 解码器注意”层就像多头自我注意一样,除了它从它下面的层创建其查询矩阵,并从编码器堆栈的输出中获取键和值矩阵。

最终线性和Softmax层

解码器堆栈输出浮点数向量。我们如何将其变成一个单词?这是最终线性层的工作,其后是Softmax层。

线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的矢量投影到一个更大,更大的矢量中,称为logits矢量。

让我们假设我们的模型知道10,000个独特的英语单词(我们的模型的“输出词汇表”),它是从训练数据集中学到的。这将使logits矢量10,000个细胞宽 - 每个细胞对应于一个唯一单词的得分。这就是我们如何解释线性层后面的模型输出。

然后softmax层将这些分数转换为概率(全部为正,全部加起来为1.0)。选择具有最高概率的单元,并且将与其相关联的单词作为该时间步的输出。

 
该图从底部开始,矢量产生为解码器堆栈的输出。然后它变成输出字。

回顾培训

现在我们已经通过训练有素的变压器覆盖了整个前进过程,看一下培训模型的直觉是有用的。

在训练期间,未经训练的模型将通过完全相同的前进传球。但是,由于我们在标记的训练数据集上训练它,我们可以将其输出与实际正确的输出进行比较。

为了想象这一点,让我们假设我们的输出词汇只包含六个单词(“a”,“am”,“i”,“thanks”,“student”和“<eos>”(“句末”的缩写)) 。


在我们开始训练之前,我们模型的输出词汇是在预处理阶段创建的。

一旦我们定义了输出词汇表,我们就可以使用相同宽度的向量来表示词汇表中的每个单词。这也称为单热编码。例如,我们可以使用以下向量指示单词“am”:


示例:我们的输出词汇表的单热编码

在回顾一下之后,让我们讨论一下模型的损失函数 - 我们在训练阶段优化的指标,以引导一个训练有素且令人惊讶的精确模型。

损失函数

假设我们正在训练我们的模型。说这是我们在训练阶段的第一步,我们正在训练它的一个简单例子 - 将“merci”翻译成“谢谢”。

这意味着,我们希望输出是指示“谢谢”一词的概率分布。但由于这种模式还没有接受过训练,所以这种情况不太可能发生。


由于模型的参数(权重)都是随机初始化的,(未经训练的)模型产生的概率分布具有每个单元/单词的任意值。我们可以将它与实际输出进行比较,然后使用反向传播调整所有模型的权重,使输出更接近所需的输出。

你如何比较两个概率分布?我们简单地从另一个中减去一个。有关更多详细信息,请查看 交叉熵和Kullback-Leibler散度。

但请注意,这是一个过于简单的例子。更现实的是,我们将使用长于一个单词的句子。例如 - 输入:“jesuisétudiant”和预期输出:“我是学生”。这真正意味着,我们希望我们的模型能够连续输出概率分布,其中:

  • 每个概率分布由宽度为vocab_size的向量表示(在我们的玩具示例中为6,但更实际地是3,000或10,000的数字)
  • 第一概率分布在与单词“i”相关联的单元处具有最高概率
  • 第二概率分布在与单词“am”相关联的单元格中具有最高概率
  • 依此类推,直到第五个输出分布表示' <end of sentence>'符号,其中还有一个与10,000元素词汇表相关联的单元格。


我们将在一个样本句子的训练示例中训练我们的模型的目标概率分布。

在足够大的数据集上训练模型足够的时间之后,我们希望产生的概率分布看起来像这样:


希望通过培训,模型将输出我们期望的正确翻译。当然,这个短语是否是训练数据集的一部分并不是真正的指示(参见:交叉验证)。请注意,即使不太可能是该时间步的输出,每个位置都会获得一点概率 - 这是softmax非常有用的属性,有助于训练过程。

现在,因为模型一次生成一个输出,我们可以假设模型从该概率分布中选择具有最高概率的单词并丢弃其余的单词。这是一种方法(称为贪婪解码)。另一种方法是保持前两个词(例如,'I'和'a'),然后在下一步中,运行模型两次:一旦假设第一个输出位置是单词'I',另一次假设第一个输出位置是'me'这个单词,考虑到#1和#2的位置,保留的是哪个版本产生的错误较少。我们重复这个位置#2和#3 ......等。这种方法称为“波束搜索”,在我们的例子中,beam_size是两个(因为我们在计算位置#1和#2的波束后比较了结果),和top_beams也是两个(因为我们保留了两个单词)。这些都是您可以尝试的超参数。

transformer模型原理相关推荐

  1. 详解Transformer模型及相关的数学原理

    声明:本文参考了许多相关资料,视频,博客,结合<Attention is All You Need>这篇文章的每一个细节,从一个初学者的角度出发详细解读Transformer模型,无代码. ...

  2. 最新Transformer模型大盘点,NLP学习必备,Google AI研究员出品丨资源

    萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 可高效处理长文本的模型Longformer.和堪称"升级版"Transformer的BigBird模型,到底有什么区别? ...

  3. Transformer模型总结

    Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现快速并行. 它是由编码组件.解码组件和它们之间的连接组成. 编码组件部分由一堆编码器(6个 enco ...

  4. 强的离谱, Transformer 模型与联邦机器学习详解!

    Transformer 作为一种基于注意力的编码器 - 解码器架构,不仅彻底改变了自然语言处理(NLP)领域,还在计算机视觉(CV)领域做出了一些开创性的工作.与卷积神经网络(CNN)相比,视觉 Tr ...

  5. 论文解读:《功能基因组学transformer模型的可解释性》

    论文解读:<Explainability in transformer models for functional genomics> 1.文章概括 2.背景 3.相关工作 4.方法 4. ...

  6. 知识图谱论文阅读(八)【转】推荐系统遇上深度学习(二十六)--知识图谱与推荐系统结合之DKN模型原理及实现

    学习的博客: 推荐系统遇上深度学习(二十六)–知识图谱与推荐系统结合之DKN模型原理及实现 知识图谱特征学习的模型分类汇总 知识图谱嵌入(KGE):方法和应用的综述 论文: Knowledge Gra ...

  7. 【python量化】将Transformer模型用于股票价格预测

    前言 下面的这篇文章主要教大家如何搭建一个基于Transformer的简单预测模型,并将其用于股票价格预测当中.原代码在文末进行获取. 1.Transformer模型 Transformer 是 Go ...

  8. transformer模型的奥秘-学习笔记

          本文主要介绍了transformer模型的大概原理及模型结构.这篇学习笔记的学习资料主要是<Attention is All you Need>这篇神作,还有两位大神的指点(见 ...

  9. Transformer模型技术长文

    Transformer模型技术长文 可高效处理长文本的模型Longformer.和堪称"升级版"Transformer的BigBird模型,到底有什么区别? Transformer ...

最新文章

  1. mysql减少锁等待_降低锁竞争 减少MySQL用户等待时间
  2. Hadoop生态上几个技术的关系与区别:hive、pig、hbase 关系与区别
  3. 安装64位Oracle 10g超详细教程
  4. Windows——右键菜单显示“管理员取得所有权”选项
  5. LeetCode 993. 二叉树的堂兄弟节点(层序遍历)
  6. 更改Ubuntu终端复制和粘贴的快捷键
  7. 【mysql安装】阿里云centos7环境mysql安装
  8. mac os x 10.11 php7,mac osx 10.11.2安装PHP7提示“configure: error: libcrypto not found!”
  9. (转)万万没想到,无人车其实是个劳动密集型产业
  10. linux 安装Elasticsearch
  11. “磁碟机”病毒分析报告
  12. CSP2019滚粗记
  13. 软件测试女生可以学习么?现在还能入行么?
  14. SW练习_POJ2007_CCW
  15. 数据集:人群行为识别数据库总结
  16. 什么是RPN,ROIAlign?
  17. 堆排序(大根堆与小根堆)
  18. 洛杉矶租车房车超强攻略,让房车旅行不麻烦
  19. 电脑中了virus.win32.sality.i和virus.win32.pioneer.c病毒,导致所以的EXE文件打不开(打开浏览器会提示:xc0000005异常)
  20. android.os.FileUriExposedException: file:///storage/emulated/0/myxmpp/154094

热门文章

  1. 芯片科技科普3摩尔定律
  2. git使用中关于文件名太长无法处理的问题
  3. 用C++写的一段电话录音程序代码
  4. 电机星三角启动SCL源程序
  5. 在电脑上观看 蓝光dvd 攻略
  6. 水果软件中的粘合与琶音命令使用方法
  7. 超链接静态资源下载中 download属性无效解决方案
  8. window8.1各种游戏不兼容
  9. 使用nexus搭建局域网私服Maven仓库(Windows版)
  10. java code combat_CodeCombat编程游戏