A Novel Neural Source Code Representation ased on Abstract Syntax Tree译文

一种基于抽象语法树的新型神经网络源代码表示

摘要:开发用于分析程序的机器学习技术备受关注。一个关键问题是如何很好地表示代码片段以便后续分析。传统的基于信息检索的方法往往把程序当作自然语言文本来处理,可能会遗漏源代码的重要语义信息。最近的研究表明,基于抽象语法树( AST )的神经网络模型能够更好地表示源代码。然而,AST的规模通常较大,现有模型容易出现长期依赖问题。本文提出了一种新的用于源代码表示的基于AST的神经网络( ASTNN )。与现有的工作在整个AST上的模型不同,ASTNN将每个大AST分割成一系列小的语句树,通过捕获语句的词汇和句法知识,将语句树编码为向量。基于语句向量序列,然后采用双向RNN模型,利用语句的自然性,并最终生成代码片段的向量表示。
我们将基于神经网络的源代码表示方法应用于两种常见的程序理解任务:源代码分类和代码克隆检测。两个任务上的实验结果表明,我们的模型优于目前最先进的方法。

1.介绍

人们提出了许多软件工程方法,如源代码分类、代码克隆检测、缺陷预测、代码摘要等,以提高软件开发和维护水平。所有这些方法共同面临的一个主要挑战是如何表示源代码,以便有效捕获嵌入在源代码中的句法和语义信息。
传统方法如信息检索( Information Retrieval,IR )通常将代码片段视为自然语言文本,并基于标记进行建模。例如,程序由Token序列或令牌表示,用于代码克隆检测、缺陷定位和代码作者分类。此外,许多研究者使用潜在语义索引( LSI )和潜在狄利克雷分配( LDA ) 来分析源代码。然而根据文献17,这些方法的共同问题是假设底层语料( 即源代码 )由自然语言文本组成。尽管代码片段与纯文本有一些共同之处,但它们不应该简单地处理基于文本或基于Token的方法,因为它们具有更丰富和更明确的结构信息,最近的工作提供了有力的证据证明了句法知识在源代码建模中的贡献更大,并且比传统的基于Token的方法能够获得更好的表示。这些方法结合了抽象语法树( AST )和递归神经网络( RvNN ) 、基于树的CNN 或Tree - LSTM 来捕获词汇( 例如 AST的叶节点 ,如标识符 )和句法(即AST的非叶子节点,如while语句)信息。这种基于AST的神经模型是有效的,但有两个主要的局限性。首先,与NLP中的长文本类似,这些基于树的神经网络模型也容易受到梯度消失问题的影响,即训练过程中梯度变得消失得很小,特别是当树非常大且很深时。
为了克服上述AST神经网络的局限性,一种解决方案是引入显式(长期)控制流和数据依赖图,并采用图嵌入技术来表示源代码。例如,最近的一项研究考虑了同一变量或函数在遥远位置引起的远程依赖。另一项研究直接构建代码片段的控制流图( CFGs ) 。然而,正如上述工作所描述的,精确的和过程间的程序依赖图( PDGs ) (即控制流和数据流依赖) 通常依赖于编译的中间表示或字节码并且不适用于不可编译和不完整的代码片段。这样的限制阻碍了代码表示在许多涉及任意代码片段的领域中的应用。
本文提出了一种新的表示不必编译的代码片段的方法,称为基于AST的神经网络( ASTNN ),它将一个代码片段的大的AST分解为语句级的一组小树,并在所有语句树上执行基于树的神经嵌入。它产生能代表词汇和语句级句法知识的表达式向量。这里的表达式指的是AST中基于编程语言规范中定义的表达式声明。我们还将方法声明作为一个特殊的语句节点。例如,图1显示了一个开源项目1的代码片段。行7和行15之间的代码段包含一个整体Try语句,行5和行6之间的代码段只包含初始化变量sb的LocalV ariable语句。对于像Try语句那样包含标题和正文中其他语句的每个语句,我们将语句的标题和所有包含的语句进行拆分。这样,大的AST就被分解为短序列的小语句树。
A Novel Neural Source Code Representation ased on Abstract Syntax Tree译文_第1张图片

                                                                         图1 一个AST语句节点的例子(标红部分)

我们使用循环神经网络( RNN ) 将语句和语句之间的顺序依赖关系编码为一个向量。这样的向量捕获了源代码的自然度,并且可以作为神经源代码表示。
更具体地说,首先我们从代码片段构建一个AST,并将整个AST拆分为小的语句树(一个由一个语句的AST节点组成的树,并以Statement节点为根)。例如,在图1中,语句树由虚线表示,原始代码片段中的相应语句(或语句头)也由虚线标记。其次,我们在多路径语句树上设计一个递归编码器来捕获语句级的词法和语法信息,然后将它们表示在语句向量中,第三步,在语句向量序列的基础上,利用双向门控循环单元( GRU ),一种递归神经网络,利用语句的序列自然性,最终得到整个代码片段的向量表示。
总之,我们提出的神经源代码表示旨在学习更多关于源代码的语法和语义信息,而不是最先进的基于AST的神经模型。它具有通用性,可用于许多与程序理解相关的任务,如源代码分类和代码克隆检测。我们在公共基准上对这两个任务进行了实验,并与最先进的方法进行了比较。实验结果表明我们的模型更有效。例如,对于源代码分类,我们的方法将准确率从94 %提高到98.2 %。对于克隆检测,我们的方法在两个基准数据集上分别将F1值的结果从82 %提高到93.8 %和59.4 %提高到95.5 %。
主要工作如下:
1.我们提出了一种新的神经源代码表示,它可以捕获词汇、语句级别的语法知识以及语句的自然度
2.我们将我们的表示应用于两个常见的程序理解任务(代码分类和克隆检测)。实验结果表明,我们的方法可以改进现有的方法
本文的其余部分的结构如下。第二节介绍了背景。第三部分介绍了我们的方法。第四节描述了我们的神经源代码表示的应用。第五节提供了我们的实验结果。有关有效性威胁的相关工作和讨论分别在第六节和第七节中介绍。最后,第八部分总结了我们的工作。

2 背景

这部分是研究现状及关于抽象语法树的基础知识,略。

3 我们提出的方法

我们在本节中介绍我们基于AST的神经网络( ASTNN )。ASTNN的总体架构如图2所示。首先将一个源代码片段解析成一个AST,并设计了一种先序遍历算法,将每个AST拆分成一系列语句树( ST-trees,它们是以语句节点为根和语句对应的AST节点组成的树),如图1所示。所有ST树都由语句编码器编码为向量,记为e1,···,et。然后,我们使用双向Gated Recurrent Unit ( Bi-GRU )来模拟语句的自然性。通过池化将Bi - GRU的隐藏状态采样到单个向量中,作为代码片段的表示。
A Novel Neural Source Code Representation ased on Abstract Syntax Tree译文_第2张图片

3.1 拆分AST并构造表达式子树序列

首先,源代码片段可以通过现有的语法分析工具转化为大型AST。对于每一个AST,我们将其按语句粒度进行分割,并通过先序遍历提取表达式子树序列。形式上,给定一个AST:T和一个语句AST节点集合S,T中每个语句节点s∈S且对应一个源代码语句。我们将MethodDeclaration视为一个特殊的声明节点,因此S = S∪{MethodDeclaration}。对于嵌套语句,如图1所示,我们定义了一个独立的节点集合P = { block,body },其中block分割Try和While语句等嵌套语句的语句头和体,body用于方法声明。语句节点s∈S的所有子节点用D(s)表示。对于一个节点d ∈ D(s),如果通过节点s的嵌套节点集合p∈P存在一条从s到d的路径,则意味着节点d被语句s主体中的一条语句所包含,我们称d是s的子节点。然后由表达式节点s∈S根植的语句树( ST-tree )是由节点s及其所有子代组成的树,不包括T中的子语句节点。
例如以MethodDeclaration为根的第一棵ST树被图1 ( b )中的虚线包围,其中包括标题部分,如" static “、” public “和” readText ",并排除了主体中两个LocalVariable、一个Try和一个Return语句的节点。
由于一个ST树的节点可能有三个或更多的子节点,因此我们也将其称为多路ST树,以将其与二叉树区分开来。通过这种方式,一个大的AST可以分解为一系列不重叠的多路ST树

你可能感兴趣的:(Java,神经网络,深度学习,自然语言处理)