微信扫码
与创始人交个朋友
我要投稿
更多相关工作:我们的工作是最近使用LLMs进行程序合成计划的一部分。我们的方法也是利用现有LLMs合成数据以训练新一代LLMs这一新兴趋势的一部分。目前,关于这种“递归训练”是否可能导致生成的LLMs适用范围变窄,学界存在争议,而也有人则提出了相反的观点。本文我们专注于一个狭义的任务,在这种情况下,在特定任务上获得比教师LLM更好的性能似乎是合理的。
我们从公开可用的Python代码数据集开始:我们使用The Stack和StackOverflow去重版本的Python子集,这两个数据集合计包含超过3500万个文件/样本,总计超过350亿个标记。我们使用GPT-4对其中一小部分文件(约10万个样本)的质量进行标注:给定一个代码片段,模型被提示“确定它对于一个旨在学习基本编码概念的学生来说的教育价值”。
然后,我们使用这个已标注的数据集来训练一个随机森林分类器,该分类器使用预训练的codegen模型的输出嵌入作为特征来预测文件/样本的质量。我们注意到,与我们在下文中广泛使用的用于生成合成内容的GPT-3.5不同,我们仅将GPT-4用于对The Stack和StackOverflow样本的一小部分进行质量标注,且使用频率极低。因此,我们认为我们对GPT-4的使用仅仅是为了避免繁琐的人工标注工作。
即使不使用下面讨论的合成数据集,我们的过滤方法也显著提高了模型性能:对于在未经过滤的Stack(去重后的Python代码)和StackOverflow上训练的3.5亿参数模型,即使在训练了96,000步(约2000亿个标记)后,HumanEval的性能也仅达到12.19%的饱和水平,而在经过过滤的子集上训练后,HumanEval的性能在36,000步后就达到了17.68%。通过在下文讨论的过滤数据集和合成教科书数据集的组合上进行训练,我们进一步将这一性能提升至20.12%(如图2.1所示)。
在创建高质量代码生成数据集时,一个主要挑战是确保示例的多样性和非重复性。这里的多样性意味着示例应涵盖广泛的编码概念、技能和场景,并且在难度、复杂度和风格上应有所不同。多样性之所以重要,有几个原因:它使语言模型接触到代码中以不同方式表达和解决问题的方法,降低了过拟合或记忆特定模式或解决方案的风险,并提高了模型对未见或新任务的泛化能力和鲁棒性。然而,实现多样性并非易事,尤其是在使用另一个语言模型生成的合成数据时。简单地提示模型生成一本编程教科书或一系列练习题,即使指令或参数有所变化,也很可能导致数据集非常单一和冗余,其中相同的概念和解决方案以微小的变化反复出现。这是因为语言模型倾向于根据其训练数据和先验知识遵循最可能或最常见的路径,并且缺乏创造力或动力去探索生成代码的替代或新颖方式。因此,需要找到合适的“技巧”,使语言模型在保持示例质量和连贯性的同时,在输出中更具创造性和多样性。受到[EL23]的启发,该研究中通过在提示中包含从固定词汇表中随机选择的单词子集,并要求这些单词以某种方式组合在生成的文本中,从而创建了一系列多样化的短篇故事。我们也寻找在提示中注入随机性的方法,以生成多样化的数据集。
合成教科书数据集:该数据集由GPT-3.5生成的Python教科书组成,包含不到10亿个标记,这些教科书是合成的,旨在为自然语言丰富的文本与相关的代码片段交替出现提供一个高质量的资源。我们进一步针对这些教科书的内容,涵盖了促进推理和基础算法技能的主题。在这里,多样性是通过为生成的教科书提供主题和目标受众的约束来实现的。以下是合成教科书中的一个示例文本:
CodeExercises 数据集:这是一个小型的合成练习题数据集,包含不到1.8亿个Python练习题和解决方案的标记。每个练习题都是一个需要完成的函数的docstring(文档字符串)。该数据集的目标是使模型能够根据自然语言指令执行函数补全任务。这个数据集也是由GPT-3.5生成的,其中实现多样性的主要手段是通过限制函数名称。对于这个特定的数据集,我们在后续章节中进行了明确的去污染和替代评估,以确保在微调过程中不会遇到与HumanEval基准测试中类似的问题。以下是一个合成生成的练习题的示例片段:
我们使用了仅解码器的Transformer模型,该模型采用了FlashAttention实现的多头注意力机制。我们还并行配置了MHA和MLP层,这一做法遵循了近期的一些模型,如CodeGen、PaLM和GPT-NeoX。我们的13亿参数phi-1模型架构包含24层,隐藏维度为2048,MLP内部维度为8192,以及32个每个维度为64的注意力头。较小的3.5亿参数phi-1-small模型包含20层,隐藏维度为1024,MLP内部维度为4096,以及16个每个维度为64的注意力头。此外,我们还使用了旋转位置嵌入,旋转维度为32。我们还使用了与codegen-350M-mono相同的分词器。除了FlashAttention外,我们的模型没有使用其他技术,如Fill-In-the-Middle(FIM)或多查询注意力(MQA),这些技术可能会进一步提升性能和效率。
在预训练和微调阶段,我们将各自的数据集连接成一个一维数组,并使用“⟨∣endoftext∣⟩”标记来分隔文件。我们在从数据集数组中切出的长度为2048的序列上进行模型训练,采用下一个标记预测损失。我们使用fp16训练和AdamW优化器,采用线性预热-线性衰减的学习率计划,以及0.1的注意力和残差丢弃率。我们使用deepspeed在8个Nvidia-A100 GPU上进行训练。我们的预训练基础模型phi-1-base在不到4天的时间内完成训练。在同一硬件上,对phi-1进行微调又额外花费了7小时。
预训练:phi-1-base模型在CodeTextbook数据集(经过筛选的代码-语言语料库和合成教科书)上进行训练。我们使用了有效批量大小为1024(包括数据并行和梯度累积),最大学习率为1e-3,并在750步内进行预热,权重衰减为0.1,总共训练了36,000步。我们选择第24,000步的检查点作为我们的phi-1-base——这相当于在我们的CodeTextbook数据集上进行了大约8个周期的训练,总共训练了超过500亿个标记。尽管这个模型的大小和计算量都不大,但它已经在HumanEval上达到了29%的准确率。
微调:phi-1是通过在CodeExercises数据集上对phi-1-base进行微调得到的。对于微调,我们使用了与预训练相同的设置,但超参数不同:我们使用了有效批量大小为256,最大学习率为1e-4,并在50步内进行预热,权重衰减为0.01。我们总共训练了6,000步,并选择了最佳检查点(每1,000步保存一次)。
图2.1显示,在小型CodeExercises数据集(<2亿标记)上进行微调后,HumanEval的改进幅度最大。CodeExercises完全由使用基本Python库的简短Python任务组成。在本节中,我们将展示一个相当显著的现象,即微调后的模型在执行微调数据集中未出现的任务时也表现出实质性的改进。这包括管理复杂的算法任务和使用外部库。这表明,我们的微调过程可能有助于模型重新组织和巩固在预训练期间获得的知识,即使这些知识在CodeExercises数据集中并未明确体现。在本节中,我们将重点定性地比较和对比我们微调后的模型phi-1与其预训练的13亿参数基础模型phi-1-base的能力。
通过我们自己创建的一个简单的Python函数,我们观察到微调后的模型在理解和遵循指令方面表现出了更高的水平。特别是,我们发现phi-1-base在处理提示中的逻辑关系时遇到了困难,而phi-1能够解释问题并正确生成答案。在这个例子中,即使我们的3.5亿参数的phi-1-small模型也显示出了一定程度的问题理解能力,尽管它给出的解决方案是错误的。我们在交互过程中始终观察到这样的趋势。
我们在这里展示,尽管我们的练习题中没有包含Pygame和Tkinter等外部库,但在CodeExercises上进行微调却意外地提高了模型使用这些外部库的能力。这表明我们的微调不仅改进了我们针对的任务,还使得从预训练中提取不相关任务变得更加容易。作为参考,图3.1显示了我们的CodeExercises数据集中包导入的分布情况。
上面的代码片段展示了一个简单PyGame程序的主循环,该程序使球在屏幕上弹跳。phi-1正确地应用了PyGame函数来更新和绘制球,按照提示进行操作。phi-1-base和phi-1-small生成的函数调用在语法上是正确的,但在语义上与任务无关。我们可以看到,phi-1-base显示出一些使用适当API调用的能力,但它未能遵循任务的逻辑,而经过微调后的phi-1-small理解了逻辑,但由于容量不足,无法学习正确的函数调用。
这三个模型的完成情况在理解提示方面存在巨大差距。phi-1-base和phi-1-small都没有使用正确的Tkinter API,而是编造了无意义的函数调用。另一方面,phi-1正确地实现了图形用户界面(GUI)和所有函数(只是没有正确复制“pewpewpew?”)。我们在附录A中提供了另外两个关于pytorch和pyplot的示例。
聊天模式示例:最后,我们展示了尽管聊天数据仅在预训练中使用,并未在微调中使用,但phi-1的聊天能力仍优于phi-1-base。
对于phi-1在HumanEval上出人意料的良好表现(见表1和图2.1),一个潜在的担忧是,这可能源于合成CodeExercises数据集的污染所导致的记忆现象。我们在第5节中直接研究了这种潜在的污染,而本节则通过设计一种非常规的新评估来应对这一担忧,这种评估不太可能出现在我们的训练数据集中。为了最大限度地减少偏见和泄漏,新的评估问题由一个专门团队创建,他们没有访问CodeExercises数据集或最终模型。他们按照HumanEval的相同格式创建了50个新问题,并指示设计在现实世界代码库或编程练习中不太可能出现的问题。以下是此类问题的一个示例:
评估语言模型在编码任务上的表现时的一个挑战是,模型的输出往往是二元的:要么代码通过了所有单元测试,要么失败了。然而,这并不能全面反映模型的表现,因为它可能生成了几乎正确但存在微小错误的代码,或者生成了完全错误的代码却恰巧通过了某些测试。可以说,一种更有信息量的评估模型编码能力的方法是将其输出与正确解决方案进行比较,并根据其与预期逻辑的匹配程度进行评分。这与人类在编程面试中的评估方式类似,面试官不仅会运行代码,还会检查推理过程和解决方案的质量。
请参阅表2,以了解phi-1和竞争模型的结果。我们针对新的非传统问题给出的评分与HumanEval的排名相同。phi-1再次在HumanEval上取得了显著高于StarCoder的分数。鉴于这些新问题没有机会污染训练数据,并且进一步设计为超出训练分布之外,这些结果极大地增强了我们对phi-1性能有效性的信心。
在图2.1中,我们看到在CodeExercises数据集上的训练显著提高了模型在HumanEval基准测试上的性能。为了研究这种提升,我们提出对CodeExercises数据集进行修剪,删除与HumanEval中“相似”的文件。这个过程可以被视为数据去污染的一种“强化形式”。然后,我们在这样的修剪后的数据上重新训练我们的模型,并仍然观察到HumanEval上的强劲性能。特别是,即使在积极修剪了超过40%的CodeExercises数据集(这甚至包括与HumanEval只有模糊相似性的文件)之后,重新训练的phi-1仍然优于StarCoder。
我们相信,这种数据修剪实验是一种公平的性能评估方式,并且比文献中通常基于训练数据和测试数据之间重叠度量的标准“污染”研究更有洞察力。为了完整性起见,我们首先进行了一项标准的污染实验,该实验表明,CodeExercises数据集在这种标准意义上并未被HumanEval污染。
N-gram基于共享的n个词序列来衡量文本片段的相似性。我们计算了HumanEval中每个问题的docstring与生成的CodeExercises数据集中每个练习的docstring之间的n-gram重叠。我们发现,有4个HumanEval问题与数据集中至少一个条目的13-gram存在重叠。进一步调查后,我们发现这4个13-gram重叠案例均为误报,例如以下示例所示。我们的n-gram重叠分析表明,我们的数据集与HumanEval在逐字上的重叠非常小。
正如我们刚才所看到的,n-gram分析在发现HumanEval和CodeExercises之间相似的代码片段方面不够精细。因此,我们采用了一种结合嵌入和基于语法的距离的方法。对于嵌入距离,我们计算了代码片段嵌入之间的L2距离,这些嵌入来自于预训练的CodeGen-Mono 350M模型。我们观察到,嵌入距离成功地捕捉到了整体代码语义相似的代码对,这可以通过Python文档字符串、函数/类名以及代码结构来推断。
对于基于语法的距离,我们计算了两个给定代码片段的抽象语法树(AST)之间的(字符串)编辑距离。AST距离能够成功识别代码对之间的重叠部分,同时不受非语法文本(如变量/函数命名、注释和Python文档字符串)的影响。在修剪CodeExercises时,我们为嵌入距离设定了一个阈值,并测试了多个AST距离的匹配率τ。我们将τ在0.95到0.8之间变化,这对应于从CodeExercises中的879.5K个总问题中移除42.5K到354K个不等的问题。
表3总结了我们在修剪后的数据集(τ = 0.95, 0.9, 0.85 和 0.8)上重新训练的phi-1模型的性能,并将其与在完整CodeExercises数据集上训练的原始phi-1模型以及拥有155亿参数的StarCoder-Prompted模型进行了比较。我们根据HumanEval问题是否在原始CodeExercises数据集中至少有一个接近的匹配项(对于给定的τ值),将HumanEval问题分为两个子集:“相似”和“非相似”。然后,我们分别报告了模型在每个HumanEval子集上的准确率。可以看出,即使在大幅修剪数据集之后,phi-1模型仍然以较大的优势(13个百分点)超越了StarCoder-Prompted模型,这验证了我们的性能提升并非由于数据集“污染”所致,即使这里的“污染”一词被宽泛地理解。此外,还注意到所有模型在HumanEval的“非相似”子集上的准确率都低于“相似”子集。
正如一本全面且精心编写的教科书可以为学生提供掌握新学科所需的知识一样,我们的工作展示了高质量数据在磨练语言模型在代码生成任务中能力方面的显著影响。通过打造“教科书级别”的数据,我们能够训练出一个模型,尽管其模型大小仅为其他开源模型的十分之一,数据集大小更是小了百倍,但在HumanEval和MBPP等编码基准测试中,该模型的表现却超越了几乎所有开源模型。我们假设,这样高质量的数据极大地提高了语言模型在代码学习方面的效率,因为它们提供了清晰、独立、富有指导性和均衡的编码概念和技能示例。
然而,与更大的代码模型相比,我们的模型仍存在一些局限性。首先,phi-1专注于Python编程,这限制了其相对于多语言模型的通用性。其次,phi-1缺乏大型模型所拥有的特定领域知识,如使用特定API编程或使用不太常见的包。最后,由于数据集的结构化特性和在语言及风格方面的缺乏多样性,phi-1对于风格上的变化或提示中的错误(例如,当提示中存在语法错误时,其性能会大幅下降)的鲁棒性较差。我们在附录B中详细讨论了这些局限性,并给出了phi-1失败模式的示例。
这些局限性似乎都不是根本性的,通过进一步的研究,我们的方法可以用来解决每一个问题,尽管目前尚不清楚为了克服这些局限需要多大的规模扩展(无论是模型大小还是数据集大小)。我们还认为,如果使用GPT-4而不是GPT-3.5来生成合成数据,可能会取得显著的进步,因为我们注意到GPT-3.5生成的数据错误率较高。有趣的是,尽管存在这些错误,phi-1仍然能够达到如此高的编码熟练度(在[AZL23]中也观察到了类似的现象,即语言模型可以在100%错误率的数据上进行训练,并在测试时生成正确答案)。
更一般地说,我们的工作为开发高质量数据集的良好方法提供了证据,这是推动自然语言处理及相关领域研究的核心方向。然而,创建高质量数据集并非易事,它面临着需要解决的多个挑战。一个挑战是确保数据集涵盖了模型需要学习的所有相关内容和概念,并且以平衡和具有代表性的方式做到这一点。另一个挑战是确保数据集真正具有多样性和非重复性,以便模型不会简单地过拟合数据或记忆特定的模式或解决方案。这需要在数据生成过程中找到注入随机性和创造性的方法,同时保持示例的质量和连贯性。此外,即使在创建了这样的数据集之后,我们也缺乏一种良好的方法来测量和评估数据的多样性和冗余性。例如,如果我们有一个包含编程练习的数据集,那么很难确定每个练习存在多少种不同的变体,以及它们在数据集中的分布情况。最后,由于语言模型本身将用于为未来的语言模型整理数据,这进一步加剧了训练此类模型的伦理和社会影响方面的紧迫性,如参与此过程的数据和模型的责任感、透明度和偏见。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-05-28
2024-04-26
2024-08-21
2024-04-11
2024-08-13
2024-07-09
2024-07-18
2024-10-25
2024-07-01
2024-06-17