什么神器,竟然能自动检索、修复Python代码bug?

机器之心报道

机器之心编辑部

还在为不断的 debug 代码烦恼吗?
本地化 Bug 并修复程序是软件开发过程中的重要任务。在本篇论文中,来自微软 Cloud+AI 部门的研究者介绍了 DeepDebug,一种使用大型预训练模型 transformer 进行自动 debug 的方法。
首先,研究者基于 20 万个库中的函数训练了反向翻译模型。接下来,他们将注意力转向可以对其执行测试的 1 万个库,并在这些已经通过测试的库中创建所有函数的 buggy 版本。这些丰富的调试信息,例如栈追踪和打印语句,可以用于微调已在原始源代码上预训练的模型。最后,研究者通过将上下文窗口扩展到 buggy 函数本身外,并按优先级顺序添加一个由该函数的父类、导入、签名、文档字符串、方法主体组成的框架,从而增强了所有模型。
在 QuixBugs 基准上,研究者将 bug 的修补总数增加了 50%以上,同时将误报率从 35%降至 5%,并将超时(timeout)从 6 小时减少到 1 分钟。根据微软自己的可执行测试基准,此模型在不使用跟踪的情况下首次修复了 68%的 bug;而在添加跟踪之后,第一次尝试即可修复 75%的错误。为评估可执行的测试,作者接下来还将开源框架和验证集。
论文链接:https://arxiv.org/pdf/2105.09352.pdf
引言
自动程序修复中的主要范例是「生成和验证」方法。研究者遵循该方法,假设存在可以识别 bug 存在的一组测试函数,然后本地化 bug 并考虑候选的修补程序,直到找到满足测试的补丁程序为止。
在整个实验过程中,研究者使用了错误已被本地化为单个 buggy 方法的合成 bug,将其与其他上下文(例如函数文件中的上下文以及暴露 buggy 函数的栈追踪)作为输入,并将该输入提供给尝试生成修复好的函数的序列到序列 transformer。
研究者在部署方案中还尝试使用了栈追踪来本地化 bug。目前,研究者基于来自开发人员自己的代码行的栈追踪来应用一种简单的启发法,因为最近调用的行是最可疑的。在未来,作者还有兴趣使用可以对给定栈追踪的方法进行重新排序的编码器 transformer 来改进启发法。
如下图所示,利用了经过广泛预训练的 transformer,研究者使用了用于微调 PyMT5 的相同的 DeepDev-py 序列到序列模型。他们首先使用 commit 数据来训练基线 bug 修补程序模型和 bug 创建模型。Bug 创建(bug-creator)模型向 DeepDebug(反向翻译)提供的数据量是原来的 20 倍。最后,研究者针对具有可执行测试并产生追踪的函数中的神经错误微调了此模型,从而获得其最终的 DeepDebug(追踪)。
训练 pipeline。
模型
研究者重复使用了具有 12 个编码器层和 12 个解码器层的 4.06 亿参数的序列到序列 transformer。在实验栈追踪时,他们为代码框架分配了 1024 个 token,为追踪分配多达 896 个 token,并且为了适应这个规模更大的上下文,还需要扩展 transformer 的位置嵌入矩阵。为此,研究者受 reformer 的启发使用了轴向嵌入,复制了已有 1024 个位置嵌入中的前 896 个,生成一个随机的轴向向量,并将该向量添加到所有 896 个重复嵌入中。在初步实验中,此方法的性能优于随机初始化的嵌入。
数据
研究者使用四个不同的训练数据集:
  • 用于预训练的原始 python 代码;

  • 用于训练神经 bug 创建和 bug 修补程序的 commit 数据;

  • 从原始代码中提取的方法,其中插入了神经 bug 以训练更强大的 bug 修补程序;

  • 通过可执行测试的方法。

对于最后一个数据集,研究者还获得了每个测试执行的行列表,并通过再次插入合成 bug 并重新运行通过测试来获得另一个 bug 补丁程序数据集,使得他们可以在栈追踪、错误消息、打印语句上对 bug 补丁程序进行微调。研究者还实验了为 bug 修补程序模型提供焦点 buggy 方法或整个文件的「骨架」(skeleton),以优先考虑数据(例如函数签名)的优先级。
预训练
在 DeepDev transformer 平台上,研究者重用了 FaceBook 的 BART 模型热启动的 4.06 亿参数的 DeepDev Python transformer,然后使用 Spanmasking objective 对其进行了预训练。预训练数据由 20 万个五星公共 Python 库组成,在 DGX-2 盒子上进行了为期三周的预训练。DeepDev 的 token 生成器附加了空白 token,例如四空间和八空间 token,提高了吞吐量和有效上下文长度。为了最大程度地减少泄漏的风险,研究者始终将验证和测试库限制在同一范围内,尤其是 CodeSearchNet 中使用的库。
commit 的数据
研究者遍历了 10 万个被过滤为至少 10 星 Python 库的 commit 历史记录,并进一步过滤所有消息中包含「修复」一词的 commit,大约占所有 commit 的五分之一。基于对示例的检查,研究者发现了这个简单过滤器的精确度似乎与使用「补丁 bug」或「修复错误」之类语句的限制性过滤器差不多。但是,数据仍然非常嘈杂。
commit 的数据使研究者做到了以下两点:首先,允许他们训练一个偏向于建设性的、bug 修复的编辑模型,让研究人员可以直接在 bug 修复中评估这种模型,或者在过滤更进一层的 bug 数据上对其进行微调。其次,研究者可以反转输入和输出,并训练偏向于破坏性的、引发 bug 的编辑模型。研究人员可以使用此模型来创建神经 bug,以大幅度增强训练数据。这种反向翻译方法已经在 NLP 中被证明是有用的。
 合成 bug 
由于研究者对通过合成 bug 进行数据扩充感兴趣,所以使用了 GitHub 上的大量无 bug 代码。与仅使用从 bug 修复提交中提取的函数相比,这样做有可能使目标方法的数据集扩展二十倍。此外,研究者通过为每种方法创建多个 buggy 版本来任意地扩大规模。在本篇论文中,他们将规模限制为来自 1 万个库中的 130 万个函数(与提交数据几乎相等),并通过反向翻译扩展到了 1800 万个 bug 修复。
研究者观察到了模型注入了以下几类错误:
  • 将点访问器替换为方括号访问器;

  • 将截断链接的函数调用;

  • 删除返回行;

  • 将返回值封装在元组和字典等对象中然后忘记封装对象;

  • 将 IndexError 等精确错误替换为 ValueError 等不同的错误;

  • 误命名变量诸如 self.result 而不是 self._result;

  • 错误地按引用复制而不是按值复制。研究者几乎应用了以前文献中已报道的所有启发式 bug。

「启发式 bug」一词被用来指代使用简单规则手动创建的合成 bug,例如在函数调用中删除一行或交换两个参数、替换二进制运算符(使用!= 代替 ==)、使用错误变量、忘记『self.』访问器或者删除代码。
「神经 bug」一词被用来指代使用神经编辑模型创建的合成 bug,例如训练来还原 bug 修复提交的 bug。使用神经 bug 进行数据增强具有许多吸引人的功能。灵活的神经模型几乎可以任意生成从开发人员实际犯错的分布中得出的编辑。例如,神经编辑模型可以将 get_key 与 get_value 交换,而简单的启发法可能会进行随机交换,比如从 get_key 切换到 reverse_list。而且,这种方法几乎与语言无关,因为研究者可以重用框架来进行挖掘提交,并且只需要一个解析器就可以提取类和方法,以及组成代码框架所需的部分。
上表所示是在测试集用于训练两个 transformer 的交叉熵损失,一个用于提交数据,另一个用于反向提交。在有和没有代码框架的情况下,在向前和向后编辑中对这两个模型进行评估。由于编辑任务相对容易,因此交叉熵损失比通常报告的生成 Python 代码的效果提升五倍。此外,反向编辑的损失比正向编辑的损失低三分之一。正向模型在正向编辑时比反向模型好 6%,反向模型在反向编辑时反过来又好 6%。与仅使用聚焦方法相比,使用框架的两种模型的性能都高出 2%。
如上图所示,bug 创建模型将 kwargs.pop 替换为了 kwargs.get、将. startwith(self.name) 替换为了 ==self.name、并删除了 break。
可执行测试的方法
实际上,有很多机会可以调试可以实际执行的代码,尤其是在有附带测试验证执行正确的情况下。典型的调试会话包括在栈追踪的帮助下查找可疑的代码块、在近似二进制搜索中插入打印语句和断点、修改并执行代码片段、在 StackOverflow 中搜索错误消息的解释以及 API 使用示例。相比之下,基线神经模型是机会更少的,在每次写入一个 token 之前,只能盯着一段代码几秒钟。
而由可执行测试启用的「生成并验证」方法可以有多次机会提高性能。例如,在短 Java 方法领域,研究者见证了 top-20 精度是 top-1 精度的三倍。尽管先前的工作已经表明这些编辑可能会过拟合,真正的随机编辑仍能确保足够多的尝试次数以通过测试组。
研究者主要运用的方法有三种:
  • 追踪法:除了使用测试对不正确的编辑进行分类之外,还以三种不同的方式将来自测试的信息整合到训练中:将错误消息附加到 buggy 方法中,另外附加了栈追踪,并进一步使用测试框架 Pytest 提供了故障处的所有局部变量值;

  • 收集通过测试法:为了以训练规模收集可执行的测试,从用于预训练的 20 万个库开始,过滤到包含测试和 setup.py 或 requirements.txt 文件的 3.5 万个库。对于这些库中的每一个,都在唯一的容器中执行 Pytest,最终从 1 万个库中收集通过的测试;

  • 合成 bug 测试法:在过滤通过可执行测试的函数并插入神经 bug 之后,重新运行测试以收集 Pytest 追踪,并滤除仍通过测试并因此实际上不是 buggy 的已编辑函数。

实验及结果
研究者对训练反向翻译数据、添加框架以及添加 Pytest 栈追踪进行了实验,并得到了如下结果。
反向翻译数据 
在首个实验中,研究者比较了通过前向提交数据进行的训练与通过反向翻译产生的合成 bug 进行的训练,并对保留数据上使用交叉熵进行评估。如下表所示,比起前向提交数据,DeepDebug(反向翻译)的损失降低了 10%。令人惊讶的是,反向翻译模型实际上在反向提交数据上的表现较差。
总体而言,DeepDebug 比以前的技术要强大得多。QuixBugs 挑战是带有小合成 bug 且 Python 和 Java 版本几乎相同的 40 个经典算法的基准,最初的 QuixBugs 挑战是让开发人员在一分钟的时间内修复尽可能多的 bug。下表报告了模型挑战 QuixBugs 的结果。
研究者将模型限制为通过随机采样生成 100 个补丁,这大约是在一分钟跨度内可以生成和评估的数量。随后将现有的 bug 数量提高了 50%以上,同时将误报率从 35%降低到了 5%。值得注意的是,由于此任务的复杂性较低,因此所有的模型都会生成许多重复的编辑,这表明在采样上仍有改进空间。鉴于先前模型的超时以及额外信息提供,这些结果更加令人印象深刻。例如,CoCoNuT 被明确告知哪一行包含该 bug,并被允许六个小时来找到补丁;五个非神经工具找到了 122 个补丁程序,用于最长的递增子序列算法,还进行了数千次的尝试。
添加框架
在第二个实验中,研究者比较了仅使用焦点函数作为输入以及使用整个框架作为输入的训练和评估。如下表所示,当对神经 bug 进行评估时,使用框架时,神经 bug 补丁损失减少了 25%。而实际上,当对提交数据使用框架时,神经 bug 补丁的表现更差,因为提交通常会编辑多个函数。
Pytest 栈追踪
在第三个实验中,研究者将 Pytest 栈追踪附加到 buggy 输入中,使用轴向嵌入来扩展上下文窗口,以适应其他的 token。在计划进行开源的验证集中筛选了 100 个库中的 523 个神经 bug 的基准。他们观察到了令人印象深刻的表现,与交叉熵结果相反,使用追踪大大提高了性能。如下表所示,DeepDebug(反向翻译)的前 10 个修补程序成功率为 90%,而 DeepDebug(追踪)的前 10 个修补程序成功率为 97%。
(完)
看完本文有收获?请转发分享给更多人
关注「Python那些事」,做全栈开发工程师
(0)

相关推荐

  • 神经网络 debug 太难了,这里有六个实用技巧

    重磅干货,第一时间送达 神经网络的 debug 过程着实不容易,这里是一些有所帮助的 tips. 基于神经网络的项目瓶颈通常并非对网络的实现.有时候,在编写了所有代码并尝试了一大堆超参数配置之后,网络 ...

  • 精读文章:高级软件工程师成长秘诀

    身为软件工程师,你要如何进一步成长? 2018 年的时候,我开始在彭博社(Bloomberg)工作.从那之后,事情发生了很大变化.我不再是公司里最初级的成员了,而且我还指导过几个工程师,这真是太棒了. ...

  • 深度学习之PyTorch实战(2)——神经网络模型搭建和参数优化

    如果需要小编其他论文翻译,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/DeepLearningNote 上一篇博客先搭建 ...

  • 想理解深度学习,究竟应该降维打击 or 升维思考?

    让我们从一道选择题开始今天的话题. 什么是神经网络? 请选择以下描述正确的一项或多项. A.神经网络是一种数学函数,它接收输入并产生输出. B.神经网络是一种计算图,多维数组流经其中. C.神经网络由 ...

  • 中山大学提出新型行人重识别方法和史上最大评测基准

    来源:机器之心公众号 来自:我爱计算机视觉公众号 导读:行人重识别,是利用 CV 技术判断图像或视频序列中是否存在特定行人的技术.常规的行人重识别方法往往需要高昂的人工标注成本,计算复杂度也很大.在本 ...

  • 分享一些网友工作中遇到的bug和解决技巧(二)

    下面,跟着我一起看看大家在工作中遇到的bug和解决技巧吧! kuailewangzi8: 话说,刚参加工作的那会,给公司领导演示新开发的产品,心情那个即激动又紧张啊,明明已经试好的产品就是没有反应,当 ...

  • 深度学习之PyTorch实战(3)

    上一节,我们已经学会了基于PyTorch深度学习框架高效,快捷的搭建一个神经网络,并对模型进行训练和对参数进行优化的方法,接下来让我们牛刀小试,基于PyTorch框架使用神经网络来解决一个关于手写数字 ...

  • 又一个Jupyter神器,操作Excel自动生成Python代码!

    来自公众号:Python数据科学 大家好,我是东哥. 不得不说,Jupyter对于表的处理真的是越来越方便了,很多库可以直接实现可视化操作,无需写代码.但是这还不够,最近看到一个神器叫Mito,它真的 ...

  • 这个 Python 代码自动补全神器搞得我卧槽卧槽的

    是时候跟你说说这个能让你撸代码撸得舒服得不要不要的神器了--kite. 简单来说,它是一款 IDE 的插件,能做到代码自动补全,可能你会说了,这有什么牛逼的?一般的编辑器不都有这个功能么? 它虽然是一 ...

  • 图床 这款199元的管理神器竟然“被”出了免费版!

    鹏少 JOKER鹏少 在B站关注我较早的朋友,应该都还记得有一款素材收集整理神器,Eagle,因为当时我们有合作,所以经常在不同视频中推荐.虽然目前合作已终止,但我私下还一直在用,只是对于有些学生党来 ...

  • 30行Python代码实现蚂蚁森林自动偷能量(附源码)

    虽然我支付宝加了好多好友,平时有很多能量可以偷,但由于太懒,至今一棵树都没种成,所以心心念念把偷能量这事自动化.之前通过用代码模拟手机点按的方式,实现了 朋友圈自动点赞,但当时蚂蚁森林的操作流程要比朋 ...

  • 这人人可用的神器竟然免费了!微软太良心...

    原创 ID王大伟 Python爱好者社区 近期微软的一款在Github上开源的工具引起了小编的兴趣,并且试用之后让小编感到非常惊艳,它就是PowerToys.小编就来给大伙介绍一下这款堪称良心的工具集 ...

  • 卧槽!这种"神器"竟然还有电脑版

    一直以来,汤汤都对为什么会有,PC端的小说阅读器的存在而且感到疑惑,毕竟应该没人用电脑看小说吧. 上班时间不能看,下班时间看不爽,总不能挤地铁的功夫,拿出笔记本看吧,不过我后来才发现"上班摸 ...

  • 华为P30 Pro的隐藏技能,竟然能自动剪辑视频

    华为P30 Pro的隐藏技能,竟然能自动剪辑视频

  • 堪称老照片拯救神器,这款照片修复软件的效果绝对惊艳

    很多旧照片随着年代久远,就会变得发黄,没有了原来的光泽和鲜艳.那么如何将这些旧照片翻新呢? 今天带鱼就给大家介绍一款照片修复软件--AKVIS Retoucher. 无偿领取提示: 1.评论随意评论 ...

  • 不到8MB!!这等神器竟然现在才被发现!

    大家好,我是你们的的好盆友大明, 欢迎大家来到[大明青年]. 今天给大家分享一个电脑端的工具箱 电脑端的软件分享比较少 但是个个都是精品~ 今天这个软件大小只有7.8MB 却覆盖了各式各样的小工具 保 ...