广州网站建设 易点,宠物医院网站开发,建模师的就业前景,wordpress升级后编辑文章很慢时间轴 GPT 首先最初版的GPT#xff0c;来源于论文Improving Language Understanding by Generative Pre-Training#xff08;翻译过来就是#xff1a;使用通用的预训练来提升语言的理解能力#xff09;。GPT这个名字其实并没有在论文中提到过#xff0c;后人将论文名最后…时间轴 GPT 首先最初版的GPT来源于论文Improving Language Understanding by Generative Pre-Training翻译过来就是使用通用的预训练来提升语言的理解能力。GPT这个名字其实并没有在论文中提到过后人将论文名最后三个单词的首字母拿出来就将其简称为GPT。
读前先问 这篇论文大方向的目标是什么 摘要第一句话就提到自然语言理解中有很多任务比如文本蕴涵、问答、情感相似度评估和文档分类等等。据此再深入想一下其实所有这些任务的根本目的是想让模型理解语言想要表达的意思并做出相应的回应。 这个方向目前有什么问题 训练模型需要数据虽然文本语料库很丰富但是大部分都是未标注的数据针对特定任务的标注数据很少导致并不能充分发挥模型的性能。 这篇论文要解决什么问题 大量未标注数据没有得到利用而少量标注数据又不够用。 为什么会有这些问题 互联网上的各种文本信息太多了GPT-3的训练数据集就达到了45TB但是数据标注的成本是很高的而且有一定的限制中国人只能标中文数据不一定能标英文的数据而图像标注中中国的猫和外国的猫并没有什么不一样。我大二的时候还给达摩院做过外包干的就是ASR语音识别标注标一小时的数据好像就几块钱。 作者是怎么解决这些问题的 GPT的解决方案就是先在没有标注的数据上预训练一个语言模型然后在有标注的数据上再针对特定任务进行微调。在微调期间还使用了任务感知进行输入的转换后面详解尽量减少了对模型架构的修改。 什么是语言模型 简单讲就是单字接龙。 具体来说就是给它“任意一段长的上文”模型会据此生成“下一个字”。 语言模型最常见的应用就是手机输入法它会根据你当前的输入给出可能的后续输入。 语言模型每次会将预测的新的词再添加到输入序列最后作为下一次的输入这也是一种称为自回归的想法。 怎么验证论文的解决方法是否有效 摘要中提到通过这种预训练微调的方式可以让模型在特定任务上有巨大的增益并且在很多自然语言理解的基准测试上都取得了很好的效果刷新了12项任务中的9项SOTA。
介绍
深度学习模型训练需要大量的标注数据这实际上限制了其本身在各个领域的发展而一些研究表明通过在大量未标注数据上通过无监督学习一个很好的表征可以提升模型的性能。一个最典型的例子就是词嵌入模型。
怎么样更好的利用未标注数据进行无监督学习
使用未标注的文本有一些困难
不知道用什么样的优化目标学习文本表征最有效不知道怎么将学到的文本表征信息传递到下游的子任务。
在这篇论文中作者就提出了一种两阶段方法先用未标注数据进行预训练再用标注数据进行微调。预训练阶段的目标就是通过语言模型学习通用的文本表征可以尽量无损的迁移到下游任务中。
训练框架
无标签数据无监督预训练
假设我们有一段文本里面每一个词表示为 U { u 1 , … , u n } \mathcal{U}\left\{u_{1}, \ldots, u_{n}\right\} U{u1,…,un}语言模型要根据 i i i前连续 k k k个词 u i − k , … , u i − 1 u_{i-k}, \ldots, u_{i-1} ui−k,…,ui−1预测第 i i i个词 u i u_{i} ui出现的概率因此目标函数就是最大化似然估计 L 1 ( U ) ∑ i log P ( u i ∣ u i − k , … , u i − 1 ; Θ ) L_{1}(\mathcal{U})\sum_{i} \log P\left(u_{i} \mid u_{i-k}, \ldots, u_{i-1} ; \Theta\right) L1(U)∑ilogP(ui∣ui−k,…,ui−1;Θ)。其中 k k k表示上下文窗口大小的超参数是模型输入序列的长度序列越长网络看到的东西就越多。 Θ \Theta Θ模型采用了Transformer中的解码器通过随机梯度下降进行训练。 Transformer中编码器与解码器的区别 编码器在对第i个元素抽取特征时能够看到序列中的所有元素。 解码器因为掩码的存在导致在对第i个元素抽取特征时只能看到当前元素和之前的序列。 详细解释如果要预测 u u u这个词的概率就把 u u u之前的 k k k个词拉出来记为 U ( u − k , … , u − 1 ) U\left(u_{-k}, \ldots, u_{-1}\right) U(u−k,…,u−1)然后进行词嵌入投影再加上一个位置信息编码就得到第一层的输入 h 0 U W e W p h_{0} U W_{e}W_{p} h0UWeWp。
接下来要做 n n n层一样的Transformer块 h i transformer-block ( h i − 1 ) ∀ i ∈ [ 1 , n ] h_{i} \text{transformer-block}\left(h_{i-1}\right) \forall i \in[1, n] hitransformer-block(hi−1)∀i∈[1,n]。 拿到最后一个Transformer块的输出再做一个Softmax就得到概率分布 P ( u ) softmax ( h n W e T ) P(u) \text{softmax}\left(h_{n} W_{e}^{T}\right) P(u)softmax(hnWeT)。 GPT和BERT的区别 ● BERT做的任务类似于完形填空用的是自注意力层所以在预测的时候既能看到之前的词也能看到之后的词对应了Transformer的编码器。GPT在预测的时候只能看到当前词及其之前的词用的是带掩码的自注意力层对应了Transformer的解码器。 ● 对于目标函数的选取GPT选择的是一个更难的目标——预测未来难度要比完形填空更大。这也是一开始GPT的效果不如BERT的效果的原因之一 ● GPT选择去解决更大更难的问题因此要出效果更难一些。Transformer和BERT来源于Google一开始想解决的问题其实都比较小比如Transformer最开始提出其实是要解决机器翻译的问题BERT则是将计算机视觉中先预训练模型再微调子任务的套路搬到了自然语言处理中单纯为了提升模型的效果。 有标签数据的有监督微调
简单讲给一个长度为 m m m的词序列然后知道序列的标签是 y y y以此进行训练。
详细解释把整个序列放入预训练好的模型中然后拿最后一个Transformer块的输出 h n m h_{n}^{m} hnm之后乘以一个输出层 W y W_{y} Wy最后再做一个Softmax就得到了预测标签的概率 P ( y ∣ x 1 , … , x m ) softmax ( h l m W y ) P\left(y \mid x^{1}, \ldots, x^{m}\right)\operatorname{softmax}\left(h_{l}^{m} W_{y}\right) P(y∣x1,…,xm)softmax(hlmWy)。微调任务中所有带标签的序列对都输入模型计算真实标签的概率然后做最大似然估计 L 2 ( C ) ∑ ( x , y ) log P ( y ∣ x 1 , … , x m ) L_{2}(\mathcal{C})\sum_{(x, y)} \log P\left(y \mid x^{1}, \ldots, x^{m}\right) L2(C)∑(x,y)logP(y∣x1,…,xm)。
在做微调的时候其实有两个目标函数第一个就是语言模型的目标函数给定一个序列然后预测序列的下一个词第二个是给定一个完整的序列然后预测序列对应的标签。
作者发现将语言模型作为微调的辅助任务一方面可以提升模型的泛化能力另一方面可以加速模型收敛。
所以有标签数据的有监督微调最终优化的目标函数就是 L 3 ( C ) L 2 ( C ) λ ∗ L 1 ( C ) L_{3}(\mathcal{C}) L_{2}(\mathcal{C}) \lambda * L_{1}(\mathcal{C}) L3(C)L2(C)λ∗L1(C)其中 λ \lambda λ是超参数。
模型架构
GPT使用了12层带掩码自注意力头的Transformer解码器维度768带12个注意力头掩码可以让模型看不见未来的信息得到的模型泛化能力更强。序列长度为512位置编码的长度是3072。模型使用Adam进行优化GELU作为激活函数最大学习率是2.5e-4batchsize为64训练了100个epoch。
数据使用BPE编码有40000个字节对用ftfy library2清理原始文本标准化了一些标点符号和空格然后用spaCy tokenizer。
任务感知的输入变换
知道了微调任务是什么形式之后接下来要考虑的就是怎么样把NLP中各种各样的子任务表示成我们想要的形式——一个序列加一个标签。
文本分类任务给定一段文本判断所属的标签。在文本开始前放一个表示开始的token在结束后放一个表示抽取的token通过Transformer之后将最后一个token抽取的特征通过一个线性层投影到多分类标签。文本蕴含任务给定一个前提然后提出一个假设判断假设的内容是否包含在前提中。在文本开始前放一个表示开始的token然后两段话中间放一个表示分隔符的token最后放一个表示抽取的token同样通过Transformer之后将最后一个token抽取的特征通过一个线性层投影到二分类标签。文本相似判断给定两段话判断两段话表示的意思是否相似。因为相似是一个对称的关系A和B相似那么B和A也是相似的但是在语言模型中序列是有先后顺序的所以论文中做了两个序列。第一个序列是Text1在前Text2在后第二个序列是Text2在前Text1在后。两个序列分别通过Transformer之后将最后一个token抽取的特征加在一起再通过一个线性层投影到二分类标签。选择题给定问题和多个选项选择认为最正确的选项。如果有N个选项就构造N个序列问题在前选项在后。每个序列分别通过Transformer和线性层给每一个选项算一个置信度最后算一个Softmax。
虽然每个任务的目标不一样但是都可以构造成一个序列的形式然后通过预训练完的Transformer模型进行下游任务。
实验
无监督训练数据集
在无标签数据无监督预训练阶段作者使用了BooksCorpus数据集训练语言模型这个数据集包含了7000多本没有发布的书籍含有很多长文本能够让模型学习更长的上下文依赖关系。因为书籍没有发布所以很难在下游数据集上见到更能验证模型的泛化能力。
有监督微调数据集
有监督未微调阶段的训练参数大部分跟无监督预训练阶段一致。分类器增加了一个比例为0.1的Dropout层。对于大部分下游任务学习率设置为6.25e-5batchsize设置为32。在有监督微调数据集上快速训练了3个epoch。
有监督微调阶段用到的数据集就比较多了主要包括四块自然语言推理、问答、语义相似度和分类。 自然语言推理任务上的实验结果
问答和常识推理任务上的实验结果
语义相似度和分类任务上的实验结果
分析 模型层数的影响
越多越强悍。
Zero-Shot能力
直接将预训练好的模型不经过监督微调直接执行任务。
横轴表示训练次数纵轴表示相对任务表现0就表示随机猜的基线1就表示当时的SOTA结果。
在没有见过数据的Zero-Shot任务中GPT的模型要比基于LSTM的模型稳定且随着训练次数的增加GPT的性能也逐渐提升表明GPT有非常强的泛化能力能够用到和有监督任务无关的其它NLP任务中。
总结
在这篇论文中介绍了一种在自然语言理解中先用未标注数据进行预训练再用标注数据进行微调的框架。通过在大量文本语料库上进行预训练模型可以获得令人意想不到的世界知识和处理长文本依赖的能力并且可以迁移到下游任务中。
其实我觉得重点是发现了GPT的零样本推理能力这也是后面GPT-2和GPT-3的主要卖点。
GPT-2
GPT发表的4个月后Google发表了BERT不同的是BERT采用的是Transformer的编码器结构而且BERT做了两个模型BERT-BASE的模型深度和宽度跟GPT一样而BERT-LARGE的参数量是BERT-BASE的三倍效果也比GPT要更好。 BERT效果更好的原因一方面是模型更大了另外一方面是采用的数据集也更大了。那OpenAI就很不爽了估计心想不过就是把模型和数据集都增大了而已我上我也行。但是单纯把之前的工作拿过来炒冷饭再加点料没什么意思而且估计是没打过因为GPT-2的论文里并没有直接把GPT-2的效果跟BERT的效果放在一起对比的内容所以论文就换了一个思路转而说明GPT-2具有Zero-Shot的能力。 读前先问
这篇论文大方向的目标是什么 让模型理解语言想要表达的意思并做出相应的回应。这个方向目前有什么问题 自然语言处理任务例如问答、机器翻译、阅读理解和摘要通常需要对任务特定数据集的监督学习来训练。问题是一方面会让模型只能处理特定的任务另外一方面特定的数据集也需要收集和标注。这篇论文要解决什么问题 如何仅利用未标注数据就能训练出具有多任务处理能力的模型。为什么会有这些问题 文本信息太多标注数据太贵。作者是怎么解决这些问题的 收集了一个包含百万网页的数据集WebText只在这个数据集上进行预训练不进行任何监督学习也能让模型学会各种自然语言处理的任务。怎么验证论文的解决方法是否有效 摘要中提到15亿参数的GPT-2模型在零样本推理的设定下已经能够在8个测试数据集中的7个取到SOTA的效果。
介绍
现在的机器学习系统虽然在很多任务上的表现都很强悍但它们都是通过大数据集、大模型和监督学习训练出来的这就导致这些系统对于数据分布的变化和任务的变化会有些脆弱和敏感。模型的泛化能力不够强也就是我在任务A数据集上训练的模型没有办法直接用在任务B上所以现在的系统只能算是一个领域的专家而不是一个全才。OpenAI的目标一直是做通用人工智能因此他们也希望训练一个通用的模型可以执行各种任务而不需要人工再去标注数据集。
作者猜测在单个数据集上进行单个任务的训练可能是造成当前系统泛化性不强的原因之一。因此为了提高模型的泛化性和鲁棒性应该在多个领域的多个任务上同时训练和评估模型的性能也就是多任务学习。
但是在NLP领域多任务应用的并不多更多的还是采用预训练模型微调的套路。这样还是有两个问题①针对每个下游任务还是需要重新训练②还是需要收集有标签的数据。
GPT-2还是在做语言模型但是在做下游任务的时候采用了Zero-Shot的设定这个设定的意思是说在下游任务中不需要修改模型架构不需要任何的标注信息也不需要重新训练。
方法
GPT-2和GPT采用的模型架构是一样的不同点在于对下游任务数据的处理。GPT中将下游任务的数据进行了标注和处理加入了一些特殊的token表示开始、分隔和提取这些token在预训练阶段模型是没有见过的因此微调阶段模型重新训练之后才会认识。
在Zero-Shot的设定下做下游任务时模型不能再被调整因此就没有办法再引入一些新的token。换句话讲下游任务的输入在预训练阶段应该都见过这就要求模型的输入在形式上要更接近人类的自然语言。
在语言模型中只有一个学习任务给定输入来预测输出的概率 p ( o u t p u t ∣ i n p u t ) p(output|input) p(output∣input)。通用系统应该能够执行许多不同的任务即使输入相同但是任务不同输出应该也是不同的因此它的目标就变成了给定输入和任务来预测输出的概率 p ( o u t p u t ∣ i n p u t , t a s k ) p(output|input, task) p(output∣input,task)。
这个地方作者给了两个例子
机器翻译。如果你想将英语翻译成法语那么输入可以表达为(translate to french, english text, french text)。这个输入就是prompt也可以叫提示词。阅读理解。输入可以表达为(answer the question, document, question, answer)。
此方法并不是GPT-2论文中首次提出的至于为什么可以这么做作者也花了很长一段去解释。大概意思就是说如果你的模型足够强大见过的语料足够多那么它就可以理解提示词表达的意思。另外一个原因可能是与这些提示词类似的表达原本就在训练语料中出现过因此模型已经见过多次了。 训练数据集
作者希望训练一个通用的模型因此数据集也必须包含各种领域的各种任务。 Common Crawl是一个公开的网页抓取项目它从互联网上获取各种各样近乎无限的文本但是数据质量太差信噪比太低毕竟很多网页中的信息是没有高质量文本的。
GPT-2一开始也在Common Crawl数据集上做过实验但是结果并不好因此最终并没有采用这个数据集而且自己又搞了一个网页爬虫去爬了Reddit。至于Common Crawl后面在训练GPT-3的时候还是采用了的。
GPT-2的训练数据集采用的是Reddit这是一个新闻聚合平台它的形式是每个人都可以提交自己感兴趣的网页然后别的用户可以投票也可以发表自己的意见投票会产生一个叫karma的东西karma越高说明越多人觉得这个网页有价值。GPT-2中就将至少有3个karma的网页都爬下来有4千5百万个链接整理成了一个文本数据集WebText其中包含了8百万篇文档一共有40GB。数据集也做了一些清洗去掉了维基百科的文档因为这些内容可能和测试集数据有重叠。
模型
有了更大的数据集之后就可以训练更大的模型了作者设计了4个模型。
第一个模型的规模其实跟GPT是一样的也跟BERT-BASE是一样的第二个模型的规模就跟BERT-LARGE是一样的在此基础上作者又训练了两个更大的模型。
实验
GPT-2的实验并没有直接跟GPT或BERT进行对比估计是比不过但是它换了一个思路发现GPT-2的Zero-Shot能力非常强因此实验这部分GPT-2对比的都是别的同样做Zero-Shot的工作。 当然针对GPT中的几个任务阅读理解、翻译、摘要和问答GPT2中也还是做了对应的实验的。横轴表示的模型的规模纵轴表示相应任务的指标。可以发现GPT-2在前面三个任务上的表现还算不错在问答任务上还差一点意思。但是可以发现的话随着模型规模的增大效果也是在上升的因此还是有很大的提升空间。 总结
GPT-2这篇论文证明了在足够大也多样化的数据集上无监督训练的语言模型依然能够在多个领域和数据集上表现良好即使是在Zero-Shot的设定下8个测试任务中也有7个达到了SOTA的效果。这也一下打通了GPT系列的任督二脉到了GPT-3就开始狂飙了。
GPT-3
GPT-2虽然提出发现了一个非常有意思的现象也就是预训练模型具有Zero-Shot能力但是它的效果还是差强人意因此GPT-3就是为了解决GPT-2效果不大行的问题。GPT-3在Zero-Shot的设定上也退了一步并没有追求完全的Zero-Shot从论文题目上也可以看出来它追求的是Few-Shot。Few-Shot的意思是说提供少量的学习样例就可以让模型掌握新的知识。
GPT-3是一篇技术报告并不是论文。那我们就跳过读前先问了 摘要
OpenAI训练一个名叫GPT-3的自回归语言模型有1750亿个可学习的参数比之前任何非稀疏的语言模型要大了10倍。因为模型规模巨大下游任务如果还要微调的话成本会非常高因此GPT-3对于所有的子任务都不用做任何的梯度更新或微调。GPT-3在很多NLP的数据集上取得了很好的成绩包括翻译、问答、完形填空等等并且可以通过Few-Shot学会新的任务。
介绍
背景近几年在NLP领域预训练模型下游任务微调的模式越来越流行但是这有一个最大的限制下游任务需要标注数据集和微调。
但是去掉这个限制是有必要的
从实际应用的角度来看每一项下游任务都需要大量的标注数据集但是下游任务数不胜数如果每个任务都要收集数据集并微调的话耗时耗力也不可持续在下游任务上微调之后的效果好并不一定能说明预训练的大模型具有泛化性有可能是过拟合了预训练数据集中包含的一部分微调任务的数据导致在微调任务上的效果是比较好的。但是同一个任务换一个语种可能效果就没有那么好了。因此如果下游任务不允许做微调那么拼的就是预训练模型的泛化性从人类的角度看我们去做一个新的任务时并不需要巨大的数据集数据集可能给一两个例子看一看就学会了。
作者提出了这些问题之后就给出了自己的解决方案Few-Shot。
GPT-3是一个有1750亿参数的模型然后作者还训练了一系列不同大小的模型来进行对比对于每个任务采用三种办法进行评估
Few-Shot对于每个任务提供10~100个参考样例One-Shot对于每个任务只提供1个参考样例Zero-Shot对于每个任务不提供任何参考样例。 x x x轴表示的是语言模型的参数量大小 y y y轴是准确率图片中的虚线是子任务的指标实线是所有任务的平均。从一些虚线中也可以看出很多任务的能力都是在模型达到了一定规模之后才迅速提升的也就是涌现。
方法
在方法这一块首先对比了一下传统的微调和Few-Shot、One-Shot、Zero-Shot的区别。 模型架构
GPT-3的模型架构跟GPT-2是一样的还是Transformer的解码器结构然后也做了一丢丢修改比如换用了Sparse Transformer。
这些参数怎么定出来的作者说他是按照另外一篇论文里的缩放原则增加层数的时候增加了宽度因为计算复杂度跟宽度是平方关系跟层数是线性关系但整体来说GPT-3的模型是比较偏扁一点的。
训练数据
基于CommonCrawl但是做了一些处理
将CommonCrawl的样本作为负例之前训练GPT2的数据集作为正例训练一个分类模型然后再将这个模型应用于CommonCrawl如果一篇文章的得分偏向于正例的话就认为这个网页内容是高质量的在数据集内部和跨数据集之间做了文档级的模糊去重又加入了一些收集的高质量数据集提升数据集的多样性 训练过程
接下来就是最可气的部分——模型训练过程1750亿参数的模型分布式训练肯定是非常麻烦的我当时分布式训练一个35亿参数的模型花了差不多一个月的时间研究然后中间还有各种坑结果他在论文里6、7句话就把训练过程一笔带过了。
根据前人的研究越大的模型应该使用越大的batchsize但是需要更小的学习率。训练过程中也采用了数据并行和模型并行然后是在一个高带宽的V100 GPU集群上训练的。 然后他说是在附录中有详细的参数但真的就只是参数说了下Adam的参数、学习率和窗口大小等等也没有说具体分布式训练这一块怎么切分或者用了什么框架。
实验结果
GPT-3有特别多的作者这是这些作者并不是挂个名而已的实际上在论文的最后就有说明每一位作者的贡献大部分人都是来对GPT-3做各种实验的因此实验结果这一部分特别多。
不同大小的模型在训练的时候跟计算量的关系。x轴表示的是计算量y轴表示的是验证集的损失每一根线表示的是一个参数的模型。
完形填空 x轴表示的是模型参数规模y轴表示的是在Lambada测试集上的准确率。但是有几个奇怪的地方我没有想通
为什么模型参数量比较小的时候Few-Shot和One-Shot的效果比Zero-Shot要差那么多为什么One-Shot的效果一直比Zero-Shot的效果要差1.3B的Few-Shot为什么会突然间出现一个波动
问答 x轴表示的是模型参数规模y轴表示的是在TriviaQA测试集上的准确率。这个就很符合预期随着模型规模的增加效果也一直增加而且Few-Shot的效果要比One-Shot要好One-Shot的效果要比Zero-Shot的效果要好。
翻译 x轴表示的是模型参数规模y轴表示的是翻译任务的BLEU。这里并没有再对比Zero-Shot、One-Shot和Few-Shot而是对比的不同语言之间的差距。
数学 后面的一些实验结果也都大差不差作者还试了让GPT-3参加SAT考试美国高考以及生成一些新闻稿效果都非常的惊艳。
局限性和影响力
作者在这里花了很大的篇幅讨论GPT-3的一些局限性和可能造成的影响不过并不涉及很多技术所以在这不再讨论。
总结
初代GPT-3展示了三个重要能力
● 语言生成遵循提示词prompt然后生成补全提示词的句子。这也是今天人类与语言模型最普遍的交互方式。能力来自于语言建模的训练目标 (language modeling)。
● 上下文学习 (in-context learning): 给定任务的几个示例然后为新的测试用例生成解决方案。此能力来源及为什么上下文学习可以泛化仍然难以溯源。 直觉上这种能力可能来自于同一个任务的数据点在训练时按顺序排列在同一个 batch 中。
● 世界知识包括事实性知识 (factual knowledge) 和常识 (commonsense)。来自 3000 亿单词的训练语料库。
虽然初代的 GPT-3 可能表面上看起来很弱但后来的实验证明初代 GPT-3 有着非常强的潜力。这些潜力后来被代码训练、指令微调 (instruction tuning) 和基于人类反馈的强化学习 (reinforcement learning with human feedback, RLHF) 解锁最终体展示出极为强大的突现能力。
GPT-3.5系列
GPT-3.5 的进化树
OpenAI 发布的初代GPT-3模型索引名为davinci。然后又发布了Codex的论文这是根据120 亿参数的 GPT-3 变体进行微调的命名为Code-davinci-001。后来这个 120 亿参数的模型演变成 OpenAI API 中的Code-cushman-001。之后OpenAI 发布了指令微调 (instruction tuning) 相关的论文其监督微调 (supervised instruction tuning) 的部分对应了Instruct-davinci-beta和Text-davinci-001。
有的这两项技术之后OpenAI又在此基础上通过语言模型代码训练然后再进行指令微调的方式训练出了Code-davinci-002在此基础上又通过监督指令微调 (supervised instruction tuned) 训练出了Text-davinci-002模型最后就是通过基于人类反馈的强化学习训练除了Text-davinci-003和 ChatGPT。
我们关注Code-davinci-002和Text-davinci-002这两兄弟是第一版的 GPT3.5 模型一个用于代码另一个用于文本。它们表现出了几种与初代 GPT-3 不同的重要能力
● 响应人类指令以前GPT-3 的输出主要训练集中常见的句子。现在的模型会针对指令 / 提示词生成更合理的答案而不是相关但无用的句子。
● 泛化到没有见过的任务当用于调整模型的指令数量超过一定的规模时模型就可以自动在从没见过的新指令上也能生成有效的回答。这种能力对于上线部署至关重要因为用户总会提新的问题模型得答得出来才行。
● 代码生成和代码理解这个能力很显然因为模型用代码训练过。
● 利用思维链 (chain-of-thought) 进行复杂推理初代 GPT-3 的模型思维链推理的能力很弱甚至没有。code-davinci-002 和 text-davinci-002 是两个拥有足够强的思维链推理能力的模型。
这些能力从何而来与之前的模型相比两个主要区别是指令微调和代码训练。
具体来说
● 响应人类指令的能力是指令微调的产物。遵循指令和泛化的能力可能都已经存在于基础模型中后来只是通过指令微调解锁了这些能力而已。这主要是因为指令数据量大小比预训练数据量少了几个数量级。
● 对没有见过的指令做出反馈的泛化能力是在指令数量超过一定程度之后自动出现的T0、Flan 和 FlanPaLM 论文进一步证明了这一点
● 使用思维链进行复杂推理的能力可能是代码训练的产物。原因最初的 GPT-3 没有接受过代码训练它不能做思维链。Text-davinci-001 模型虽然经过了指令微调但第一版思维链论文报告中说它的它思维链推理的能力非常弱 —— 所以指令微调可能不是思维链存在的原因代码训练才是模型能做思维链推理的最可能原因。
CodeX
Codex 是为 GitHub Copilot 提供支持的模型精通十几种编程语言可以用自然语言生成代码。
摘要
CodeX是一个基于GPT的语言模型在GitHub公开可用的代码上进行了微调。GPT-3的创新点虽然是可以不做微调但是CodeX属于GPT-3的一个应用因此相当于做了定向应用优化。不能自己打自己的脸
CodeX其实只做了Python代码的训练而Copilot是支持多语言的因此它们并不完全一样。
作者还发布了一个评估数据集——HumanEval用来衡量从注释到代码的正确性。在这个数据集上CodeX可以解决28.8%的问题而GPT-3啥也不是GPT-J可以解决11.4%。
在现实生活中编程也不是一步到位的经常需要迭代修改因此增加了一个新的指标多次生成只要有一个能通过即算正确。通过这种不断的重复生成限定最多100次的前提下有1次通过即可Codex可以解决70.2%的问题。
介绍
在之前GPT-3的工作中作者发现模型可以根据注释生成简单的Python代码这种能力让人兴奋因为GPT-3并没有在专门的代码数据上进行训练。在本文中作者就研究了从注释生成Python函数代码的功能并通过单元测试自动评估代码的正确性。
代码生成任务与自然语言生成任务有一点不同在自然语言生成中结果通常由人工进行评估但是在代码生成中结果可以由机器来进行评估。为了准确地对模型进行基准测试作者就创建了一个包含164个带有单元测试的编程问题数据集用于测试模型对语言的理解能力、对算法的实现和解决数学问题的能力。
在评估的时候会让模型生成多个答案只要有一个能通过单元测试即算通过。如果只能生成一个答案的话120亿参数的模型能够解决28.8%的问题。为了进一步提升模型的性能作者又收集了一个数据集这个数据集跟评估模型的方式更加相近一点在这个数据集上再进行微调得到Codex-S模型此时即使只允许生成一个答案的情况下模型能够解决37.7%的问题如果允许生成100次其中只要有一个通过即算通过的情况下能够解决77.5%的问题。
因为这是一篇比较偏向于应用方面的文章而在实际编程的过程中不可能由模型生成100个答案然后由用户进行选择因此作者又提供了一个排序算法选择平均概率估计的最大值挑出第一的结果也能解决44.5%的问题。
评估框架
代码正确性判断指标
在生成序列的时候经常使用的一个指标叫BLUE这个指标看的是生成的序列和真实的序列在一些子序列上的相似度这是一个模糊匹配的指标不需要完全匹配。
但是在生成代码的任务中BLUE分数会有一些问题因为即使生成的代码和目标代码在一些子序列上一致也不代表生成的代码能够正确运行并达到预期的效果。
本文中使用的是一个叫 p a s s k passk passk的指标这里的 k k k表示模型可以生成 k k k个不同的结果其中只要有一个能够通过测试即算通过。然而直接计算 p a s s k passk passk并不是很稳定所以作者在这个地方是一次生成 n ( n k ) n \ (n k) n (nk)个样本每次从这 n n n个样本中随机采样 k k k个出来看看里面是不是有正确答案其中正确答案的个数记为 c c c。具体的计算公式 pass k : E Problems [ 1 − ( n − c k ) ( n k ) ] \text { pass } k:\underset{\text { Problems }}{\mathbb{E}}\left[1-\frac{\left(\begin{array}{c} n-c \\ k \end{array}\right)}{\left(\begin{array}{l} n \\ k \end{array}\right)}\right] pass k: Problems E 1−(nk)(n−ck) 。 验证数据集
作者在HumanEval数据集上评估函数的正确性这个数据集包含164个手写编程问题每个问题包括函数的签名、注释、函数体和若干个单元测试。这些评估的数据集必须是人工生成的因为如果采用网上找的代码很可能就已经被包含的训练数据集中了即数据泄露。
代码微调
数据收集
训练集是2020年5月从GitHub上5400万个代码仓库中收集的包含179GB的Python文件然后做了一些过滤① 可能是自动生成的② 平均一行长度大于100的③ 最大一行长度大于1000的④ 二进制文件。经过清洗之后最终数据集大小为159GB。
方法
Codex是基于GPT-3模型进行训练的但是比较令人惊讶的是在预训练模型上再进行微调并没有对最终结果带来什么明显的提升仅仅是收敛速度变快了。 因为代码的单词分布跟自然语言的文本分布不同有很多的空格、缩进和换行因此Codex在训练的时候添加了一组往外的token来表示不同长度的空格这样相比于原来表示代码的方式可以节省大约30%的token。
论文中还提到在生成代码的时候采用了核采样的方法。普通的采样每次选择Softmax之后概率最大的token这样并不能保证整个序列最终的概率最大即不是全局最优还有一个问题就是如果每次都选择概率最大的值那么每次生成的结果都是固定的。一般来说改进的方法是通过树搜索或者叫Beam Search可以维护一定数量的当前最优候选然后一直往下看计算量上会增加一点但是可以一次给出多个解。核采样还是在每个时刻对候选词都有一个概率然后我们按照概率对token进行降序保留累加概率达到0.95的所有token。
结果
因为评估指标 p a s s K passK passK是会生成多个结果的因此生成时的参数该如何设置也有讲究论文中也讨论了一下。 上图的x轴表示采样数从1~100y轴表示 p a s s K passK passK指标不同颜色的线表示生成代码时设置的参数temperature不一样temperature0表示每次都选择概率最大的结果那不管采样多少次结果都是一样的因此是一条直线。temperature越大最终生成的多个结果的多样性就越大。下图是根据上图导出的在不同采样次数下的最优temperature。 在设置最优参数的情况下作者做了个实验观察模型参数大小对 p a s s K passK passK的影响可以发现还是参数量越大模型效果越好。
接下来作者又对比了几种方法 ● 蓝色 K K K个结果中只要有1个通过即算通过 ● 橙色在原本通过注释生成代码的基础上又训练了一版通过代码生成注释的模型 ● 绿色取概率之和最大的结果 ● 红色取平均概率最大的结果 ● 紫色随机取一个
监督微调
作者认为前面从GitHub上收集的数据集中包含了很多的类实现、配置文件和数据存储文件这部分文件的内容与最终任务无关因此可能会降低的模型的性能。为了让Codex能够更好的迁移到目标任务的分布作者又收集了一个数据集这个数据集是从各种在线评测网站上爬下来的还有一部分来自持续集成的代码库。在新的数据集上又进行了一次监督微调新的模型叫Codex-S。 对比了Codex和Codex-S在不同采样数下的最优temperature。 上图对比了Codex和Codex-S模型大小对 p a s s K passK passK的影响下图对比了不同取法对 p a s s K passK passK的影响。
局限性
样本利用率不高对长文本的处理不够好对大局观的理解不够好对数学计算不太擅长
InstructGPT 标题训练语言模型使其服从人类的指令
背景GPT-3虽然掌握了各种词语搭配和语法规则还学会了编程了解不同语言之间的关系可以给出高质量的外语翻译但是还有一个问题尽管GPT-3拥有了海量的知识但回答形式和内容不受约束。因为它知道的太多了见到了一个人几辈子都读不完的资料可以随意联想会不受控制的乱说什么丑闻、脏话和幻觉等全都有可能蹦出来。所以GPT-3的能力其实是非常强悍的但是我们却很难指挥它。
InstructGPT的解决思路用优质对话模板矫正GPT-3模型。具体做法就是不再用随便的互联网文本进行训练而是把人工专门写好的“优质对话范例”喂给GPT-3再去做单字接龙以此来学习如何组织符合人类要求的回答。
举个例子当用户询问如何毁灭世界时不能让它真的回答怎么毁灭世界而要回答“这是有害的行为”。
为什么不在一开始就直接教它最正确的对话方式和对话内容呢
一方面“优质对话范例”数量有限所能提供的语言多样性不足可能难以让模型学到广泛适用的语言规律也无法涉猎各个领域。
另一方面“优质对话范例”都需要人工专门标注价格不菲。所以说不定未来有了足够多的“优质对话范例”之后就会跳过预训练这一步直接用“优质对话范例”进行监督学习。
摘要
语言模型越做越大并不意味着能让它们更好的遵循人类的指令例如大语言模型会生成一些不真实的、有毒的或没有价值的答案这是因为训练语言模型的目标函数给定前文预测后文不合适并不是遵循人类的指令换句话说模型没有与用户对齐。我们希望语言模型是有用的、真诚的并且无害的。
这篇文章中作者提出了一种通过人类的反馈进行微调的方法来将语言模型与用户意图进行对齐。在对模型的评估中13亿参数的InstructGPT模型效果比1750亿参数的GPT-3模型效果更好并且在性能损失不大的情况下有毒输出明显降低。
介绍
作者希望通过微调的方法来对齐语言模型与人类意图具体的方法就是基于人类反馈进行强化学习Reinforcement Learning from Human Feedback, RLHF。 第一步首先雇佣了40个人的标注团队专门写了很多的提示词然后将提示词发给OpenAI的API之后将符合人类意图的模型结果整理成数据集最后在这个数据集上通过监督学习来微调GPT-3。
第二步我们对模型的多个输出进行打分并排序收集成一个新的数据集通过这个数据集训练一个打分模型。
第三步通过打分模型在第一步数据集的提示词上进行强化学习微调。最终训练出来的模型就是InstructGPT。
为什么要有第一步
为了让InstructGPT遵循人类的规范。经过大规模预训练和有监督学习微调之后模型已经变得非常强悍了但是还有一些不足InstructGPT的回答可能过于模板化限制了其创造力有可能变成模板复读机。我们希望InstructGPT还能生成一些超越模板但仍符合人类对话模式和价值取向的创新性回答。
为什么要有第二步和第三步
激发更多的创意。这有点类似于试卷最后的附加题按照正常学习的模板来做的话可能并不能得出正确结果这时候就需要一些奇思妙想因此如果能有一些创新的回答就可以获得更高的分数。在这一步不再要求它按照我们提供的对话范例做单字接龙而是直接向它提问让它自由回答如果回答的很好就给予奖励如果回答的不好就降低奖励然后利用评分再去调整模型。 两步之后既不会因为模板规范限制其表现又可以引导它生成符合人类认可的优质回答。
最后对InstructGPT做了一系列的评估结果如下 ● 标注人员觉得 InstructGPT 的输出比 GPT-3 的输出明显更好 ● InstructGPT 模型在真实性方面比 GPT-3 有所改进 ● InstructGPT 与 GPT-3 相比生成有毒内容的情况略有改善但还是存在偏见 ● RLHF 根据某一个目标函数微调可能会使得在其它任务上的性能下降对齐税 ● 模型可以泛化到训练数据之外的预留数据上 ● 公共 NLP 数据集FLAN、T0并不能反映我们的语言模型是如何生效的 ● InstructGPT 对 RLHF 微调分布之外的指令也具有泛化性 ● InstructGPT 还是会犯一些简单的错误
方法与细节
数据集
提示词数据集是怎么来的
标注人员写了很多的提示词① 随意写任何问题确保多样性② 给定一个主题来写指令③ 根据用户的一些需求设计相应的提示词。基于以上数据训练了第一个InstructGPT模型。将第一个模型放在Playground中会有很多人去用然后再将这些数据采集回来再做一些筛选和切分。
基于这些提示词作者构建了三个不同的数据集然后进行微调
SFT数据集13k个样本标注人员直接去写答案然后训练SFT模型RM数据集33k个样本用来训练打分模型PPO数据集31k个样本没有人工标注了通过打分模型进行标注 任务
训练任务也有两个来源
标注人员编写的提示词数据集早期InstructGPT的API中提交的提示词数据集
训练任务也具有多样性表1中包含了不同任务的占比表2中提供了一些例子更多的例子在附录中。
人工数据标注
从UPwork和ScaleAI雇佣了一个40个人的团队来对数据进行打标签。
模型
监督学习微调SFT将GPT-3在人工标注数据集通过监督学习进行微调。奖励模型 a. 将一个60亿参数的SFT模型后面的unembedding层去掉将Softmax替换为一个线性层基于提示词和回复直接输出一个奖励值的标量。 b. 损失函数输入的标注是排序并不是实际的奖励值因此需要将排序转换为奖励值。具体来讲对一个提示词取出一对答案假设 y w y_w yw的排序比 y l y_l yl要高先把 x x x和 y w y_w yw通过奖励模型得到一个分数然后把 x x x和 y l y_l yl也通过奖励模型得到一个分数因为 y w y_w yw的排序比 y l y_l yl要高因此我们希望前一个 r θ r_θ rθ的奖励要比后一个的大然后通过一个Sigmoid函数再做一个log也就是逻辑回归的损失函数 loss ( θ ) − 1 ( K 2 ) E ( x , y w , y l ) ∼ D [ log ( σ ( r θ ( x , y w ) − r θ ( x , y l ) ) ) ] \text{loss}(\theta)-\frac{1}{\left(\begin{array}{c} K \\ 2 \end{array}\right)} E_{\left(x, y_{w}, y_{l}\right) \sim D}\left[\log \left(\sigma\left(r_{\theta}\left(x, y_{w}\right)-r_{\theta}\left(x, y_{l}\right)\right)\right)\right] loss(θ)−(K2)1E(x,yw,yl)∼D[log(σ(rθ(x,yw)−rθ(x,yl)))]。对于每个提示词会生成K9个答案每次从K里面选出来两个最终除以组合数进行标准化。强化学习PPO模型 objective ( ϕ ) E ( x , y ) ∼ D π ϕ R L [ r θ ( x , y ) − β log ( π ϕ R L ( y ∣ x ) π S F T ( y ∣ x ) ) ] γ E x ∼ D pretrain [ log ( π ϕ R L ( x ) ) ] \operatorname{objective}(\phi) E_{(x, y) \sim D_{\pi_{\phi}^{\mathrm{RL}}}}\left[r_{\theta}(x, y)- \beta \log \left(\frac{\pi_{\phi}^{\mathrm{RL}}(y \mid x)}{\pi^{\mathrm{SFT}}(y \mid x)} \right)\right] \gamma E_{x \sim D_{\text {pretrain }}}\left[\log \left(\pi_{\phi}^{\mathrm{RL}}(x)\right)\right] objective(ϕ)E(x,y)∼DπϕRL[rθ(x,y)−βlog(πSFT(y∣x)πϕRL(y∣x))]γEx∼Dpretrain [log(πϕRL(x))] a. π ϕ R L \pi_{\phi}^{\mathrm{RL}} πϕRL可学习的策略初始化的时候跟 π S F T \pi^{\mathrm{SFT}} πSFT一样 b. π S F T \pi^{\mathrm{SFT}} πSFT监督学习微调训练出来的模型 c. E ( x , y ) ∼ D π ϕ R L E_{(x, y) \sim D_{\pi_{\phi}^{\mathrm{RL}}}} E(x,y)∼DπϕRL第一项的 ( x , y ) (x,y) (x,y)来自当前的RL模型每个提示词 x x x都通过模型生成一个 y y y然后对 ( x , y ) (x,y) (x,y)进行打分最大化分数来更新模型参数 d. r θ r_{\theta} rθ是不会发生改变的并且它的训练数据分布来自于 π S F T \pi^{\mathrm{SFT}} πSFT因此 π ϕ R L \pi_{\phi}^{\mathrm{RL}} πϕRL的更新可能会导致 y y y的分布发生变化 r θ r_{\theta} rθ的估算逐渐不准因此通过KL散度 β log ( π ϕ R L ( y ∣ x ) π S F T ( y ∣ x ) ) \beta \log \left(\frac{\pi_{\phi}^{\mathrm{RL}}(y \mid x)}{\pi^{\mathrm{SFT}}(y \mid x)} \right) βlog(πSFT(y∣x)πϕRL(y∣x))控制更新幅度 e. 过于专注微调任务可能会导致模型偏移因此又从GPT-3训练数据集中采样了一些数据做语言模型损失函数 γ E x ∼ D pretrain [ log ( π ϕ R L ( x ) ) ] \gamma E_{x \sim D_{\text {pretrain }}}\left[\log \left(\pi_{\phi}^{\mathrm{RL}}(x)\right)\right] γEx∼Dpretrain [log(πϕRL(x))]如果 γ 0 \gamma 0 γ0则模型为纯PPO如果 γ ≠ 0 \gamma \neq 0 γ0则模型为PPO-ptx
结果 后面的论文中还有大量的篇幅讨论InstructGPT模型的效果和不足包括能降低多少有害输出能降低多少幻觉以及跟其它一些大模型的对比就不一一展示了总的来说就是我们比较牛逼感兴趣的可以看原论文。
总结
指令微调触发的能力 ● 指令微调不会为模型注入新的能力 —— 所有的能力都已经存在了。指令微调的作用是解锁 / 激发这些能力。这主要是因为指令微调的数据量比预训练数据量少几个数量级基础的能力是通过预训练注入的。 ● 指令微调将 GPT-3 分化到不同的技能树。 有些更擅长上下文学习如text-davinci-003有些更擅长对话如ChatGPT。 ● 指令微调通过牺牲性能换取与人类的对齐alignment。OpenAI 的作者在他们的指令微调论文中称其为 “对齐税” (alignment tax)。许多论文都报道了code-davinci-002在基准测试中实现了最佳性能但模型不一定符合人类期望。
RLHF 触发的能力 ● 翔实的回应text-davinci-003 的生成通常比 text-davinci-002长。ChatGPT 的回应则更加冗长以至于用户必须明确要求“用一句话回答我”才能得到更加简洁的回答。 ● 公正的回应ChatGPT 通常对涉及多个实体利益的事件例如政治事件给出非常平衡的回答。这也是RLHF的产物。 ● 拒绝不当问题这是内容过滤器和由 RLHF 触发的模型自身能力的结合过滤器过滤掉一部分然后模型再拒绝一部分。 ● 拒绝知识范围之外的问题例如拒绝在2021 年 6 月之后发生的新事件因为它没在这之后的数据上训练过。这是 RLHF 最神奇的部分因为它使模型能够隐式地区分哪些问题在其知识范围内哪些问题不在其知识范围内。
有两件事情值得注意 ● 所有的能力都是模型本来就有的 而不是通过RLHF 注入的。RLHF 的作用是触发 / 解锁突现能力。这个论点主要来自于数据量大小的比较因为与预训练的数据量相比RLHF 占用的计算量 / 数据量要少得多。 ● 模型知道它不知道什么不是通过编写规则来实现的 而是通过RLHF解锁的。这是一个非常令人惊讶的发现因为 RLHF 的最初目标是让模型生成复合人类期望的回答这更多是让模型生成安全的句子而不是让模型知道它不知道的内容。