来源:数据实战派
本文约4300字,建议阅读10分钟 本文将结合实例,讲解选择行为的经济学理论和计量分析模型。
毋庸置疑,编程已经发展为社会最广泛的技能之一,与此同时,对高质量代码的需求也随之增加。
经过多年的学习,人类专家已经能够将各种认知任务的抽象规范转化为具体的程序,比如,在过去的几年里,大规模语言模型在推广到各种认知任务方面彰显了其广阔前景,包括语言推理(Linguistic inference)、常识推理(commonsense reasoning)、逻辑演绎(logical deduction)、数学(mathematics),以及对人类知识的多个领域的一般理解。
然而,大规模语言模型是否能够可靠地编写代码解决方案,仍然是一个悬而未决的问题。代码生成评估方面的工作同样出奇的少,因此我们难以精确严格地评估代码的生成性能。
考虑到语言模型的潜力和对代码生成评估的需要,在该挑战下,来自加州大学伯克利分校(University of California, Berkeley)的一支研究团队,引入了一种基于自然语言规范的代码生成基准 —— 自动编码进度标准(APPS, Automated Programming Progress Standard)。论文题为 Measuring Coding Challenge Competence With APPS。
APPS 提供了一个精确而全面的代码生成视图,其评估模型的标准不仅限于编写正确程序的能力,还包括理解任务描述和设计算法以解决实际任务的能力。
APPS 评估框架如下图 1 所示,团队的基准测试包含 10,000 个不同难度级别的编程问题,从简单的入门级问题、面试级问题到竞赛级不等。
如果模型在 APPS 上表现良好,则表明它具有灵活使用数据结构和编程技术的能力,以及正确理解各种任务说明,遵循并理解人的意图的能力。
区别于先前使用 Transformer 语言模型进行代码生成的工作,团队的基准测试衡量了模型采用任意自然语言规范和生成满意的 Python 代码的能力,更具现实性和丰富性。
类似于公司评估候选软件开发人员的过程,通过检查在测试用例上生成的代码来评估模型。
此外,团队成员微调了 GitHub 和训练集上的大型语言模型,发现随着模型的改进,语法错误率呈指数级下降。例如 GPT-Neo 等最新模型,可通过大约 20% 的入门问题测试用例,因此团队发现,机器学习模型已加入学习编写代码的行列。随着未来自动代码生成的社会意义的不断提升,团队开发的基准可以为跟踪进展提供重要的度量标准。
APPS 数据集
APPS 数据集包含从不同的开放访问编码网站收集的问题,如 Codeforces(全球最著名的在线评测系统之一)、Kattis(算法竞赛网站)等。APPS 基准测试试图通过在不受限制的自然语言中提出编码问题并使用测试用例来评估解决方案的正确性,以反映人类程序员是如何被评估的。
该基准总共包含 10,000 个编码问题,为了验证模型给出的答案,数据集包含 131,836 个测试用例和 232,444 个人类编写的实际解决方案。其中,问题的平均长度是 293.2 words,其复杂度可能会很高。数据划分为训练集和测试集,各包含 5000 个问题。而在测试集中,每个问题都有多个测试用例,测试用例的平均个数为 21.2。并且每个测试用例都是为相应的问题专门设计的,有助于严格地评估程序的功能。
(1)APPS 数据集的创建
为了创建 APPS 数据集,团队成员从开放访问站点手动处理问题,在这些站点中程序员可以共享问题,包括 Codewars、AtCoder、Kattis 和 Codeforces。
问题以自然语言规范的形式提出并以不同的格式呈现。为了提高质量和一致性,团队成员为每个问题源编写了自定义 HTML 解析器,这允许我们在问题文本中正确格式化 LaTeX 表达式、列表和章节。必要时,可以使用 MathPix API 将方程图像转换为 LaTeX,并消除依赖于图像数据的问题。
此外还使用了具有 SVD 降维和余弦相似度的 tf-idf 特征执行重复数据的删除操作。为保证问题的高质量,团队对数据集进行了 6 个月的不断优化和改进。
执行和评估任意 Python 代码是极具挑战性的任务。在团队获取数据的网站上,允许人工解决方案运行任意代码,包括公共模块和库的导入语句。为解决此问题,每个网站都实现了 “量身定制” 的评判系统。为此,研究特意设计了一个测试框架,其融合了多个网站的判断功能,并还标准化了测试用例的格式。最终的期望结果是允许解决方案执行任意的 Python 代码,并将其输出与给定问题的测试用例进行比较。
下表 1 是用于文本和代码之间转换的 APPS 数据集与现有数据集的比较。与这些数据集、测试用例和自然语言问题描述相比,APPS 拥有更真实的解决方案。
(2)APPS 数据集的难度
数据集中的每个问题来源都使用单独的难度量表来衡量。团队将这些不同来源的问题归结为三类。
例如,源自 Kattis 网站的问题,难度系数小于 3 的被归类为 “入门级”,难度在 3 到 5 之间的被归类为 “面试级”,难度大于 5 的为 “竞赛级”。具体介绍如下:
入门级(Introductory Level):此类问题不需要复杂的算法,有 1-2 年经验的程序员便可以回答,有 3639 个。这类问题的例子包括计算字符串中的元音数量,或返回整数列表的运行和。
面试级(Interview Level):此类问题会涉及算法,能达到编程技术面试中的难度水平,有 5000 个。这类问题的例子可能包括树或图等数据结构的问题,或者需要非平凡算法(nontrivial algorithms)的问题。
竞赛级(Competition Level):此类问题最具挑战性,难度最高,达到最先进的高中和大学编程竞赛的水平,包括 USACO、IOI 和 ACM 等,有 1361 个。
(3)问题格式
为了适应广泛的问题来源,APPS 中的问题有两种格式:
基于调用格式(Call-Based Format)的问题通常提供初始入门程序(starter code),通常以函数头的形式,并要求提供作为函数返回值的解决方案。
标准输入格式(Standard Input Format)的问题通常缺少入门程序。相反地,模型只提供了问题,并且必须将其答案输出到 STDOUT 流,例如使用 print 语句。
GPT 接受检验
(1)模型及微调
研究团队使用了 GPT-2、GPT-3 和 GPT-Neo 模型。考虑到 GPT 模型自回归的特性,其体系架构特别适用于文本生成。
然而,原始的 GPT-2 模型只接受过自然语言的训练,因此文中使用了 Github 的代码对其进行预训练。坊间证据表明 GPT-3 可以生成代码,为了确定其代码生成能力的范围,选用 “达芬奇”(DaVinci)模型作为最大的公开可用模型,推测其参数数量高达 1750 亿。
最后,GPT-Neo 具有类似于 GPT-3 的架构,但不同之处在于,GPT-Neo 的权重是公开的,因此团队在 APPS 的训练集上对其进行了微调。在预训练和微调中,团队成员使用 AdamW 优化器,batch 大小为 256,权重衰减(weight decay)为 0.05,并微调了 10 个 epoch。在训练大型模型时,使用 DeepSpeed 及其 ZeRO 优化器来减少内存的消耗。模型在 8 A100 GPUs 上进行微调。
(2)GPT-2 的表现如何?
图 2 GPT-2 1.5B 模型的生成代码情况
在上述问题上,GPT-2 1.5B 模型写的代码通过了全部测试用例,着实令人欣喜。请注意,在问题中给出的模型与这里的格式完全相同,这甚至意味着解析 LATEX。为了直观起见,研究团队从所描述的问题中排除了格式化指令。
对于基于调用格式问题,则使用以下输入提示模型:
上述两个提示,变量 q_str 表示问题语句的原始文本,而变量 starter_code_str 表示问题定义中给出的入门程序,如果没有提供此代码,则为空字符串。对于标准输入格式问题,团队仍然使用先前的输入字符串提示模型,只不过将 “基于调用格式” 替换为 “标准输入格式”。
需要注意的是,如果给出了入门程序,那么它也只是输入的一部分。这就意味着,要使用入门程序,模型必须学会在输出答案的开始阶段复制入门程序,以获得正确的问题。团队发现,经过微调的模型完成此操作实属 “小菜一碟”。
图 3 展示了来自 GPT-2 1.5B 的示例。尽管生成的代码没有通过任何一个测试,但乍一看还是很合理的
(3)度量标准
为了得到代码生成能力的综合评价,使用了 APPS 提供的大量测试用例和真实的解决方案。
其中,测试用例允许自动评估,即使可能的程序空间组合起来可能很大。因此,与许多其它的文本生成任务不同,不需要手动分析。团队使用两个度量指标 —“测试用例平均值” 和 “严格的准确率”,以聚合生成的代码在测试用例上的性能,具体计算公式如下所示:
其中,代表测试集的问题数量, 表示解决问题所生成的代码,问题的测试用例集为 。
通常,解决方案可以成功地通过测试用例的子集,但不能覆盖所有的用例。这在模型评估的严格性上适当的留有空间,因为严格的准确率目前可能会掩盖模型的改进。
(4)性能分析
下表 2 呈现了主要的实验结果,包含通过测试用例的平均百分比、模型的严格准确率和难度级别。其中,‘0.1B’表示数十亿的模型参数。不同于其它模型的是,GPT-3 是一种小样本模型且未进行微调。文中作者明确表示,模型的确可以生成一些能通过测试的代码,这也就意味着这些生成的程序没有语法错误,并且可以输出正确答案。
很明显,对于入门级问题,GPT-Neo 表现最佳,达到近似 4% 的严格准确率,并且通过了大约 15% 的测试用例。
图 5 展示了测试用例平均结果的可视化。这说明模型在代码生成方面有了显著的改进,定会推动代码生成领域的研究进展。
研究使用了宽度为 5 的波束搜索(beam search)并评估了 5 个波束,使得每个模型在纠正问题时有五次尝试而不是只有一次。通过这种设置,GPT-Neo 在入门级问题上的严格准确性超过 5%,如上图 4 所示。
附录中的结果显示,排名前 5 的 GPT-2 0.1B 测试用例平均值是 10.75,排名前 1 的 GPT2 1.5B 测试用例平均值是 7.96。由此强调了简单地对多个候选解决方案进行抽样是显著提高性能的有效方法。
在测试准确率上,团队发现从 GPT-2 1.5B 到 GPT-Neo 2.7B 的性能改进要比从 GPT-2 0.1B 到 GPT-2 1.5B 的性能改进更大一些。团队分析 GPT-Neo 性能更好的潜在原因为,GPT-Neo 在更多地 GitHub 代码上进行了训练,有更多的参数,或者是其具有更好地体系结构。由于模型仍然有很大的提升空间,在没有不合理的计算资源的情况下,解决 APPS 基准测试可能需要架构或算法上的进一步改进。
在语法错误率上,这些错误会阻止程序被解释,空格不一致,括号不平衡,冒号缺失等等。上图 6 中可视化了语法错误的流行情况。GPT-3 在入门级问题上给出的答案大约有 59% 的错误,而相似架构的 GPT-Neo 在语法错误方面却只有 3%。
在评估模型的性能上,BLEU 指标被发现是一种较差的替代评估。
为了评估 BLEU,团队将生成的解决方案与给定问题的人类编写的解决方案来计算其 BLEU 值;然后记录最高的 BLEU 分数。从下图 7 中可以观察到,BLEU 分数随着问题来源变得更加困难而增加,尽管在实际情况中,模型在困难的问题上表现得更糟。此外,更差的模型可能有类似或更高的 BLEU 分数。
例如,GPT-2 0.1B 在入门级、面试级和竞赛级题目的 BLEU 分数分别为 26.8、29.7 和 30.2。而 GPT-Neo 2.7B 的 BLEU 分数分别为 27.1、29.1、29.3。因此,BLEU 错误地认为 GPT-Neo 成了一个更差的模型。
总而言之,这项研究引入了一项包含 10,000 个 Python 编程问题的基准测试 —APPS。
与先前的工作侧重于从伪代码到代码的生成不同,本文的基准测试可以在给定的自然语言描述下,来衡量语言模型生成的 python 代码的质量。通过利用具有质量保证,并且包括不同难度级别的成千上万的测试用例和真实解决方案,本文创建了一个全面而严格的测试平台来评估模型。团队用 APPS 评估了最新的生成模型,发现整体性能很低。
但是,随着模型规模的增大以及微调的引入,语法错误率便会呈指数趋势下降,比如 GPT-Neo 模型。
用自然语言编写符合规范的代码是一项极具经济价值的任务,如果能够得到解决,将会带来广泛的社会影响。随着模型在代码生成方面的能力越来越强,如何跟踪这种能力的变化将愈发重要,因为它很可能会导致自动化或恶意代码生成等情况的出现。APPS 基准为这类进展提供了重要的手段。其数据集和实验代码见:github.com/hendrycks/apps。
Reference:
1、https://arxiv.org/pdf/2105.09938.pdf
编辑:黄继彦
校对:林亦霖