大数据文摘出品
来源:github
编译:小七、池俊辉、Andy
今年,我们见识了许多令人眼花缭乱的机器学习的应用成果。其中OpenAI训练的GPT-2模型就展示出了惊艳的能力,它能够撰写出连贯而富有激情的论文,比当下其他所有的语言模型写的都好。
GPT-2其实并不是一种特别新颖的架构,它的架构非常类似于Transformer模型的Decoder结构。然而,GPT2是一个非常大的基于Transformer的语言模型,需要基于大量数据集进行训练。在这篇文章中,我们将介绍什么样的结构能够让模型产生好的结果,深入研究模型中的self-attention层,此外,我们将研究除语言建模之外的Transformer模型Decoder结构的应用。
我写本文主要是为了补充我之前的“图解Transformer模型”系列。
系列链接:
https://jalammar.github.io/illustrated-transformer/通过图解的方式更直观地解释Transformer模型的内部工作原理,以及它们自发布以来的演变过程。我希望通过这种图形示例能够更容易地解释后来基于Transformer的模型,毕竟它们的内部工作原理是在不断发展的。
本文主要从以下几方面展开阐述
第一部分:GPT2和语言建模
语言模型的含义
用于语言建模的Transformers模型
与BERT的区别
Transformer 架构的演变
速成课程:探索GPT-2内部工作原理
深入了解内幕
GPT-2小结
第二部分:图解Self-Attention(自我关注)模型
自注意力(Self-Attention,不加mask)
创建查询向量、键向量和值向量
打分
求和
图解Masked Self-Attention
GPT-2的Masked Self-Attention
你做到了!
第三部分:语言建模番外
机器翻译
生成摘要
迁移学习
音乐生成
结论
第一部分 GPT2和语言模型
那么究竟什么是语言模型呢?
语言模型的含义
在The Illustrated Word2vec中,我们研究了语言模型是什么,它是能根据一个句子前半部分的单词预测出下一个单词的机器学习模型。最著名的语言模型是智能手机键盘,可以根据您当前键入的内容建议出下一个单词。
The Illustrated Word2vec:
https://jalammar.github.io/illustrated-word2vec/从这个意义上讲,我们可以说GPT-2基本上是键盘应用程序的下一个单词预测功能,但它比你手机上的键盘输入法具有更大更复杂的功能。GPT-2是基于一个名为WebText大型数据集进行的训练,这个数据集大约有40G,是OpenAI研究人员为了研究从互联网上爬下来的。就存储大小来说,我使用的键盘应用程序SwiftKey占用了78MB的空间。训练出来的GPT-2的最小变体,占用500MB的存储空间来存储其所有参数。GPT-2的最大变体是最小变体的13倍,因此它可能需要占用超过6.5 GB的存储空间。
使用AllenAI GPT-2 Explorer来进行GPT-2建模是一个很好的方法,它使用GPT-2显示10个对下一个单词的预测结果,以及它们的概率分数。您可以选择其中一个单词,然后再查看下一个预测列表,循序渐进,持续不断地写下去。
用于语言建模的Transformers模型
正如我们在“图解Transformer模型”中看到的那样,原始的 transformer模型由encoder和decoder组成,每个都是我们称之为 transformer 架构的堆栈。这种架构是合理的,因为该模型解决了机器翻译问题——过去encoder-decoder结构解决的问题。
在随后的许多研究工作中,这种架构要么去掉了encoder,要么去掉了decoder,只使用其中一种transformer堆栈,并尽可能高地堆叠它们,为它们提供大量的训练文本,并投入大量的计算机设备,以训练其中一部分语言模型,这一研究需要花费数十万美元,就像在研究AlphaStar时也投入了数百万美元的资金。
那么我们可以将这些块堆叠多高呢?事实证明,堆叠的高度是不同的GPT2模型之间大小有别的主要影响因素之一。
与BERT的区别
GPT-2是基于 transformer模型的decoder架构构建的。而BERT则是基于 transformer模型的encoder结构构建的。我们将在以下部分中研究两者的差异。两者之间的一个关键区别是,GPT2与传统语言模型一样,一次输出一个token。接下来让我们来举例说明,经过训练的GPT-2是如何背诵机器人第一定律(First Law of Robotics)的。
这些模型实际工作的方式是在生成每个token之后,添加到输入序列中,而新序列将成为下一步模型的输入。这就是“自回归(auto-regression)”的思想。但这种想法也使得RNN的效率大打折扣。
GPT2以及一些后来的模型如TransformerXL和XLNet本质上都是自回归的。而BERT不是,它是一种权衡。在失去自回归的过程中,BERT可以获得两边的单词,以结合上下文去获得更好的结果。而XLNet既使用了自回归,同时也找到了根据两边单词融合上下文的替代方法。
Transformer架构的演变
一个是encoder结构,如下图所示:
来自原始 transformer论文的encoder模块可以输入直到某个最大序列长度(例如512个token)。如果输入序列短于此限制,我们可以填充序列的其余部分。
另一个是decoder结构,这个结构与encoder具有较小的体系结构差异——多了一层用于关注encoder中的特定片段:
self-attention层的一个关键区别在于它隐藏了未来的tokens,而不是像BERT那样,将单词更改为[mask(掩码)],而是通过干扰阻止了从正在计算的位置右侧的tokens中得到的信息进入到self-attention层计算。
例如,如果我们要强调位置#4的路径,我们可以看到它只允许参与当前和之前的tokens:
重要的是,BERT使用的self-attention和GPT-2使用的masked self-attention之间的区别是明确的。正常的self-attention允许在其右侧的tokens达到峰值。而Masked self-attention可防止这种情况发生:
然后是只包含decoder的架构,在发表论文“通过总结长序列来生成Wikipedia”后,提出了另一种能够进行语言建模的transformer结构。这个架构不再使用Transformer的encoder结构。因此,我们将模型称为“Transformer-Decoder”。这种早期基于transformer的语言模型由六个decoder结构组成:
论文链接:
https://arxiv.org/pdf/1801.10198.pdfDecoder结构是相同的。我扩展了第一个,所以你可以看到它的self-attention层是掩码变体。请注意,该模型现在可以在某个段中处理多达4,000个tokens——原来的 transformer只能处理512个,该模型有了较大提升。
这些结构与原始decoder结构非常相似,只是它们消除了第二个self-attention层。在“具有更深的Self-Attention的角色级语言建模”(https://arxiv.org/pdf/1808.04444.pdf)一文中实验了类似的体系结构,以创建一次预测一个字母/字符的语言模型。
OpenAI GPT-2模型使用的就是只有decoder结构的transformer模型。
速成课程:探索GPT-2内部工作原理
看看里面,你会发现,这些话正在我的脑海深处割裂。电闪雷鸣,锋利的言语正在将我逼向疯狂的边缘。
让我们来研究一个已经训练好的GPT-2,看看它是如何工作的。
GPT-2可以处理1024个tokens。每个token沿其自己的路径经过所有的decoder结构。
运行经过训练的GPT-2的最简单方法是允许它自己进行漫游(技术上称为生成无条件样本),或者我们可以给它提示让它生成关于某个主题的文本(也就是生成交互式条件样本)。在不设条件的情况下,我们可以简单地给它设置一个开始token,并让它开始生成单词(训练模型使用<|endoftext|>作为其开始token,称之为)。
该模型只有一个输入token,因此该路径将是唯一的活动路径。token通过所有层依次处理,然后沿该路径生成向量。该向量可以根据模型的词汇量进行评分(模型知道的所有单词,GPT-2中的单词为50,000个)。在这种情况下,我们选择了概率最高的token——“the”。但是我们也可能把事情搞混,因为有时你连续点击键盘应用程序中建议的第一个单词,它有时会卡在重复的循环中,唯一的出路就是你点击第二个或第三个建议的单词。这里就可能发生这种情况。GPT-2有一个名为top-k的参数,我们可以使用该参数让模型考虑除第一个字之外的采样(当top-k = 1时就是这种情况)。
在下一步中,我们将第一步的输出添加到输入序列,并让模型进行下一个预测:
请注意,第二条路径是此计算中唯一有效的路径。GPT-2的每一层都保留了自己对第一个token的解释,并将在处理第二个token时使用它(我们将在下一节中详细介绍有关self-attention的内容)。GPT-2不会根据第二个token重新解释第一个token。
深入了解内幕
输入编码
接下来看一下更多细节,以便更清楚地了解模型。让我们从输入开始。正如我们之前讨论过的其他NLP模型一样,模型在其embedding matrix(嵌入矩阵)中查找输入单词的embedding,embedding matrix是我们训练模型获得的结果之一。
每一行都是一个word embedding(单词嵌入):一个数字列表代表一个单词,并捕获它的一些含义。在不同的GPT2模型大小中该列表的大小是不同的。最小的模型使用每个字或每个token的embedding大小为768。
所以在开始时,我们会在embedding matrix中查找起始token的嵌入。在将其交给模型中的第一个模块之前,我们需要结合位置编码,位置编码是一个指示序列中的字到transformer模块中顺序的信号。经过训练的模型包含一个矩阵,其中包含输入中1024个位置中每个位置的位置编码向量。
在此基础上,我们已经介绍了在传递给第一个 transformer模块之前如何处理输入单词。我们还知道构成训练好的GPT-2模型的两个权重矩阵。
将字发送到第一个transformer模块意味着查找其embedding并将位置#1的位置编码向量相加。
堆栈之旅
现在第一个模块可以首先将token传递给self-attention层处理,然后将其传递给神经网络层来处理。一旦第一个transformer模块处理了该token,它就会将其结果向量发送到堆栈中,以便由下一个模块处理。每个模块中的过程是相同的,但每个模块在self-attention层和神经网络子层中都有自己的权重。
Self-Attention回顾
语言严重依赖于语境。例如,看看下面的机器人第二定律:
A robot must obey the orders given it by human beings except where such orders would conflict with the First Law.
我在句子中突出显示了三个地方,这三个单词都是指的是其他单词。如果不合并他们所指的上下文,就无法理解或处理这些单词。当模型处理这句话时,它必须能够知道:
It指的是机器人。
Such orders指的是前面所说的人类给予的命令。
The First Law是指前面完整的第一机器人定律。
这就是self-attention层的作用。它结合了模型对有关的和相关连的词的理解,在处理该词之前解释某个词的上下文,并将其传递给神经网络层。它通过为分段中每个单词的相关性分配分数,并将它们的向量表示相加来实现这一点。
作为一个例子,第一模块中的这个self-attention层在处理单词“it”时正在关注“a robot”。它将传递给它的神经网络的向量是三个单词中每一个向量乘以它们的分数之和。
Self-Attention处理层
Self-attention 是沿着段中每个token的路径来处理。重要的组成部分是三个向量:
查询向量(query):查询是当前单词的代表,用来去对其他所有词(使用他们的键向量)进行打分,我们只关心我们当前正在处理的token的查询。
键向量(key):键向量类似于段落中所有单词的标签,它们是我们搜索相关单词时所匹配的内容。
值向量(value):值向量是实际的单词表示,一旦我们得出每个单词的相关程度,这些加起来表示当前单词的值。
一个粗略的比喻就是把它想象成一个文件柜。查询向量就像是一个粘滞便笺,上面有您正在研究的主题。键向量就像机柜内文件夹的标签。当您将标签与便签匹配时,我们会取出该文件夹的内容,这些内容是值向量。但是您不仅要查找一个值,还要使用文件夹的混合值。
将查询向量乘以每个键向量会为每个文件夹生成一个得分(技术上:先进行点积运算然后再用softmax函数进行归一化处理)。
我们将每个值乘以其得分并相加——从而产生我们的self-attention结果。
这种加权的混合值向量产生了一个向量,它对robot这个词的“attention”为50%,对于单词a为30%,对 单词it为19%。在本文的后期,我们将更深入地研究self-attention。所以,让我们先继续沿着堆栈走向模型的输出。
模型输出
当模型中的第一模块产生其输出向量(self-attention的结果以及神经网络的结果)时,模型将该向量乘以embedding matrix。
回想一下,embedding matrix中的每一行都对应于模型词汇表中单词的embedding 。这种乘法的结果被解释为模型词汇表中每个单词的分数。
我们可以简单地选择得分最高的token(top_k = 1)。但如果模型也考虑了其他条件,则可以获得更好的结果。因此,更好的策略是使用分数作为选择该单词的概率,从整个列表中去抽样单词(因此具有较高分数的单词具有更高的被选择机会)。中间地带将top_k设置为40,并且让模型考虑具有最高分数的40个单词。
由此,模型完成了迭代,从而输出单个单词。模型继续迭代,直到生成整个上下文(1024个token)或直到生成序列结束token。
GPT-2模型小结
至此,关于GPT2的工作原理我就介绍完了。如果您想知道self-attention内部工作原理是什么,那么下文部分非常适合您。我创建它是为了引入更多的图形示例来描述self-attention,以便后来的transformer模型更易于检查和描述(比如:TransformerXL和XLNet)。
我想在这篇文章中提醒一些过于简化的内容:
在本文中“words”和“token”是可以互换使用的。但实际上,GPT2在词汇表中创建token是使用的字节对编码(Byte Pair Encoding)。这意味着token通常是words的一部分。
我们展示的示例在其推理/评估模式下运行GPT2。这就是为什么它一次只处理一个单词。在训练时,模型将针对较长的文本序列进行训练并一次处理多个tokens。此外,在训练时,模型将处理较大批量(512)并评估使用的批量大小。
我对向量进行了旋转或转置,以便更好地管理图像中的空间。在实施时,必须更精确。
Transformers使用大量的图层规范化,这非常重要。我们在“图解Transformer模型”一文中已经注意到其中的一些,在这篇文章中要更多地关注self-attentionin。
有时我需要显示更多的框来表示矢量,我指的是“放大”。如下图:
第二部分:图解self-attention(自我关注)模型
在前面的帖子当中,我们拿出这张图片来展示self-attention机制被应用在处理单词“it”的层中的示意:
在本节中,我们将详细介绍如何完成此操作。请注意我们将会以一种试图了解单个单词会发生什么的方式来看待它。这也是我们将会展示很多单个向量的原因。而实际的实现则是通过巨型矩阵的相乘来完成的。但是我想把重点放在对单词级别在这里会发生什么的直觉认识上。
Self-Attention(不加mask)
让我们首先看一下在自编码模块中计算出的初始的self-attention。我们使用一次只能同时处理四个tokens的简易的transformer模块。
Self-attention被应用在下面三个主要的步骤中:
这件作品有一个重复出现的三角形轮廓。这个区域出现在后面的一个高峰,它关注的是之前所有高峰的高音,一直到乐曲的开头。图中显示了一个查询(所有注意线的来源)和正在处理的以前的记忆(接收到更多softmax probabiliy的注释被突出显示)。注意线的颜色对应不同的头部,宽度对应softmax概率的权重。
https://www.youtube.com/watch?v=ipzR9bhei_o
https://github.com/openai/gpt-2
https://github.com/huggingface/pytorch-transformers
https://jalammar.github.io/illustrated-gpt2/