关于导言
在导言里,作者首先提出一个问题:如何更好的利用无监督的文本?当时最成功的模型是词嵌入模型。接下来,作者列出了使用无标注文本时遇到的两个主要困难。第一个困难是优化目标函数的选择,损失函数应该是什么样子?当时有很多选择可以解决这个问题,比如语言模型、机器翻译、文本一致性等,但没有一个特别好的目标函数适用于所有任务。第二个困难是如何有效地将所学的文本表示传递到现有的子任务上,因为NLP中的子任务多样且没有一种简单有效的方式将一种表示迁移到所有任务上。
本文提出了一种半监督方法,用于在无标号文本上训练大型语言模型,然后在具体子任务上进行微调。半监督学习是机器学习中十年前非常流行的话题,旨在利用标记数据学习未标记数据。在这种情况下,本文采用类似的方法,首先在未标记数据上训练模型,然后在标记数据上微调。
本文的模型基于Transformer架构,这是当时相对较新的架构。作者解释说,与递归神经网络(RNN)相比,Transformer在迁移学习方面更加稳健,因为它具有更结构化的记忆,可以处理更长的文本,并从句子和段落层面提取更好的语义信息。
另一个关键技术要点是在迁移学习时使用与任务相关的表示。本文将在后面详细介绍这种表示。
最后一部分介绍了实验结果。作者在12个任务中的9个任务中获得了优异的结果,但在某些任务上略逊于BERT(其实BERT的出现时间是在GPT之后,但大家都喜欢将这两个模型进行比较)。
关于模型
在模型这个章节包含3个小节,分别介绍了在没有标注数据的情况下如何训练模型、微调模型以及如何为每个子任务表示输入。
【1】预训练
假设我们有一个没有标注的文本,其中每个单词被表示为一个向量 ,整个文本被表示为一个序列 到 ,这些单词是有序列信息的,所以顺序是不能改变的。GPT使用标准的语言模型目标函数来最大化似然函数,如下面这个公式:

具体而言,语言模型要预测第i个单词的出现概率。对于单词
,模型会考虑它前面的K个单词(即 到 ),这里的K被称为上下文窗口或窗口大小。模型每次会选择连续的K个单词,并预测这K个单词后面的一个单词是什么。它使用一个模型(φ)来进行预测,该模型从输入的K个单词和模型参数中得出下一个单词的概率。将每个单词的预测概率加起来,就得到了目标函数L1。
目标就是通过训练模型φ,使其能够输出与给定文本类似的文章。超参数K是窗口大小,它控制着模型输入序列的长度。输入序列越长,网络就能看到更多的信息,从而更容易在文本中发现关系。如果您希望模型更强大,则K可能需要增加到数十甚至数百。
对于公式中的模型φ,模型使用了Transformer的解码器,这个模型涉及到编码器和解码器两个部分。编码器和解码器最大的不同在于,编码器输入一个序列时,当提取第i个元素的特征时,可以看到整个序列里的所有元素。而对于解码器来说,由于存在掩码,当提取第I个元素的特征时,它只能看到当前元素和它之前的元素,后面的元素被掩码处理,注意力机制计算时会被视为0,所以解码器无法看到后面的内容。因此,我们只能使用Transformer的解码器,而不能使用编码器。
如果我们要预测单词U出现的概率,那么将U前面的K个单词全部取出来,将K个词输入到一个大的U中,做一个词嵌入的投影,并加上位置信息的编码,这将成为我们第一层的输入。接下来,我们需要做N层这样的Transformer块,每一层都需要将上一层的输出作为输入,并得到新的输出。由于我们知道存储模块不会改变输出的形状,因此一直进行完所有层之后,我们就会得到最后一个Transformer块的输出。然后我们再做一次投影,并使用softmax函数,就能得到U出现的概率分布了。

【2】微调模型
在ChatGPT的微调中,数据是有标号的,也就是给定一个长为m的词序列X1到Xm,并告诉它们对应的标号是y。我们的目标是对这个序列去预测它的y的概率。在微调任务中,我们把整个序列放入之前预训练的GPT模型中,然后获取transformer块的最后一层输出,对应着序列中的Hm,接着将其乘以输出层,再使用一个softmax函数,就能得到预测概率。这个操作在微调任务中的所有带有标签的序列上都会执行。在微调任务中,我们需要使用标准分类目标函数来最大化预测概率。

作者还提到,尽管我们只关心单个分类任务的性能,但是将预训练语言模型也放到微调模型中会提高效果。也就是说,在微调任务中我们有两个目标函数。一个是预测下一个单词,另一个是预测给定完整序列的标签。将这两个目标函数结合起来效果最好。作者通过对它们的加权平均来平衡这两个目标函数,权重是一个超参数,可以根据需要调整。

【3】子任务
对于不同的子任务,我们需要找到一种合适的方式来表示这些任务。如何将NLP中四种常见的用户任务表示为一个序列和对应的标签,是接下来要讨论的。

第一类是应用场景是“分类”(classification),例如对一段文本进行情感分类,判断其是正面还是负面。为了将这种任务表示为一个序列和标签,我们需要在原始文本前添加一个起始标记,后面添加一个结束标记,形成一个序列,然后将其输入到transformer解码器中。模型会抽取最后一个词的特征并将其传入一个线性层进行投影。线性层的输出大小在训练时是固定的,并且对于每个文本和标签对都会进行训练。在微调中,我们需要重新构造一个新的线性层,其中权重可能是随机初始化的,并且数字大小与标签数量相同。通过这个线性层,我们可以将输入序列转换为我们需要的标签,这是微调过程中的一个区别。
第一个应用场景是“蕴含”(entailment),即判断一段文本是否蕴含某种假设。该应用可以看作是一个三分类问题,需要将两段文本串联成一个长序列,采用特殊的开始符、分隔符和抽取符来区分不同部分。注意,这些特殊标记不能和文本中的其他词重复。该应用中使用的模型是GPT算法,它在训练数据集上的表现相较于之前的算法有所提升,在多个数据集上的表现也相对较好。
第二个应用场景是“相似”(similarity),即判断两段文本的相似程度。该应用同样采用GPT算法,但需要考虑相似关系的对称性。因此,对于每一对文本,需要构造两个序列,分别将它们放在不同的位置上,并用特殊标记区分不同部分。这些序列将分别输入模型中进行处理,得到最终的输出结果,然后通过一个线性层进行判断,是相似还是不相似。
第三个应用场景是“多选题”(multiple choice),即从多个答案中选择正确的答案。该应用需要构造多个序列,其中每个序列的开头都是同一个问题,而每个答案则依次作为第二个序列进行处理。这些序列将分别输入模型中进行处理,最终通过一个线性投影层输出对应的答案得分,用softmax函数将得分转换为对每个答案的选择概率。在这个应用中,GPT算法同样能够发挥出色的表现。
虽然这三个应用的数据形式有所不同,但它们都可以被看作是一个序列处理问题。不论输入形式如何变化,使用的GPT算法的结构都不会改变,这是与之前的算法相比的一个显著优点。因此,GPT算法在NLP领域有着广泛的应用前景,尤其适用于处理文本序列的问题。
关于实验
关于实验我们主要关心两点。第一点,该模型是在名为 "BooksCorpus" 的数据集上进行训练的,该数据集包含7000篇未发表的书。第二点,模型本身采用了12层Transformer解码器,每层维度为768,其规模相当庞大。实验结果表明该模型在训练数据集上的表现相较于之前的算法有所提升。GPT算法在精度上的表现也优于其他算法,这一点在多个数据集上都得到了验证。

总体而言,这一模型的训练规模和数据集的规模都比较大,这使得其性能表现相较于之前的算法更加优秀。
与BERT对比
从模型上来说,BERT并不使用标准的语言模型,而是采用带有掩码的语言模型,即完形填空。在完形填空任务中,一个句子中间的一个单词被挖去,然后让你去猜测这个单词。在这个任务中,我们可以看到挖去的单词之前和之后的单词,因此我们可以使用Transformer的编码器来完成这个任务,编码器可以看到所有单词
但是使用编码器和解码器并不是GPT和BERT的主要区别,实际上,GPT选择了一种更加困难的目标函数,即从前面的一段文本预测接下来的一个单词,这比完形填空要更具挑战性。举个例子,如果我给你股票的历史价格信息,你可以预测明天的股价,但是如果我不告诉你昨天的股票价格,让你去预测昨天的价格,那么这个任务就更难了。因为预测一个开放式的结局,要比预测一个中间状态难很多,所以它比完形填空更加具有挑战性。这也是为什么GPT在训练和效果方面都比BERT差的原因之一。
不过反过来思考,如果你的模型可以真正预测未来,那么你将比通过完形填空训练的BERT模型更加强大。这就是为什么GPT的作者需要不断地扩大模型规模并进行不断尝试,才能最终实现类似于GPT-3这样效果非常出色的经验模型。这也是之前提到的为什么作者选择了一条更加困难的技术路线,但同时也有更高的天花板。这就是预训练模型。因此,我们可以说GPT就是Transformer的一个解码器。
从参数上和实验结果上来说,BERT base使用了12层,每层有768维,这是为了与GPT进行比较。BERT Large则将层数翻了一倍,宽度增加了1.3倍,复杂度是BERT base的三倍。为什么BERT能做到三倍复杂度呢?主要是因为BERT使用了更大的数据集。BERT使用了包括GPT的BookCorpus的数据集在内的8亿个词,以及Wikipedia数据集中的20亿个词。因此,BERT的数据集大小大约是GBT的四倍。在这个数据集上,BERT训练了一个比GPT大三倍的模型。BERT的实验结果表明,BERT base比GPT的模型表现要好,平均精度达到了75.1,而BERT large的平均精度则达到了79,如果再增加模型大小,BERT的平均精度可以提高到82.1。