文章目录

  • 原文链接
  • 作者前言
  • One-hot encoding(独热编码)
  • 点积
  • 矩阵乘法
  • 查表法计算矩阵乘法
  • 一阶序列模型
  • 二阶序列模型
  • 使用跳过的二阶序列模型
  • 遮蔽
  • 中场休息站
  • 注意力之矩阵乘法
  • 二阶序列模型的矩阵乘法
  • 序列补全
  • 嵌入层(Embeddings)
  • 位置编码
  • 逆嵌入层

原文链接

Transformers from Scratch

作者前言

“我拖延了几年时间后才开始深入研究Transformers模型。最后因为不了解他们(Transformers)是如何实现而产生的不适感变得对我来说过于难以接受(才得以动手),以下便是我深入研究的内容。

Transformers在2017年的这篇论文中被介绍为序列转换的工具——将一个符号序列转换为另一个符号。该领域最流行的应用是语义翻译,如从英语翻译到德语。它同时也被拓展出实现序列补全的功能-给定一个起始提示,以相同的脉络和风格进行下去。Transformers已迅速成为自然语言处理的研究和产品开发的一个不可或缺的工具。

在我们开始之前先提个醒。我们将讨论很多关于矩阵乘法的内容,并涉及反向传播(用于训练模型的算法),但你不需要事先了解任何内容。我们将逐一添加我们需要的概念,并加以解释。

这将不是一段短暂的学习旅程,但我希望你能乐在其中。”

One-hot encoding(独热编码)

首先是文字处理部分。对于海量的文字,我们的第一步是把所有的字转换成数据,这样我们就可以对它们进行数学运算。

假设我们的目标是实现可以响应我们语音命令的计算机。我们的工作是建立一个Transformers,将一连串的声音转换为一连串的文字。

首先我们需要选择我们的词汇表,即我们在每个序列中要使用的符号集合。在我们的案例中,将有两类不同的符号集合,一类代表声音输入序列,另一类代表输出的文字序列。

现在,假设我们是在用英语工作。英语中有数万个单词,也许还有几千个用以涵盖计算机专用术语。这将使我们的词汇量达到十万之多。将单词转换为数字的一种方法是,从一开始计数,给每个单词分配自己的数字。这样一来,一连串的单词就可以被表示为一串数字。

例如,假设有一种极小的语言,其词汇量只有三个:files, find, and my。每个词都可以换成一个数字,也许files=1,find=2,my=3。那么,由单词序列[find, my, files]组成的句子 "Find my files "就可以表示为数字序列[2, 3, 1]。

这是一种相当有效的将符号转换为数字的方法,但事实证明,还有一种格式对计算机来说更容易操作,那就是独热编码。在单次编码中,一个符号由一个大部分为零的数组表示,与词汇的长度相同,只有一个元素的值为1。数组中的每个元素都对应于一个单独的符号。

另一种认识独热编码的方式是,每个词仍然被分配自己的数字,但现在这个数字是一个数组的索引。下面是我们上面的例子,用单次编码表示。

因此,"Find my files "这句话变成了一连串的一维数组,在你把它们压缩在一起后,开始看起来像一个二维数组了。

注意,我将交替使用 "一维数组 "和 "矢量 "这两个术语。同样,"二维数组 "和 "矩阵 "也是如此。

点积

独热表示法的一个真正有用的地方是,它让我们可以计算点积。它们也以其他令人生畏的名字著称,如内积和标量积。要得到两个向量的点积,需要将它们相应的元素相乘,然后将结果相加。

当我们处理独热词的表示时,点积相当有用。任何独热向量与自身的点积都是1。


而任何一个独热向量与任何其他独热向量的点积都是零。


前面的两个例子展示了点积如何被用来衡量相似性。再举另一个例子,考虑一个代表不同权重的词的组合的值向量。一个独热编码的词可以用点积与之比较,以显示该词的代表性有多强。

矩阵乘法

点积是矩阵乘法的基础,是组合一对二维数组的一种非常特殊的方式。在最简单的情况下,当A只有一行,B只有一列时,矩阵乘法的结果就是两者的点积。

请注意,A的列数和B的行数必须相同,这两个数组才能匹配并计算点积。

当A和B的维度开始增长时,矩阵乘法就开始变得棘手了。要处理A中超过一行的情况,可以分别取B与每一行的点积。答案将与A的行数一样多。

当B的列数更多时,取每一列与A计算点积,并将结果堆叠在连续的列中。


现在我们可以将其扩展到任意两个矩阵的互乘,只要A的列数与B的行数相同,其结果将与A的行数相同,与B的列数相同。

如果这是你第一次学习这些内容,可能会觉得没必要这么复杂,但我保证这之后将物有所值。

查表法计算矩阵乘法

注意矩阵乘法在这里(上图)是如何充当查找表的。我们的A矩阵是由一叠独热向量组成的。它们在第一列、第四列和第三列分别含有一个数字1。当我们进行矩阵乘法运算时,这有助于依次分离出B矩阵的第一行、第四行和第三行。这种使用独热向量来提取矩阵的某一行的技巧是transformers工作的核心。

一阶序列模型

我们可以先把矩阵放在一边,回到我们真正关心的问题上,即词的序列。想象一下,当我们开始开发我们的自然语言计算机界面时,我们只想处理三种可能的命令。

Show me my directories please.
Show me my files please.
Show me my photos please.
*

我们的词汇规模现在是7个。
{directories, files, me, my, photos, please, show}.

表示序列一个有用的方法是使用一个过渡模型。对于词汇表中的每一个词,它都会显示下一个词可能是什么。如果用户有一半的时间询问照片,30%的时间询问文件,其余的时间询问目录,那么过渡模型将是这样的。跳转到任何一个词的过渡总和将恒为1。


这个特殊的过渡模型被称为马尔科夫链,因为它满足马尔科夫属性,即下一个词的概率只取决于最近的词。更具体地说,它是一个一阶马尔可夫模型,因为它只看最近的一个词。如果它考虑最近的两个词,它就是一个二阶马尔可夫模型。

我们与矩阵的暂别已经结束。事实证明,马尔科夫链可以方便地以矩阵形式表达。现在使用与我们在创建独热向量时相同的索引方案,每一行代表我们词汇表中的一个词。每一列也是如此。矩阵过渡模型将矩阵视为一个查找表。找到与你感兴趣的词相对应的那一行。每一列的值显示了该词接下来的概率。因为矩阵中每个元素的值都代表一个概率,它们都将落在0和1之间。因为概率的总和为1,所以每一行的数值加起来总是1。

在这里的过渡矩阵中,我们可以清楚地看到我们三个句子的结构。几乎所有的过渡概率都是0或1。马尔科夫链中只有一个地方发生了分支。在my之后,directories、files或 photos 这些词可能会出现,每一个都有不同的概率。除此以外,接下来会出现哪个词并不具有不确定性。这种确定性通过过渡矩阵中的大部分1和0来体现。

我们可以重新审视我们的技巧,即使用矩阵与独热向量相乘来提取与任何特定单词相关的过渡概率。例如,如果我们只想分离出 "my "之后哪个词的概率,我们可以创建一个代表 "my "的独热向量,并将其与我们的过渡矩阵相乘。这样就可以提取相关的行,并向我们展示下一个词的概率分布。

二阶序列模型

只根据当前的词来预测下一个词是很难的。这就像在只得到第一个音符后预测曲子的其余部分。如果我们能至少得到两个音符,我们的机会就会大很多。

我们可以在另一个计算机命令的小型语言模型中看到这一点是如何运作的。我们预计这个模型将只看到两个句子,比例为40/60。

Check whether the battery ran down please.
Check whether the program ran please.

马尔科夫链说明了这是一个一阶模型。


在这里我们可以看到,如果我们的模型读取的是最近的两个词,而不是只有一个,它可以做得更好。当它遇到battery ran时,它知道下一个词将是down,而当它看到program ran时,下一个词将是please。这就消除了模型中的一个分支,减少了不确定性,增加了可信度。往后看两个词就变成了二阶马尔可夫模型。它提供了更多的背景,可以作为下一个词预测的基础。二阶马尔可夫链的绘制更具挑战性,但其关联性足以证明其价值。


为了强调两者之间的区别,下图是一阶过渡矩阵。


而这是二阶过渡矩阵。


请注意二阶矩阵是如何使每一个词的组合(其中大部分在这里没有显示)都有一个单独的行。这意味着,如果我们从N个词汇量开始,那么过渡矩阵有N^2行。

这使我们对我们的模型更具信心。在二阶模型中,有更多的1和更少的分数。在我们的模型中,只有一行有分数,一个分支。直观地说,看两个词而不是看一个词,可以提供更多的背景,更多的信息,作为猜测下一个词的依据。

使用跳过的二阶序列模型

当我们只需要读取两个词来决定下一个词的时候,二阶模型表现出很好的效果。那么,当我们需要进一步向后读取的时候呢?想象一下,我们正在建立另一个语言模型。这个模型只包含两个句子,每个句子发生的可能性都是一样的。

Check the program log and find out whether it ran please.
Check the battery log and find out whether it ran down please.

在这个例子中,为了确定哪个词应该在run之后,我们必须往前看过去的8个词。如果我们想改进我们的二阶语言模型,我们当然可以考虑使用三阶和高阶模型。然而,对于一个相当大的词汇量,这需要结合创造力和算力来实现。一个简单的八阶模型的执行就会有N^8行,这对于任何合理的词汇量来说都是一个荒谬的数字。

然而我们可以采取一些取巧的方法,设计一个二阶模型,但考虑最近的词与之前的每个词的组合。这仍然是二阶的,因为我们一次只考虑两个词,但它允许我们进一步追溯并捕捉长范围的依赖关系。这个二阶带跳过的模型与无限阶模型之间的区别在于,即便我们放弃了大部分的词序信息和前面词的组合,遗留下的信息仍大有可为。

马尔科夫链现在对我们几乎毫无作用了,但我们仍然可以用其表示每一对前面的词和后面的词之间的联系。在这里,我们省去了数字权重,只显示与非零权重相关的箭头。较大的权重用较重的线条表示。

以下是它在过渡矩阵中可能出现的情况。

这个视图只显示与预测ran之后的词有关的行。它显示了最近的词(ran)在词汇表中的每个其他词之前的情况。只显示相关的值。图中所有的空单元格都是零。

首先很明显的是,当我们试图预测run后面的词时,我们不再只看一行,而是观察一整组。我们现在已经走出了马尔科夫的领域。每一行不再代表序列在某一点上的状态。相反,每一行都代表了可能描述序列在某一点的许多特征之一。最近的词与之前出现的每一个词的组合构成了一个适用行的集合,也许是一个大集合。由于这种意义上的变化,矩阵中的每个值不再代表概率,而是一类投票。其投票将被汇总和比较,以决定下一个词的预测结果。

继而显而易见的是,大部分的特征并不重要。绝大多数词都同时出现在两个句子中,所以它们被观察到的事实对预测接下来的内容没有帮助。它们的值都是0.5。唯一的两个例外是battery和program。它们有一些1和0的权重与之相关。battery, ran这一特征表明,ran是最近的一个词,而battery在句子的某处出现。这个特征与down相关的权重为1,与please相关的权重为0。同样地,特征program, ran的权重也是相反的。这种结构表明,这两个词在句子中的早期出现对预测下一个词起着决定性的作用。

为了将这组词的特征转换为下一个词的估计值,需要将所有相关行的数值相加。向下加列,序列 Check the program log and find out whether it ran 产生的所有词的和都是0,除了down的4和please的5。序列Check the battery log and find out whether it ran与之结果相同,除了一个5的down和一个4的please,其他都是一样的。通过选择投票总数最高的词作为下一个词的预测,这个模型让我们得到了相对正确的答案,尽管结果与另外八个词深度依存。

遮蔽

经过更仔细的考虑可以得出,上述结果并不令人满意。总票数为4和5之间的差异相对较小。这表明该模型并不像它预想的那样可信。而在一个更大的、更贴合实际的语言模型中,很容易想象这样一个微小的差异将消失在统计噪音中。

我们可以通过剔除所有不具参考价值的特征票来提高预测的清晰度,除了battery, ran和program, ran之外。在这一点上,记住我们从过渡矩阵中抽出相关行的操作是很有帮助的,我们将其与显示哪些特征当前处于活动状态的向量相乘。到目前为止,在本例子中我们始终使用下图给出的隐含特征向量。

该向量包含每个特征,是ran与它前面的每个词的一个组合。任何在它之后的词都不包括在特征集中。(在下一个词的预测问题中,这些词还没有被看到,所以用它们来预测接下来的内容是不公平的)。而且这还不包括所有其他可能的单词组合。对于这个例子,我们可以放心忽略这些数据,因为它们都将是零。

为了改善我们的结果,我们可以通过再创建一个掩码将无用的特征强制化为零。这是一个全为1的向量,除了你想隐藏或屏蔽的位置,这些位置将被设置为0。在我们的例子中,我们想屏蔽除了battery, ran 和program, ran,外所有的特征,只有这两组是有帮助的。

为了应用掩码,我们将这两个向量逐一相乘。在未屏蔽位置的任何特征活动值将被乘以1,并保持不变。在被屏蔽的位置上的任何特征活动值将被乘以0,从而被强制归零
掩码具有隐藏大部分过渡矩阵的效果。它隐藏了除battery和program之外的所有特征的组合,只留下重要的功能。

在掩盖了无用的特征后,下一个词的预测变得更直接。当battery这个词出现在句子的前面时,在run之后的词被预测为权重为1的down和权重为0的please,原来25%的权重差异变成了无限大的差异,接下来会出现什么词就是毋庸置疑的了。当program在ran前出现时,对please也有同样强烈的预测。

这种选择性遮蔽的过程就是Transformers的原始论文标题中所呼吁的注意力(Attention)。到目前为止,我们所描述的只是对论文中注意力实现方式的一个近似解释,它抓住了其重要的概念,但细节与之不同。之后我们会弥补上这个差距。

中场休息站

恭喜你走到这一步。如果你愿意可以停下来休息一会。至少在解码器方面,建立选择性二阶跳转模型是思考Transformers所做工作的一种有用方式。它初步捕捉到了像OpenAI的GPT-3这样的生成性语言模型正在做的事情。尽管并没有讲述完整的故事,它仍代表了其中心主旨。

接下来的章节进一步填补了这个直观解释和Transformers如何实现之间的差距。它们主要是由三个实际考量因素驱动:

  1. 计算机在计算矩阵乘法方面特别擅长。有一个完整的产业围绕开发计算机硬件尤其是快速矩阵乘法计算打造。任何可以表示为矩阵乘法的计算都可以做到惊人的高效。这就像一列子弹列车。如果你能把你的行李放进去,它就能以惊人的速度把你带到你想去的地方。
  2. 每一步都需要是可微的。到目前为止,我们只是在举儿童玩具般简单的例子,而且还可以手工挑选所有的过渡概率和掩码值–即模型参数。在实践中,这些必须通过反向传播来学习,这取决于每个计算步骤是否可微。这意味着,对于一个参数的任何微小变化,我们都可以计算出模型误差或损失的相应变动。
  3. 梯度需要是平滑的和良态的。所有参数的所有导数的组合就是损失梯度。在实践中,要使反向传播表现良好,需要梯度是平滑的,也就是说,当你在任何方向上做小的步骤时,斜率不会变化的过快。当梯度呈良态时,它们的表现也会好得多,即它不会在一个方向上比另一个大得多。如果你把损失函数想象成一个景观,大峡谷就是一个条件差的景观。无论你是沿着底部旅行,还是沿着侧面旅行,你都将在差别很大的坡度上跋涉。相比之下,经典的Windows屏幕保护程序中的连绵起伏的山丘就会是一个良态的坡度。

如果说架构神经网络的科学是创建可分化的积木,那么它们的艺术就是将这些积木堆叠起来,使梯度不会变化太快,并且在每个方向上都大致相同。

注意力之矩阵乘法

特征权重可以直接通过计算训练中每个词对下一个词出现的转换频率来建立,但注意力掩码并非如此。到此为止,我们已经凭空提出了掩码向量,然而更加重要的是Transformers如何找到相关的掩码。使用某种查找表是个很自然的选择,但现在我们正努力专注于将一切表达为矩阵乘法。我们可以使用与上述介绍同样的查找方法,将每个词的掩码向量堆叠成一个矩阵,并使用最近一个词的独热表示法来提取出相关的掩码。


为了清晰起见,在显示掩码向量集合的矩阵中我们只显示了我们要提取出的那个。

我们终于到了可以开始联系论文的时候了。该查询掩码由注意力方程中的QK^T项表示。

查询向量Q代表我们感兴趣的特征,矩阵向量K代表掩码的集合。因为它是以列而不是行来存储掩码的,所以需要在乘法之前进行转置(用T运算符)。当我们全部完成的时候,我们会对其进行一些重要的修改,但是在这个层面上,它已经捕获到了Transformers所使用的可区分查找表的概念。

二阶序列模型的矩阵乘法

到目前为止,我们步骤中另一个一直手忙脚乱的部分是构建过渡矩阵。虽然我们已经清楚了这个逻辑,但仍不清楚如何用矩阵乘法来做。

一旦我们得到了注意力步骤中的结果,即一个包括最近的词和之前的一小部分词的向量,就需要把它转化为特征,每一个特征都是一个词对。通过注意力掩蔽我们得到了需要的原始材料,但它并没有建立这些词对的特征。要做到这一点,我们可以使用一个单层的全连接神经网络。

为了解神经网络层是如何创建的,我们将手工制作一个词对。它将呈现人为的干净和风格,它的权重与实践中的权重没有任何相似之处,但它将展示神经网络如何具有建立这两个词对特征所需的表现力。为了保持小而干净,我们将只关注这个例子中的三个被关注的词,battery, program, ran。


在上面的分层图中,我们可以看到权重是如何将每个词的存在与否状态结合成一个特征集合的。这也可以用矩阵形式来表达。


而它可以通过与代表从开始所看到的词语集合的向量进行矩阵乘法计算得到。

battery 和ran 的元素是1,program 元素是0。偏置元素总是1,这是神经网络的一个特点。通过矩阵乘法,代表battery 的元素为1,代表program和ran的元素为-1。其他情况的结果也类似。


计算这些单词组合特征的最后一步是非线性地应用整流线性单元(ReLU)。这样做的效果是用零来代替任何负值。这样就可以清理这两个结果,使它们代表每个单词组合特征存在(用1)或不存在(用0)。

随着这些智力训练的结束,我们终于完成了一个基于矩阵乘法来创建多字特征的方法。虽然我最初声称这些特征由最近的词和一个较早的词组成,但仔细看看这个方法就会发现它也可以建立其他特征。完成特征创建矩阵的学习而不是硬编码后,其他结构也可以进行学习。即使在这个玩具一般简单的例子中,也没有什么能阻止像battery, program, ran这样的三个词组合的产生。如果这种组合出现得足够普遍,它最终可能会被代表。我们没有办法指出这些词是以什么顺序出现的(至少现在没有),但我们绝对可以利用它们的共同出现来进行预测。甚至有可能利用忽略最近的单词的单词组合,比如battery, program。这些和其他类型的特征可能是在实践中产生的,这体现了我在定义transformers 是一个选择性的二阶带跳的序列模型时所作的过度简化。这里面有更多的细微差别,而现在你可以看到这个细微差别到底是什么。为了纳入更多的模型细节,这不会是我们最后一次改变其定义。

这种形式下,多字特征矩阵已经可以准备再进行一次矩阵乘法,即我们上面构建的带跳过的二阶序列模型。所有的序列所经的:

  1. 特征创建矩阵乘法。
  2. 非线性ReLU
  3. 过渡矩阵乘法

是应用注意力后的前馈处理步骤。论文中的公式2以简明的数学表述显示了这些步骤。

论文的图1结构图显示,这些被归纳为前馈模块。

序列补全

到目前为止,我们只谈到了对下一个单词的预测。为了让我们的解码器生成一个长的序列,我们需要添加几个部分。首先是一个提示(prompt),通过输入一些示例性的文本给transformer提供运行的起点和背景,以便建立序列的其余部分。它将被输入到解码器中,即上图中右边的那一列,在那里它被标记为 “Outputs (shifted right)”。选择一个能提供有趣序列的提示本身就是一门艺术,称为提示工程(prompt engineering)。这也是说明人类主要修改自己的行为来支撑算法,而不是反过来的一个很好的例子。

一旦解码器有一个部分序列准备就绪,它就进行前向传递。最终的结果是一组预测的词的概率分布,序列中的每个位置都有一个概率分布。在每个位置上,分布显示了词汇表中每个下一个单词的预测概率。我们并不关心序列中每个已确定的词的预测概率。它们已经被确定了。我们真正关心的是提示结束后下一个词的预测概率。有几种方法来选择这个词,但最直接的方法是贪婪(greedy),即选择概率最高的词。

然后,新的下一个词被添加到序列中,在解码器底部的 "输出 "处被替换进去,这个过程不断重复,直到你对此感到厌倦。

我们还没有准备好详细描述的一个部分是另一种形式的屏蔽,它确保当transformer 进行预测时只关注后面的部分而不是前面。 这个部分被应用于被标记为“屏蔽的多头注意力”的区块中。当我们能更清楚地了解它是如何做到的时候将重新讨论这个问题。

嵌入层(Embeddings)

正如我们到目前为止所描述的那样,transformers过于庞大了。对于一个词汇量为50,000的词汇,所有词对和所有潜在的下一个词之间的转换矩阵将有50,000列和50,000平方(25亿)行,总计超过100万亿元素。即使对于现代硬件平台来说,这仍然是一个难以企及的数字。

而问题不仅仅在于矩阵的大小。为了建立一个稳定的过渡语言模型,我们将不得不至少提供几次阐述每个潜在序列的训练数据。这甚至会远远超过最宏大的训练数据集的容量。

幸运的是,这两个问题都有一个变通的办法,即嵌入。

在一种语言的独热表示中,每个词都有一个向量元素。对于一个大小为N的词汇,该向量是一个N维空间。每个词都代表这个空间中的一个点,沿着许多轴中的一个移动,距离原点一个单位。我还没有找到画出高维空间的好方法,但下面有一个粗略的表示。


在嵌入中,这些词点都被取走并重新排列(用线性代数术语来说,就是映射)到一个较低维度的空间。上图显示了它们在一个二维空间中的样子。例如,现在我们不再需要N个数字来指定一个词,而只需要2个。这些是新空间中每个点的(x,y)坐标。下面是我们的小玩具例子中二维嵌入的样子,以及一些词的坐标。


一个好的嵌入过程会将具有相似含义的词组合在一起,使用嵌入的模型会在嵌入空间中学习模式。这意味着,无论它对一个词的学习结果如何,都会自动应用于紧挨着它的所有词。这有个额外的好处就是减少了所需的训练数据量。每个例子都提供了一部分学习的输入,而这些学习结果将被应用于整个词的邻域。

在这个插图中,我试图通过把重要的组件放在一个区域(battery, log, program),把介词放在另一个区域(down, out),把动词放在中心附近(check, find, ran)来说明这一点。在实际的嵌入中,分组可能不是那么清晰或直观,但基本概念是相同的。行为类似的词之间的距离是很小的。

嵌入能极大地减少所需的参数数量。然而,嵌入空间的维度越少,关于原词的信息丢失的就越多。一种语言的丰富性仍然需要相当多的空间来放置所有重要的概念,以便它们不会互相拖累彼此。通过选择嵌入空间的大小,我们可以用计算负荷来换取模型的准确性。

你可能不会对此感到惊讶:将单词从它们的独热表示映射到一个嵌入空间涉及到矩阵乘法。映射是矩阵最擅长的事情。从一个有一行和N列的独热矩阵开始,到一个二维的嵌入空间,投影矩阵将有N行和2列,如图所示。


这个例子显示了一个独热向量,例如用于代表battery,是如何提取与之相关的行的,其中包含嵌入空间中的单词坐标。为了使这一关系更加清晰,独热向量中的零被隐藏起来,所有其他没有被拉出投影矩阵的行也是如此。完整的映射矩阵是密集的,每一行都包含它所关联的词的坐标。

映射矩阵可以将原始的独热词汇向量集合转换成你想要的任何维度空间中的任何配置。最大的诀窍是找到一个有用的映射,即将相似的词分组在一起的映射,以及一个有足够维度来分散它们的映射。对于常见的语言,如英语,有一些相当不错的预先计算的嵌入。另外,像transformer中的其他东西一样,它也可以在训练中学习。

在原始论文的图1架构图中,这里是进行嵌入的地方。

位置编码

到目前为止,我们一直假设单词的位置是被忽略的,至少对于在最近的单词之前的任何单词来说是如此。现在我们要用位置嵌入法来解决这个问题。

有几种方法可以将位置信息引入到我们的词的嵌入表中,但在最初的transformer中,它的方法是添加一个循环摆动。

词在嵌入空间中的位置就像一个圆的中心。它被添加的一个扰动取决于它在词的序列中的位置。不同位置的词被移动相同的距离,但角度不同,当你把词在序列中移动时,会产生一个圆形图案。在序列中相互靠近的词有类似的扰动,但相距较远的词则在不同的方向受到扰动。

由于圆是一个二维的图形,表示一个圆形的摆动需要修改嵌入空间的两个维度。如果嵌入空间由两个以上的维度组成(几乎总是如此),那么圆形摆动就会在所有其他的维度对中重复出现,但是如果旋转的角度频率不同,也就是说,它在每种情况下扫出不同数量的旋转。在一些维度对中,扰动将扫出许多旋转的圆。在其他维度对中,它只会扫出一小部分的旋转。所有这些不同频率的圆周摆动的组合,可以很好地表示一个词在序列中的绝对位置。

我仍然在培养我的直觉,为什么这能起作用。它似乎是以一种不会破坏文字和注意力之间的学习关系的方式将位置信息添加到混合中。如果想更深入地了解数学和意义,我推荐阿米尔霍辛-卡泽姆内贾德的位置编码教程。

在transformer典型的结构图中,这些块显示了生成的位置码和它添加的嵌入字。

逆嵌入层

嵌入词使它们的工作效率大大提高,但一旦(嵌入)聚会结束,它们就需要被转换回原始词汇中的词。解除嵌入的方式与嵌入的方式相同,从一个空间投射到另一个空间,也就是矩阵乘法。

逆嵌入矩阵的形状与嵌入矩阵相同,但行数和列数是翻转的。行的数量是我们要转换的空间的维度。在我们所使用的例子中,它是我们嵌入空间的大小,即2。列数是我们要转换的空间的维度–在我们的例子中,是全部词汇独热表示法的大小,即13。

一个好的逆嵌入矩阵中的值并不像嵌入矩阵中的值那样可以直接说明,但其效果是相似的。当代表程序这个词的嵌入向量与去嵌入矩阵相乘时,相应位置上的数值就会很高。然而,由于投射到高维空间的工作方式,与其他词相关的值不会是零。在嵌入空间中最接近程序的词也会有中高的值。其他的词将有接近零的价值。而且很可能会有很多负值的词。词汇空间的输出向量将不再是独热或稀疏的。它将是密集的,几乎所有的值都不为零。


这没关系。我们可以通过选择与最高值相关的词来重新创建独热向量。这个操作称为argmax,用于给出最高值的参数(元素)。这就是上面提到的如何完成贪婪序列的步骤。这是个不错的第一步,但我们可以做得更好。

如果一个嵌入图很好地映射到几个词,我们可能不想每次都选择最好的那个。它可能只是比其他的选择好一点点,增加一丝变化可以使结果更有趣。另外,有时在确定最后的选择之前,提前看几个词并考虑句子可能的所有方向是很有用的。为了做到这些,我们必须首先将我们的逆嵌套结果转换成概率分布。

Transformers from Scratch(从零开始的Transformers )翻译学习【更新中】相关推荐

  1. 一段话描述相控阵论文要点(持续学习更新中...)

    一段话描述相控阵论文要点(持续学习更新中...) 2109005-许唐红,詹珍贤,胡帅帅,宋豪.T/R组件阻抗失配对相控阵天线性能的影响[J].微波学报,2021,37(03):82-84+98. 分 ...

  2. 【Spring Boot官方文档原文理解翻译-持续更新中】

    [Spring Boot官方文档原文理解翻译-持续更新中] 文章目录 [Spring Boot官方文档原文理解翻译-持续更新中] Chapter 4. Getting Started 4.1. Int ...

  3. 面试常见IT术语的英文日文英语日语翻译(不断更新中)

    常用IT术语英日翻译 用语 英文 日文 面向对象 object-oriented オブジェクト指向 面向过程 procedure-oriented プロセス指向 手続き形 变量 variable 変数 ...

  4. @淘宝前端团队 犀牛书(中文版)中的那些翻译错误(更新中)

    首先对作者David Flanagan和淘宝前端团队的前辈们表示感谢,没有你们在前方开拓荒野,和我一样的前端菜鸟们,前端之路必然没有现在这样平坦. 当然为了后来者更加方便,我将精读JavaScript ...

  5. typescript-----javascript的超集,typescript学习笔记持续更新中......

    Typescript,冲! Typescript 不是一门全新的语言,Typescript是 JavaScript 的超集,它对 JavaScript进行了一些规范和补充.使代码更加严谨. 一个特别好 ...

  6. Transformers in Vision: A Survey论文翻译

    Transformers in Vision: A Survey 论文翻译 原文 翻译链接 摘要 摘要--Transformer模型在自然语言任务上的惊人结果引起了视觉界的兴趣,而致力于研究它们在计算 ...

  7. 论文篇 | 2020-Facebook-DETR :利用Transformers端到端的目标检测=>翻译及理解(持续更新中)

    论文题目:End-to-End Object Detection with Transformers 2020 论文复现可参考:项目复现 | DETR:利用transformers端到端的目标检测_夏 ...

  8. Devops系统化,从零开始学习容器技术(更新中)

    文章目录 Devops系统化,从零开始学习Docker.K8s 一.容器技术和Docker简介 1.1 Docker导学 1.2 容器技术概述 二.Docker环境的各种搭建方法 2.1 Docker ...

  9. 「ArXiv2020」【Efficient Transformers: A Survey】论文笔记(更新中)

    「ArXiv2020」[Efficient Transformers: A Survey]论文笔记 Abstract 1. Introduction 2. Background on Transfor ...

最新文章

  1. 【转】Oozie4.2.0配置安装实战
  2. ubuntu自动登录tty1(shell,text)配置
  3. Count the Colors ZOJ - 1610
  4. linux标准c和c编译器6,linux内核中GNU C和标准C的区别
  5. 已阻止网站自动通话怎么回事_如何实现百度快速收录网站与快速排名
  6. 亚马逊 开发者api 调用_关于微信API:常用微信API文档整理
  7. vue.js根据数据循环生成表格_vue.js循环for(列表渲染)详解
  8. 合同电子档备份-NXCRM客户管理系统v2.2.5
  9. 201521460005 实验五
  10. 关于ajax post请求跨域问题的解决心得
  11. 详解CAN总线:常用CAN连接器的使用方法
  12. 考查频率最高的吉林八景
  13. PowerBuilder9.0窗口最小化没显示了
  14. HTML页面显示时间——网页数字时钟、钟表
  15. python_open函数中newline参数详解
  16. Why Transformer works
  17. Centos 安装 glib
  18. 表格td的宽度不随内容自适应
  19. Twisted基本模型
  20. Andrew NG 《machine learning》week 2,class3 —Computing Parameter Analytically

热门文章

  1. php-fpm 启动失败,php-fpm自启动失败问题排查
  2. ROS(indigo) turtlebot2 + android一些有趣应用
  3. YOLOX源码解读系列
  4. 使用Matlab把图片集合生成视频流文件
  5. Java POI导出(图片,文字,表格)word文档
  6. PCB各层含义简介 浅显易懂 图文展示
  7. win7安装android驱动失败怎么办,Win7蓝牙驱动安装失败的原因分析与解决方法
  8. SQLServer错误代码解释
  9. 如何给单据分录上增加核算项目的F7(代码示例)。
  10. 微服务:同步与异步的抉择。