[软件工程程序修复论文阅读]基于代码感知机器翻译的程序修复

本文约2871字,预计阅读时长6分钟。
原文标题为CURE: Code-Aware Neural Machine Translation
for Automatic Program Repair

论文基本信息


最后的作者Lin Tan现在在普渡,本文也是基于之前一篇CoCoNuT的结果,有兴趣的可以看一下,本文二作就是CoCoNuT的一作。

这篇发的今年的ICSE,看到的时候百感交集。

论文需要解决的问题


APR问题,还是在做自动程序修复这块。本文认为自动程序修复有两个主要限制:

  1. 搜索空间可能不包含正确补丁,其实就是source和训练思路并不足以提供给模型解出正确解的可能
  2. 搜索策略忽视语法规则。这个限制其实是根植于方法来源的,本来就是有借鉴翻译的思路,但翻译过程中的语法规则没有代码这样的严苛和复杂。
    我们可以看到这里有很多不能编译的补丁

论文的创新点


  1. 预训练的程序语言模型,解决上述的第一个问题,防止生成太多不符合语法规则的补丁。
  2. 基于代码感知的束搜索策略,解决第二个问题,减少搜索的工作量,帮助搜索过程寻找正确路径。
  3. BPE算法,部分解决第一个问题

论文的处理框架


基于Fairseq的CoNuT和全卷积结构,GPT预训练模型(论文打不开就看下CSDN其他博主的论文阅读笔记)。
Overview

论文的关键技术细节


GPT模型

这个模型我们可以理解为是一个预训练的通用模板,有点知识蒸馏的感觉。GPT模型对大量的无标记语料进行训练,获得语料的特征,比如本文就是对开源项目中的Java代码中的方法进行训练,学习Java代码的通用语法规则,后面的训练中,会把预训练模型计算出的权重一并包含进去,用于生成更可能符合语法规则的补丁。通俗一点的说法就是这样,具体实现的过程没有开源代码,我也不知道他们是怎么训练这个部分的。

CoCoNuT

我写这部分的时候有一种先去把CoCoNuT的笔记补发上来的冲动,实在不想再叙述一遍了。

CoCoNuT(Combining Context-aware Nerual Translation)是Lin Tan老师去年发的文章里面提到的工具。CoCoNuT应该是基于他们组更早的一个Encore工具做的,可谓是源远流长。这个论文没有出现在Lin Tan的个人主页里面,不过搜的话可以看到最后一位的作者是Lin Tan老师。

这个工具的特点如下:

  1. 集成学习,n组超参针对不同问题训练,扩大解题范围
  2. 上下文感知,把上下文和bug line放进去一起训练。这个不太清楚他们怎么完成的,开源的Fairseq-context实现基线有点问题,在issue解决前,context和bug line是同一个输入。
  3. 不依赖于语言,只要给语料就能训练,或者说语言灵活
  4. 将CNN运用于自动程序修复和翻译
  5. 注意力网络解释生成原理

效果非常不错。

本文用了CoNuT结构,顾名思义,没有Combining,应该就是没有集成学习

代码感知束搜索

之前用的是Vanilla(不管是coconut还是vanilla都很好吃,不知道是巧合还是有意选择)Beam-search strategy。

(摘自知乎回答)每一步只保留(beamsize-n_finished)个候选决策路径+n_finished个完结决策路径。候选决策中出现的终止符(<EOS>)即会完成一次候选路径->完结路径的转换(n_finished+=1)

而这次我们的搜索方法包含两个重要部分:

  1. 有效标识符检查
    很让我不解的一点是,这个检查似乎包含两个部分,语句和标识符的语法都会被检查。
    首先它会检查标识符,对变量,会根据标识符拆分然后静态分析是否可以,如max_ending_here变成[max, _, ending, _,here]。检查max后面是否可以是_,_后面是不是可以是ending,以此类推
    然后他对语句进行检查,判断A后面是否可以跟B,如果不可以,就把这个分支的可能性设为-Inf。
  2. 长度控制
    他会计算生成补丁长度和bug行长度差距,绝对值在5以内就不做处理,超过五就会通过一个函数对差值进行惩罚。这个处理的假设是:大部分的补丁和源代码长度差不多。用这样的方式,防止无效补丁干扰其他正确补丁的出现。

BPE


天临三年的毕业生真的遭不住,实在不敢把论文里的技术概述放出来。万一查重查到我头上还要交材料,嫌麻烦嫌麻烦,所以这段话我得想个别的描述方法。

BPE是降unk率的绝对武器,只要把string字符串提前清洗一遍,unk率整个0不成问题。为什么呢,因为本来BPE就是从char level级别升上来的,使用英文字母和全部的标点符号当然可以100%表示所有的英文文本。

不过char-level实在是用处不大,英文以单词为表达单元,你整个char-level谁也不知道你这些字母有什么意义,不合适。所以英文分词我们传统都是用空格为单位word-level切分。

那问题又来了,你做文本翻译word-level自然没有问题,计算机编程中,我们有很多的生造单词,还有各种各样的标识符分割,符号化很严重。此外,因为单词是生造的,程序员可以很轻易地构造出成百上千个超出词典的变量名,到时候整个20%的unk率,训练出来的结果全是unk。

真实的故事:
Source:unk unk = unk unk unk unk unk
Target:unk unk = unk unk unk unk
Hyposis:unk unk = unk unk unk unk unk unk unk unk unk unk unk unk unk unk unk unk

这样,也不行。
不过我们观察到一个有趣的现象,程序员在命名的时候,也不是完全脱离真实世界,而是会把词汇拼在一起进行构造,这些词汇有不少是常见的,那我们能否把这个部分分离开呢?

BPE(字节对编码,byte pair encoding)就是一种很好的无监督算法。他从char level进行组合,选取最高频率的组合拼接,反复迭代,理想情况下我们就可以把单词各部分分开了。比如说,charLevel,我们很有可能通过五到六次迭代会发现char 和Level是高频词,并收录到词典里面。优点滤去一部分,重复率太高了,总之可以帮助我们分出很好很好的词表。

当然BPE也是有劣势的,他会忽略代码结构,以纯文本进行处理,模糊标识符、变量名、常量值之间的差异,单纯地作为文本处理。此外词典的size也会很大程度影响训练的结果,导致训出很多乱七八糟的结果,比如上面那个charLevel,可能会训出arLev这种词组,虽然它确实是高频,但我们可以发现他实在没什么意义,纯粹就是分错了,这种情况也不鲜见。

不过优大于劣。

论文的实验设计


数据集:Defects4J,老朋友了,还有QuixBugs,这个我没用过
数据准备:
GHTorrent获取1700个项目,用JavaParser抽取方法,用来训练PL模型( Programming language models),也就是我们之前说的GPT模型。
用了CoCoNuT的训练数据训练fine-tuning,也就是CoNuT部分
实验评估:
和一票模型比修复量和补丁可编译量,吊打
把模型内各个模组换了一下,控制变量,现有方法或多或少有提升,总之有效

实验结果分析


这个数据和我的体验是一致的,不知道啥时候有源代码开源。

自己的想法


预训练再做fine-tuning是降时间和提效率的好办法。
PL模型可以何等程度影响最终结果得进一步尝试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值