如何训练GPT?
如何训练GPT?
2023微软开发者大会Microsoft Build 2023上,Open AI联合创始人Andrej Karpathy做了一个题为《State of GPT》的演讲,其中他首先直观地介绍了GPT的训练流程的各个阶段,然后展示了如何使用GPT来完成任务并给出了直观的示例。
GPT大模型的训练流程
GPT大模型的训练流程可粗略分为四个阶段:预训练、监督式微调、奖励建模、强化学习。这四个阶段按顺序进行,每个阶段都有各自的数据集,每个阶段也有各自用于训练神经网络的算法。
所有阶段中,预训练阶段所需的计算量是最大的,可以说99%的训练计算时间和浮点运算量都集中在这个阶段。因为这一阶段需要处理超大规模的互联网数据集,可能需要数千GPU构成的超级计算机工作几个月时间。其它三个阶段都算是微调(fine tuning)阶段,所需的GPU数量和训练时间都少得多。
预训练阶段
预训练阶段的目标是得到一个基础模型。首先第一步:数据收集。这一阶段需要海量的数据,下面给出了一个例子,这是来自Meta的LLaMA模型的数据混合(data mixture)方法:
接下来,对收集到的数据进行预处理,这一步也被称为「token化」。简单来说,这就是一个转译过程,即把原始文本转译成某种整数序列,因为这种整数序列就是GPT实际工作时所操作的本地表征。
从文本到token和整数的转译过程是无损的,而具体执行这一过程的算法有好几种。
如下图所示,使用一种名为字节对编码(byte pair encoding)的技术,其工作方式是迭代式地合并短文本块并将它们分组成token。最后实际输入Transformer的就是那些整数序列。
接下来的预训练过程大致是这样的。首先会把token分批组成data batch,这些分配数据构成数组,再被输入到Transformer中。这些数组的大小为B×T;
- B是分批大小,即堆叠的独立样本的行数;
- T是最大上下文长度。
如下图:上下文长度T仅为10,但实际模型的T可达到2000或4000乃至更长。也就是说,实际模型的一行数据可以非常长,如一整个文档。我们可以将许多文档打包到各行中,并用这些特殊的文本结束token<|endoftext|>来分隔它们。简单来说,这些token是告诉Transformer新文档开始的位置。如图中的4行文档就转换成了底部的4×10的数组。
接着,需要将这些数字输入到Transformer。如下图,这里我们仅看其中一个单元格(绿色),实际上每个单元格都会经历同样的处理流程。这个绿色单元格会查看其之前的所有token,即所有黄色单元格的token。我们要将这里的全部上文输入到Transformer神经网络,Transformer则需要预测出该序列的下一个token,即图中的红色token。
为了给出准确的预测,神经网络需要调整其上百亿个参数。每次调整后,神经网络对每个单元格token的预测分布就会不同。
例如:如果词汇库的大小为50257个token,那么我们就需要同样多的数字,以便得到下一个token的概率分布,其预测了下一个token的可能值及相应概率。
如下图,下一个单元格应该是513,因此就可以将其用作监督源来更新Transformer的权重。我们可以并行地对每个单元格采取同样的操作。我们不断更换数据批,努力让Transformer有能力正确地预测序列的下一个token。
实例
《纽约时报》用莎士比亚作品训练的一个小型GPT。下面给出莎士比亚作品中的一小段,以及在其上训练GPT的情况。
下图,在GPT初始化时,权重是完全随机的,所以其输出结果也是完全随机的。随着时间推移,训练时间越来越长,GPT不断迭代,模型给出的结果样本也就越来越连贯通顺了。最后,可以看到Transformer学到了一些有关词的东西,也知道应该在哪些地方放置空格了。
实际预训练过程中,要通过一些量化指标来确定模型迭代中的表现变化。一般来说,研究者监测是损失函数。损失低说明Transformer更可能给出正确预测,即序列中下一个整数是正确值的概率更高。
预训练其实就是一个语言建模过程,这个过程的训练时间可长达一个月。之后,GPT学到了一个非常强大的通用型语言表征。然后,我们可以针对具体的下游任务高效对其进行微调。
例如:如果下游任务是情绪分类。过去,你采用的方法可能是收集大量标注好「正面」或「负面」情绪的样本,然后训练一个NLP模型。
但现在的新方法不需要预先做情绪分类了,你只需要拿一个预训练过的大型语言模型,然后只需要少量示例样本,就能非常高效地针对你的具体任务对模型进行微调。这对实际应用来说非常有用。那么为什么预训练后的大型语言模型(LLM)只需要简单微调就能用呢?这是因为语言建模过程本身就已经涵盖了大量任务 —— 模型为了预测下一个token,必须理解文本的结构以及其中内含的各种不同概念。
这就是GPT-1。而GPT-2,甚至可以不用微调就能非常有效地让这些模型执行prompt。这些语言模型的训练目标是完成文档,因此用户实际上只需通过编排适当的虚假文档,就可以诱导模型执行具体任务。
例如下图中,给出了一篇文章,用户想完成的任务是做相关的问答。因此,只需要在文章后面加几个有答案的问答(这被称为few-shot prompt),然后再提问。由于Transformer的目标是完成这个文档,也就相当于回答了问题。这个例子是用prompt来调教基础模型,使其相信它在模仿一个文档,结果却完成了问答任务。
Karpathy认为,以提供prompt替代微调的方式昭示着大型语言模型的新时代。这让基础模型本身就足以应对许多不同类型的任务。也因此,相关领域的研究前沿就转向了基础模型的进化。各大研究机构和企业都在打造自己的基础大模型。不过这些模型并不都是公开可用的,比如OpenAI一直没有发布GPT-4基础模型。我们通过API调用的GPT-4模型其实并不是基础模型,而是一个助理模型(assistant model)。
GPT-3基础模型可通过DaVinci API使用,GPT-2基础模型也是公开的,用户甚至可以在GitHub上找到其参数权重配置:https://github.com/openai/gpt-2。不过总体而言,目前最开放的基础模型还是Meta的LLaMA系列模型,但该系列也没有授权给商业使用。
要指出一点:基础模型不等于助理模型。基础模型不会回答用户提问,它们只会完成文档。所以如果你对基础模型说:「写一首关于面包和奶酪的诗」,它只会把你的要求看成一个文档,然后试图完成它。
但是,可以通过适当的prompt诱导基础模型写诗,如下图右侧所示。我们还可以诱导模型变成助理,当然,需要创建一些特定的少样本prompt,使其看起来像是人类与助理交换信息的交互过程的文档。
如下图,你只需要在文档结尾处附上你的提问,基础模型就能在一定程度上化身为一个有用的助理,给出某个答案。但这个过程并不非常可靠,实践效果也不好。
监督式微调阶段
为了打造出真正的GPT助理,需要另外的方法,即监督式微调(supervised fine tuning,即SFT)
监督式微调阶段,需要收集少量但高质量的数据集。OpenAI的方法是以人工方式收集由prompt和理想响应构成的数据。这些数据需要不少,一般需要几万个。
然后,继续在这些数据上执行语言建模。算法不变,只是换了训练数据集:从大量低质量的互联网文档换成了少量高质量的问答式「prompt - 响应」数据。这个训练过程完成后,就得到了一个SFT模型。部署这些模型就能得到助理,它们已经能完成一定程度的工作。
如下图,这是人类合同工写出的数据,其中有一个prompt,然后人类再写出理想的响应。理想的响应不是人类随意发挥的,而是需要遵循许多规则(如上右图),其中有格式上的要求并且要保证给出的答案有用、真实可信且无害。
奖励建模阶段
接下来还需要基于人类反馈的强化学习(RLHF),其中包含奖励建模阶段和强化学习阶段。
奖励建模阶段,需要将数据收集转变成比较的形式。
如下图:对于同样的prompt,要求助理写一个能检查给定字符串是否为回文的程序或函数。再使用已经训练好的SFT模型生成多个结果,这里给出了三个。然后,再让人类给这些结果排名。
这事做起来可不简单,要是让人类来完成一个prompt,可能需要耗费几个小时时间。
现在假设排名完成了,然后就需要在这些结果的所有可能配对上执行类似二元分类的操作。
如下图,具体的做法是这样的:将prompt按行排列;这里的三行prompt是一样的,但完成的结果不同,即图中黄色token(来自SFT模型)。然后,在其后添加一个特殊的奖励读出token。这样,只需要在绿色token位置对Transformer执行监督,就能使Transformer预测出某个奖励,从而判断prompt的完成结果是否优良。
这就是让Transformer猜测每个完成结果的质量。当其猜测完每个不同结果的质量后,开发者就可以动用已有的基本真值(ground truth)强行让某些结果的质量分数高于其它结果,从而使模型的奖励预测结果与人工给出的基本真值保持一致。这个过程,可以通过一个损失函数完成。
强化学习阶段
有了奖励模型之后,GPT依然还不能成为一个有用的助理,但奖励模型却对后面的强化学习阶段很有用,因为奖励模型可以评估任意给定prompt的任意完成结果的质量。
强化学习阶段做的事情就是基于奖励模型,使用强化学习算法对大量prompt对应的结果进行评分。
以下图一个prompt为例,将SFT模型完成的结果(黄色)排列成行,然后在后面加上奖励token(绿色)。这些奖励来自奖励模型,并且已经固定不变。现在,用同样的语言建模损失函数,只是现在是在黄色token上训练,并根据奖励模型指示的奖励来重新权衡语言建模目标。
- 如在第一行,奖励模型认为这个完成结果的评分相当高。因此,模型在第一行采样的所有token都会得到强化,也就是在未来会有更高的概率被采用。
- 对比之下,奖励模型不喜欢第二个完成结果,给了负分评价,因此该行的所有token在未来出现的概率就会降低。
如此这般在许多prompt上操作一遍又一遍,经过许多数据批次,就能得到一个创建黄色token的策略。依照这个策略,所有完成结果都能被奖励模型给予高分。
这就是RLHF的训练流程。最后得到的模型就可以部署成应用了。
RLHF
OpenAI为什么要使用RLHF呢?ChatGPT是一个RLHF模型,Karpathy表示,使用RLHF能让模型表现更好。根据OpenAI之前做的一些实验,可以看到使用了PPO(近端策略优化)算法的RLHF模型整体上都更好一些。当把结果提供给人类时,相比于SFT模型和通过prompt化身为助理的基础模型,人类也基本更喜欢来自RLHF模型的token。
RLHF为什么能让模型更好呢?目前AI研究界还没有找到一个得到大家认可的理论,但Karpathy还是给出了自己的见解。他认为这可能与比较和生成的计算难度之间的不对称性有关。
举个例子说明一下:假设我们要让一个模型写一首关于回形针的俳句。如果你是一位正努力创建训练数据的合同工,正在为SFT模型收集数据。那么你该怎样写出一首关于回形针的好俳句呢?你可能并不是一位优秀的俳句诗人。但是,如果给你几首俳句,你却有能力辨别它们中哪首更好一些。也就是说,比起创建一个好样本,判断哪个样本更好是简单得多的任务。因此,这种不对称性可能使得比较是一种更好的方法 —— 能更好地利用人类的判断来创造出好一些的模型。
RLHF并不总是会为基础模型带来提升!在某些情况下,RLHF模型会失去一些熵,也就是说它们会输出更加单调、变化更少的结果。而基础模型的熵更高,可以输出更加多样化的结果。
如下图中的任务,可能就更适合使用基础模型,即:生成与已有的n个示例相似的东西。这里的示例任务是:生成更多宝可梦名字。首先,用户向模型提供了7个宝可梦名字,然后让基础模型完成文档。基础模型生成了大量宝可梦名字。这些名字都是虚构的,毕竟宝可梦并不真实存在。Karpathy认为这类任务使用基础模型会得到更好的结果,因为基础模型的熵更高,给出的结果既与之前的示例相似,又更加多样化和炫酷。
助理模型排名
现在,用户可以使用的助理模型已有不少了。伯克利有个团队正对许多助理模型进行排名并给出了基本的ELO评分。如下图:现目前最好的模型是GPT-4;Claude和GPT-3.5紧随其后。有些模型公开提供模型权重,比如Vicuna、Koala等。在这个榜单中,前三名都是RLHF模型,其它模型基本都是SFT模型。