GraphCodeBert: Pre-Trainng Code Representions with Data Flow
  LoXWivbP6ycg 2023年11月05日 48 0

GraphCodeBert: Pre-Trainng Code Representions with Data Flow

创新点:认为AST中有许多不必要的联系且仅是在语法层面,而DFG关注了语义层面:采用数据图流向【将程序中变量作为图的节点,将变量之间的数据流向作为边,mask掉部分边后再进行预测】

三个预训练任务:MLM、EP边预测(即创新点)、NA节点对齐【将NL中的变量与PL中的变量进行对齐训练】 

标题

GraphCodeBert: 用数据流进行预训练代码表示

会议/期刊

ICLR 2021

作者

Daya Guo1∗, Shuo Ren2∗, Shuai Lu3∗, Zhangyin Feng4∗等

关键词

数据流

摘要

GraphCodeBERT试图考虑代码的内在结构以提高对代码的理解和处理。

  1. 预训练模型的背景:预训练模型用于编程语言已经在多种与代码相关的任务中取得了显著的经验性改进,包括代码搜索、代码自动补全、代码摘要等。
  2. 现有问题:然而,现有的预训练模型将代码片段视为一系列标记(tokens),忽略了代码的内在结构。这个内在结构包含了关键的代码语义信息,可以增强对代码的理解过程。
  3. GraphCodeBERT介绍:为了解决这个问题,提出了GraphCodeBERT,这是一种面向编程语言的预训练模型,它考虑了代码的内在结构。与传统的抽象语法树(AST)等语法级别的结构不同,GraphCodeBERT在预训练阶段使用数据流,这是代码的语义级别结构,用于编码变量之间的“值来自何处”的关系。这种语义级别的结构相对较简单,不会引入不必要深层次的AST层次结构,这使得模型更加高效。
  4. 基于Transformer的模型:GraphCodeBERT基于Transformer模型进行开发。除了使用遮蔽语言模型任务之外,还引入了两个结构感知的预训练任务。其中一个任务是预测代码结构的边缘关系,另一个是在源代码和代码结构之间对齐表示。模型使用了一种带有图引导的遮蔽注意力函数,以将代码结构纳入模型的考虑范围。
  5. 模型评估:作者对GraphCodeBERT进行了四项任务的评估,包括代码搜索、克隆检测、代码翻译和代码改进。结果表明,代码结构和新引入的预训练任务可以改善GraphCodeBERT,并在这四项下游任务中取得了最先进的性能。
  6. 结构级别的关注:作者还指出,在代码搜索任务中,模型更倾向于使用结构级别的关注而不是标记级别的关注。


引言

程序语言预处理模型是受启发于自然语言与处理模型。预处理模型在程序语言处理任务上(如代码搜索、代码补全、代码摘要等等)取得了很好的成就,然而目前存在的预处理模型都是将代码视作token序列而忽略了代码的内在结构。本文作者基于此设计了GraphCodeBert这样一个考虑代码内在结构的预训练模型。 首先,为了融入代码结构,开发者并没有考虑AST(抽象语法树),而是采用了DFG(数据流向图)。他们认为AST代表的是各个token之间的句法关系,是syntactic层面的关系,而DFG代表的变量之间的来源关系,是semantic层面的关系。DFG在一定程的上能够避免AST中一些不必要的联系从而提升了模型的有效性; 其次,GraphCodeBert也是基于Transformer开发的; 最后,GraphCodeBert是通过三项预训练任务来训练模型的:MLM(掩语言模型)、EP(数据流向图的边预测)和NA(数据流向图节点和代码token之间的关系预测)。 GraphCodeBert是第一个加入语义级别的代码结构的预训练模型,并且提高了四个下游任务(代码搜索,克隆检测,代码翻译和代码改错)的处理能力。

数据流向图

数据流向图DFG是一个有向图,代表的是每个变量的值从哪里来到哪里去的关系。

下图代表了同一个python函数(功能是输入两个数,返回两数中较大的那个数)分别转换成AST和DFG后的结果。

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_图神经网络

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_图神经网络_02

模型

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_图神经网络_03

模型架构

输入序列

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_04

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_图神经网络_05

Transfomer

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_图神经网络_06

基于图的掩码注意力机制

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_07

预训练任务

同bert一样,GraphCodeBert也只训练编码器。GraphCodeBert通过MLM、EP和NA三个任务来训练编码器。

MLM 掩码语言模型

这个任务也是参考bert的训练工作从代码序列和注释序列中选取15%的token,其中80%会被掩盖,10%会替换成一个随机的token,剩下的10%不做变化。MLM的任务就是由扰乱后的序列输出扰乱之前的序列。

EP 边预测

加入这项任务是为了使得模型能够学习到data flow中的信息。

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_08

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_09

NA 节点对齐

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_10

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_11

下游任务

为了显示GraphCodebert的有效性,作者进行了四项下游任务,包括了:代码搜索、克隆检测、代码翻译和代码改错。

代码搜索

这个实验的任务是通过输入一段自然语言描述,模型输出从代码库中选出一段最符合描述的代码。这个实验所用的数据集为经过预处理之后的CodeSearchNet,并且以Mean Reciprocal Rank (MRR)作为评价标准

实验结果对比

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_12

以上模型主要通过计算代码和查询描述之间的内积来对候选的代码进行排名的。第一组分别代表了词袋模型、卷积神经网络、双向RNN和自注意力机制;第二组代表的一些预训练模型,RoBerta是一个在文本语料库上通过MLM任务训练的模型,RoBerta(code)则是在代码上的预训练模型,CodeBert是在文本-代码对上通过MLM训练的模型。

克隆检测

任务的目的是给出两个输入代码的相似度。实验使用的数据集是BigCloneBench

实验结果对比

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_13

案例

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_14

上图显示了对于两个字面相似但是语义不同的函数 ,GraphCodeBert给出了正确的结果而其他两个模型预测错误。

代码翻译

代码翻译的任务就是能够将一种语言的代码转换成另一种语言。

实验结果对比

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_15

Navie是将源语言原封不动输出用来做参照; PBSTMT代表的是以短语为基础的统计学机翻模型。

代码改错

实验结果对比

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_16

上图显示了不同模型分别在短和中等长度的代码中的能力评价。

模型分析

消融实验

对比去除任意一个组件在代码搜索任务上的表现:

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_bert_17

注意力分布

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_18

[CLS]被认为是可以和一个输入序列中所有的token做注意力,因此[CLS]在一定程度上也代表了这个代码的表征向量。 上图第一行表示了代码和DFG节点的数量分布;第二行表示了[CLS]对于代码和节点的注意力分布。此图表说明了模型对于单个节点具有更高的注意力。

AST与DFG的对比

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_19

AST Pre-order Traversal通过先序遍历来序列化一个AST;AST Subtree Masking是一个transfomer模型,但是AST上的每一个节点只能注意到他的子代。

上图显示,当输入序列长度较低时,AST相关的模型的MMR评分低于参照,而无论输入长度如何GraphCodeBert表现效果都明显高于AST。作者给出的解释是:AST中包含了大量不必要的联系

GraphCodeBert: Pre-Trainng Code Representions with Data Flow_代码生成_20

上图则显示了data flow的有效性,通过对比有没有dataflow这个结构的模型对自然语言描述和代码的匹配度。

模型局限

首先模型不能处理一些特有的库,如tensorflow;其次模型还会出现一些类似于标识符未定义先使用、括号没闭合等问题。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
LoXWivbP6ycg