eclipse自动补全_DeepAutoCoder:学习用诱导代码标记精确地补全代码

摘要

代码补全是现代IDEs(即集成开发环境)的一个重要部分。它帮助开发人员加快编码过程并减少打字错误。本文利用深度学习技术LSTM,在大型代码语料库上学习语言模型,并对代码元素进行预测。与自然语言不同的是,无数的标识符导致了词汇的爆炸,也更加难以预测。因此,我们提出了一种新的基于诱导标记的LSTM方法来处理大量标识符,从而减少词汇表的大小。为了引出代码标记,我们提供了两种方法,一种是约束字符级LSTM,另一种是使用各种前面的上下文对标识符进行编码,然后将它们输入到标记级LSTM中。基于这两种方法,开发了Deep-AutoCoder工具,并在两种经典的补全场景中进行了评估,即方法调用补全和随机代码补全。实验结果表明,Deep-AutoCoder在方法调用补全和随机代码补全方面的性能优于目前的最新技术。此外,Deep-AutoCoder的实验结果表明,减少词汇量可以有效提高代码补全的精度。

关键词:代码补全,深度学习,语言模型

1 引言

代码补全作为代码生成的一个重要部分,已经成为IDEs的一个基本特性。它是开发人员最常用的10个命令之一[1]。智能代码补全可以消除代价高昂的错误,并推荐准确的代码元素,包括标识符、方法调用、常量等,从而帮助加速软件开发。但是,现有的智能代码补全引擎按照字母顺序或使用频率列出候选代码。在大多数情况下,所需的代码元素并没有在前几个候选项中列出,程序员必须从这些候选项中进行选择。

为了提高代码补全的性能,一些相关的技术被提了出来。Asaduzzaman等人[2]提出了一个上下文敏感的基于实例的工具CSCC,来支持方法调用补全。它采用前四行来确定方法调用的上下文。然而,从这四行中捕获的特性对于方法调用的预测是有限的。一些研究尝试了利用人工智能技术来补全代码。人工智能技术,特别是语言模型已经被运用到重要的软件工程任务中,包括代码生成[3,4,5,6,7],源代码总结[8,9],代码克隆检测[10]等。语言模型在各种自然语言处理(NLP)问题中得到了广泛的应用,如机器翻译[11]、文本摘要[12]和对话系统[13]。最近研究尝试使用语言模型来解决代码补全问题,包括n-gram模型[14,15,16],对数双线性模型[17,18]等。这些语言模型基于一组固定的相对特性,对程序元素进行预测(例如,预测之前的n代码标记)。这样的特性通常是一个糟糕的选择,因为它们只捕获预测元素的局部依赖。

编程语言和自然语言是非常不同的。标识符占据了源代码标记的大部分[19],因此在代码补全中扮演着重要的角色。这些标识符可以是单个字符,也可以由多个单词组成,从而导致标识符爆炸。标识符爆炸对语言模型的词汇量产生了灾难性的影响。如表I所示,我们计算了不同语言的标记总数、行数和词汇表大小。对于自然语言,我们采用了广泛使用的机器翻译数据集WMT-14[20]。统计结果表明,编程语言的词汇量比自然语言的词汇量要大得多,编程语言的词汇量至少是自然语言的两倍。此外,词汇表的大小随着标记总数的增加而快速增加。

bc9e9a56c4482a44b8ab18e05f459f0b.png

在标识符爆炸的情况下,我们提出了一种新的方法,即引入基于标识的长短期记忆机制(LSTM)来补全代码。诱导标记,即编码标识符,目的是减少标识符的数量。为了诱导标记,我们对字符级LSTM和带标识符编码器的标识级LSTM进行了实证研究。通过诱导标记,词汇量显著下降。在基于诱导标识的LSTM机制的基础上,我们开发了一个名为Deep-AutoCoder的工具,应用于经典的代码补全任务、Java语言的方法调用补全和C语言的随机补全。结果表明,Deep-AutoCoder在方法调用补全方面优于以往的工作。此外,Deep-AutoCoder可以有效地随机补全代码元素。本文的主要贡献如下:

• 本文提出了一种新的方法—基于诱导标识的LSTM—来解决代码补全问题。从大型代码库中学习到的语言模型,可以准确地预测方法调用和随机代码补全。

• 我们提出了两种诱导标识的方法,即约束字符级LSTM和带标识符编码器的标识级LSTM来处理大量标识符。

• 我们的Deep-AutoCoder方法在大规模项目中被执行和评估。

2 动机和背景

首先介绍代码补全的问题及其挑战。然后,对本文所使用的语言模型进行说明。

A. 代码补全

代码补全是现代IDEs(如Eclipse和IntelliJ IDEA)中的主要特性之一。它广泛应用于方法调用补全和关键字补全。大多数代码补全技术利用静态信息来分析代码元素,然后代码补全引擎按字母顺序列出所有候选对象。程序员花了很多时间从众多的候选对象中,通过上下键搜索正确的代码序列。

为了引出我们的方法,并获得更好的理解,考虑以下代码片段:

bbd278f15dfcbdac0ec5095b3569588f.png

该方法的目的是为了“删除浏览器”,应该调用webBrowser对象的destroyFunction方法。通过分析webBrowser对象的静态信息,Eclipse的代码补全引擎将webBrowser声明的所有方法按字母顺序列出。但是,在前10个候选方法中没有出现想要的destroyFunction方法。此外,如果不输入标识符或关键字的前几个字母,现有的代码补全引擎不可能预测这些标识符或关键字。这些代码补全引擎会省略部分程序的上下文信息,并按字母顺序列出候选程序。另外,他们不能随机补全代码元素,这是一个迫切的问题。本文利用深度学习方法来解决这些问题。我们主要关注代码补全的两种情况:(1)方法调用的补全,因为方法调用在程序中占很大比例;(2)随机代码补全,包括标识符、关键字等。

A. 标识符嵌入

神经网络将词汇作为输入,并将其作为向量嵌入到低维空间中,即单词嵌入[21,22]。单词嵌入是第一层的权重,通常称为嵌入层。对于大的词汇表来说,使用非常深的体系结构生成单词嵌入是非常昂贵的计算。与自然语言中的单词不同,程序员定义各种标识符。如表I所示,编程语言的词汇率明显高于自然语言。在相同数量级上,编程语言的词汇量至少是自然语言的两倍。词汇表的大小会随着标识总数的增加而显著增加。使用庞大的词汇表为源代码构建语言模型是一项挑战。因此,如何诱导标记来更好地利用语言模型,是实现代码补全的迫切问题。

标识符占源代码标识的大部分,如表II所示。引入标识符是减少词汇量的有效方法。一个标识符可以是几个单词的组合,也可以只是一个没有意义的字符。这些标识符的定义规则有助于对标识符进行编码。在本文中,我们提出了两种诱导标记方法。

3a66fb9f917e12fefaec20a3ec5ecda7.png

• 一个用来建模源代码的约束字符级LSTM机制。源代码中的字符明显少于标识。当应用于方法调用补全时,通过添加约束将生成限制在更小的空间中。

• 带有基于前面上下文对标识符进行编码的编码器的标识级LSTM机制。标识符由前面的上下文表示,例如,它们的类型、前面的标记和标识符的索引。

B. Language模型

我们的工作受到NLP问题语言模型的启发。Hindle等人[23]指出编程语言像自然语言一样具有重复性和可预测性。语言模型本质上是为一个话语分配一个概率。对我们来说,“话语”就是程序。通过计算代码序列的概率分布并减小该分布的熵,我们通常能够很有把握地猜测码序列前缀后面是什么。

  语言模型是一个学习如何生成语言的概率模型。对于序列y = (y1, y2,…,yN),语言模型的目标是估计其发生的概率。

7bdd990bb7354f57e06d1d042a3622a2.png

其中N是这个序列中的标识数量。因此,怎么计算p(yt|y1...yt-1)是我们需要考虑的最重要的问题。

本文采用了一种基于深度神经网络LSTM的语言模型。LSTM是目前最先进的递归神经网络(RNN)之一。与基于固定数量的前代标识来预测标识的N-grams不同的是,RNN[24]可以通过前代标识预测更长的标识。RNN是一种用于处理序列数据的前馈神经网络。原则上,它可以将以前的整个历史输入映射到每个输出。如图1所示,RNN的链状性质表明递归神经网络与序列和列表密切相关,基于神经网络的自然结构来处理这些数据。此外,LSTM的性能优于一般的RNN,因为它能够对长期依赖关系进行学习。它在各种各样的问题上工作得非常好,现在被广泛使用[20,25]。因此,我们采用LSTM来学习源代码的语言模型。

770f70b4f656512a3bdd6a6ca692ca59.png

LSTM包括三层,即输入层、隐藏层和输出层。输入层将序列中的每个标识映射到一个向量;隐藏层通过读取每个向量,计算和更新隐藏状态;然后输出层估计给定当前隐藏状态的下列标识的概率。LSTM引入了一种称为记忆单元的结构,解决了普通RNN难以学习数据的长期依赖关系的问题。记忆单元由四个主要元件组成:一个输入门、一个具有自循环连接(与自身的连接)的神经元、一个遗忘门和一个输出门。

在时间戳t时,记忆单元ct和隐藏状态ht用以下公式更新:

7ee39a909f71e0467fec68e71af63c07.png

其中i,f和o是激活门。σ是sigmoid层,输出0到1之间的数字,描述每个组件有多少应该通过。门是一种选择性地让信息通过的方式,它们由一个sigmoid神经网络层和一个点态乘法运算组成。

  旧单元状态ct-1更新为新单元状态ct

04c10a64d7f2ca570754e50a72a109fc.png

其中cˆt是一个由双曲正切层生成的新候选值向量。最后根据当前隐藏状态ht预测P (yt |y1…yt−1)的可能值。

在训练时,从数据中学习g,使估计y的错误率最小化。

dafb6d17d6e39acc6f66d37262db2f6e.png

3 Deep-AutoCoder

A. 概述

本节将描述Deep-AutoCoder,一种基于诱导标识的的LSTM实现。深度学习方法已被证实,其能有效捕获有用的特征并自动构建从输入到输出的映射。Deep-AutoCoder采用基于诱导标识的LSTM完成代码补全任务。该语言模型在大规模代码库中提取的程序上进行训练,然后对代码元素进行预测。

e8cd8bf15de33591a933928ef9713197.png

图2展示了Deep-AutoCoder的总体架构。它主要包括三个步骤,源代码处理阶段,离线训练阶段和在线补全阶段。源代码必须解析为适合各种方法的特定形式。本文采用抽象语法树(AST)对源代码进行解析。然后在下面的小节中,分别在不同的场景中使用不同的方法(即使用前面的上下文标识符编码器的约束字符级LSTM和标识级LSTM)归纳解析后的标识符。训练语料库中的程序使用深度学习模型进行训练,即第二节所述的双层LSTM机制。在预测阶段,学习模型的输入是部分程序,输出是指定程序上下文的推荐代码元素。

A. 约束字符级LSTM

Deep-AutoCoder采用约束字符级LSTM机制,并诱导标识来补全方法调用。方法调用的推荐由于使用频率很高,因此成为代码补全的一个重要部分[26]。许多IDEAs,如Eclipse和IntelliJ,当程序员在一个对象后面键入一个点时,会自动列出所有可用的成员函数。然后程序员可以从列表中选择适当的方法调用。这些候选方法按字母顺序或根据程序员使用的频率列出。对于程序员来说,从列出的候选方法中选择合适的方法是很费时的。Deep- AutoCoder采用约束字符级LSTM模型对方法调用进行预测,以使推荐更加准确。基于诱导标识的LSTM模型是第二节中介绍的基本LSTM模型的变体。

38e1e562fc9ab175094a051624155262.png

图3使用上面展示的程序示例说明了约束字符级LSTM模型的细节。模型采用代码字符而不是源代码的标识作为输入。例如,输入序列是字符浏览器,webBrowser和它的one-hot是x1,x2,…,xT和xi∈{0,1}|D|,其中D为词汇表中字符的数量。我们假定每行代码最多有100个字符。因此,T = N×100,其中N表示代码行数(LOC)。hi表示LSTM单元格当前时间戳的隐藏状态,它是根据之前的LSTM单元格隐藏状态hi−1和当前输入嵌入向量计算的:

133db226109cd60b3f9c4629fb390163.png

其中E∈R|D|×H,是一个单词嵌入矩阵,并且H是代码的嵌入维数。最后,部分程序x1,x2,…,xT被编码为固定长度的向量c。

当一个字符接着一个字符地生成一个方法名称时,我们在Deep-AutoCoder中添加约束。Deep-AutoCoder提取想要调用方法的对象及其所属的类,然后通过遍历AST获得类声明的所有方法,提取过程的细节将在后面给出。通过添加约束,生成空间被限制在这些可能的方法中。在生成范围内,Deep-AutoCoder预测该方法名的第一个字符y=g(c)。接下来的字符预测是由第二节中描述的过程完成的。Deep-AutoCoder不是生成一个字符序列,而是根据概率列出所有可能的候选字符序列。预测过程中的每一个分支都是一个LSTM,在每一个时间步Deep-AutoCoder对生成的字符的概率进行排序。如图3所示,(d,e,j,…)是候选方法名的第一个字符按其生成概率排序的列表,后面的字符将按照相同的规则生成。最后,排在第一位的方法名是destroyFunction,它是上下文中合适的方法调用。

A. 基于前面的上下文编码标识符的标识级LSTM

我们想要在所有可能的位置进行代码元素补全,而实现自动编程是人工智能代码补全的理想结果。它比完成方法调用困难得多,因为方法调用空间可以被限制在特定类声明的方法。对LSTM来说,大规模词汇表的生成是一个挑战。为了减少词汇表的大小,我们提出了几种诱导(或归纳)标识符的方法。这些方法的目的是使用前面的上下文对标识符进行编码。

程序员经常根据上下文信息声明这些标识符。例如,C语言中的标识符是由简单的字符集定义的for(int i;i

Index:程序中的标识符用索引1,2,...,n来表示。在程序的不同位置出现的相同标识符用相同的索引表示。例如,(int i;i<100;i++)用(int ID_1;ID_1<100;ID_1++)来表示。

Type+Index:此外,我们将索引与标识符类型集成在一起。因此,上面的代码可以表示为for(int INT_1;INT_1<100;INT_1++)。通过添加标识符类型,标识符不仅可以用位置来区分,还可以用类型来区分。

Previous tokens:Deep-AutoCoder采用的第三种编码标识符的方法是使用它们以前的标识符来表示它们(这些标识符是通过_连接的)。我们求解前面的一个、两个和三个标识符,并分别对标识符进行编码。

ID:为了计算标识级LSTM的上限精度,Deep-AutoCoder使用标识ID替换所有标识符。因此for循环表达式可以表示为for(int ID;ID<100;ID++)。这种编码方法不关心标识符之间的差异,它通过把源代码当作自然语言,给出了所有可能位置的代码补全上限。

在诱导标识符完成之后,将代码序列作为第II-C节中介绍的两层LSTM的输入。语言模型根据给定部分程序的概率分布生成之后的标识。

4 评估

我们通过实验来回答以下研究问题:

• RQ1:带有约束的字符级LSTM语言模型对方法调用补全有效吗?

• RQ2:带有诱导标识的标识级LSTM,是否有助于随机代码补全?词汇量和补全精度之间有什么联系?

A. RQ1-用于方法调用补全的约束字符级LSTM

Asaduzzaman等人[2]所做的工作是,与方法调用推荐最相关的。他们开发了一个名为CSCC的代码补全工具,该工具收集当前方法调用请求的上下文,并从示例代码库中匹配它。这些匹配的方法调用将按照相似值的降序排列呈现给程序员。但是CSCC只考虑前四行来确定方法调用的上下文,有限的上下文信息可能会导致大量匹配的高度相似。

为了解决这些问题,Deep-AutoCoder采用了约束字符级LSTM来预测将要调用的方法名。

接下来将介绍评估的细节:

1> 数据集细节:为了进行比较,我们使用相同的数据集Eclipse 3.5.2,并专注于名为Standard Widget Toolkit(即SWT)的库API。他们评估的其他七个项目,例如Vuze和NetBeans,都太小了,无法进行训练。比较Eclipse上的不同方法仍然可以证明Deep- AutoCoder在Java方法调用补全上执行得很好。

数据处理过程如下所述:

    • 使用Eclipse的JDT compiler2将Eclipse项目的源代码文件解析为抽象语法树;

• 在每个源代码文件中找到SWT的所有方法调用;

• 对于每个方法调用o.m(),其中o是SWT类的实例,我们可以找到它的对象o;

• 通过遍历AST,获取对象o所属的类C;

• 提取C声明的所有方法C.m1, C.m2,…C.ml

如上所述,我们提取了SWT库的类及其方法。这些提取特定类的方法被用作LSTM的约束,即语言模型的生成空间。然后,删除所有的注释和导入语句。剩下的纯源代码被用于训练和测试语言模型。

2> 准确度测量:为了测量Deep-AutoCoder在方法调用补全方面的性能,我们分别计算测试集上Top1、Top3和Top10的精度、召回率和F度量。

这些评价标准的计算方法如下:

b1d94a310e6a071436a41d8d93049112.png

其中#Accepted recommendation是整个测试用例中正确推荐的数量。#Generated recommend -ation是推荐的数量。#Method invocations是测试数据中方法调用的数量。因此,当且仅当推荐的方法与源代码中出现的当前方法相同时,推荐才被接受。精度越高,生成的代码就越正确。召回率越高,对应于给定代码片段的适当代码元素的覆盖率就越高。

1> 训练细节:Deep-AutoCoder将所有数据按照8:1:1的比例拆分为训练集、验证集和测试集。如第III-B节所述,我们采用约束字符级LSTM来补全不同LOCs(从1到12)下的方法调用。此外,为了提高训练性能,我们利用两层LSTM来学习源代码。

我们将批大小(即每批实例的数量)设置为20。所有的模型都通过RMSprop[27]优化,该方法将梯度除以其最近大小的运行平均值。学习速率设定为5×10−4,在10个epoch后衰减。我们设置了单词嵌入和隐藏状态到1024。词汇表大小为97,包含小写和大写字母、数字和其他编码符号。

    我们使用开源的深度学习框架Torch来实现。该模型是在一台使用Nvidia GTX1080 GPU的服务器上进行训练的。训练持续50个epoch,耗时约10小时。

2> 方法调用补全的精度:我们在Eclipse 3.5.2上评估SWT API补全的精度,SWT是CSCC工具使用的数据集。我们分别计算前1、前3和前10的精度。表III显示了四个代码补全系统的精度、召回率和F度量,这些系统包括CSCC、带有约束的标识级LSTM、带有约束的字符级LSTM和Deep-AutoCoder,其中Deep-AutoCoder是带有约束的字符级LSTM。括号中LOC的数字表示该模型使用LOC可以达到最高的精度。例如,Deep-AutoCoder在接受12行的代码片段的训练时表现最好。

6f98bb6232785cff3ec39e8acbb7d361.png

对于77.9%的方法调用,Deep-AutoCoder可以直接生成准确的推荐;94.5%的方法调用可以出现在前10个候选推荐中;它的性能明显优于传统的CSCC方法。带有约束的标识级LSTM的精度较低,因为词汇表规模较大,为20,798。通过减小词汇量,Top1的准确率提高了8.1%。对于Deep-AutoCoder,生成空间被限制在类的方法中。但是,一般字符级LSTM的生成空间是源代码词汇表的所有值。与一般的字符级LSTM相比,Deep-AutoCoder的精度提高了11%。结果表明,对于方法调用的补全,生成空间比使用空间的影响更大。

3> 与LOCs相关的精度:我们计算方法调用补全的精度与LOCs的关系。对于标识级LSTM,我们分别用5、10、15、20和25个LOCs训练和测试模型。对字符级LSTM进行1-12 LOC的训练和测试。两种LSTM在不同的LOC上有不同的表现。如图4(b)和图4(c)所示,字符级LSTM对LOC更加敏感。随着LOC的增加,其准确度有明显的上升趋势。较长的代码段有助于方法调用推荐。当LOC小于6时,精度有明显提高。当LOC大于8时,精度趋于稳定。此外,在代码片段较短时(例如,代码行数少于2),Deep-AutoCoder的Top3和Top10精度远远高于一般的字符级LSTM。

为了进行对比,标识级LSTM分别对5、10、15、20、25 LOCs进行了训练和测试。图4(a)表明标识级LSTM从5 LOC开始就处于平稳期。在10和15 LOC中精度略有上升,在15 LOC中精度上升到最高点,而后精度在此开始下降。

2ce71561680077f198a68b8d6813ce39.png

这些结果表明,LSTM所能处理的长度是有限的。首先,精度随着LOC的增加而增加。因为较长的代码片段包含方法调用补全所需的更多信息。但是,当长度达到LSTM可以处理的最大值时,精度变化不大。因为如果代码段太长,前置代码段的信息会丢失。

A. RQ2-用于代码随机补全的带有前置上下文编码器的标识级LSTM

对于所有可能位置的代码补全的研究很少。Deep-AutoCoder采用带有前置上下文编码器的标识级LSTM来处理大量标识符。

1> 数据集细节:Deep-AutoCoder在从POJ收集的新的C语言语料库上,实现所有可能位置的代码补全。POJ是一个在线评定系统,包含了大量来自不同编程比赛的问题。我们收集程序员提交的解决方案,并通过不同的上下文编码器处理这些程序中的标识符。

最大代码长度设置为512,较长的程序将被删除。所有的注释在输入到模型之前都被删除。

2> 精度度量:为了评估代码在所有可能位置的补全精度,我们提出了四种度量指标。

• Total Precision:说明程序中各种标识的总体性能。

5d851f53e63aa5cf2f748649280f09a6.png

• Identifiers Precision:说明标识符预测的能力。

0b83116b327a3857939753ed2170b3ae.png

• Keywords Precision:除了标识符,我们还计算其他标记(如关键字)的补全情况。

6e2e9866196ed3d2dd5809c542648c1e.png

• Distinction:说明区分不同标识符的能力。

5a32750696e5a3350668b4dc9962a59c.png

075d24b91d2ee335cfc079cd995cdbc6.png

其中,#predicted和#original表示预测程序和原始程序中的标识符的数量。

1> 训练细节:与上面的训练过程类似,Deep-AutoCoder将数据集分成三部分,通过Torch框架进行训练。Deep-AutoCoder分别用不同的上下文编码器对标识级LSTM进行训练。我们分别对32和512个单词嵌入和512个隐藏状态进行模型评估。模型由Adam优化,每批32个样品。

2> 不同诱导标记方法的精度:我们对不同的编码器进行评估,以使用不同的前面上下文对标识符进行编码,结果如表IV所示。每个模型在两种单词嵌入维数上进行评估,分别是32维和512维。其中,标识级LSTM将源代码标识作为输入,不进行任何处理,并且一个出现频率小于3的标识被替换为一个UNK标识,词汇表大小为7,439。其他的是标识级LSTM,它集成了不同的标识符编码器,这些编码器用ID标识、索引、类型+索引和以前的标识表示标识符。通过使用前面的上下文对标识符进行编码,词汇表的大小显著减小,如表IV所示。

17fce60676b0901ed753ade487abc771.png

9ea436bf9cc5f6f87fe12691beac86a4.png

该集成ID标识符编码器的模型具有最高的精度,包括标识符、关键字和总精度。它可以准确地确定90.99%标识符的位置。该模型对关键词的预测准确率为83.18%,优于其他模型。但是,这种区别对于ID标识符编码器是没有意义的,因为所有标识符表示为ID标识是没有区别的。总之,这个方法是LSTM在不显式使用任何结构信息的情况下补全代码的上限。

类型+索引编码器可以有效地预测标识符(80.37%)和关键字(82.16%)。同时,它也可以有效地区分标识符。不考虑标识符的含义,Deep-AutoCoder生成的大多数程序都可以运行,而且不产生bug。类型编码器和类型+索引编码器的实验结果表明,类型信息对于标识符和关键字补全都很有帮助。

与类型和索引信息相比,利用前面的标记来编码标识符的精度较低。此外,编码器使用的先前标识越多,精度越低。

总的来说,通过对标识符进行编码来减小词汇表的大小,可以有效地提高标识符和关键字的补全精度。

3> 单词嵌入维数的影响:单词嵌入维数对代码补全也有影响。当维度下降到32时,所有模型的精度下降。其中,集成ID编码器的模型影响最小。它的精度下降0.5%,其他编码器下降约1%。而单词嵌入维数对一般标识级LSTM的精度影响较大。其标识符、关键字和总精度分别下降约3%。这是因为一般标识级LSTM的词汇表比其他模型要大得多。小的单词嵌入维数不能有效地处理大字典的分布。字典中的多个标记可以映射到嵌入向量中,使得过于紧密而得不到有效区分。

4> 词汇量的影响:图5说明了精度和词汇量的关系。随着词汇量的增加,标识符和关键词的嵌入精度在32和512个单词嵌入维度上都有显著降低。

5 讨论

A. 为什么Deep-AutoCoder能够发挥作用?

代码补全的一个主要挑战是标识符的数量过大。现有的基于上下文的方法和语言模型(如N-grams)通常没有处理标识符的能力,并且缺乏对源代码分布的深入理解。我们已经确定了Deep-AutoCoder在解决这些问题时的的两个优点。

基于前置上下文的标识编码器:通过标识符之前的上下文对其进行编码,词汇表的大小显著减小。训练一个模型时,用位标记来补全标识符是有效的。为了估计随机代码补全的RNN的上界,我们将所有的标识符表示为ID标识。虽然由它生成的程序的标识符不能被区分,但它提供了最多14%的改进空间的证据。此外,我们评估了不同的编码器,它们不仅可以减少标识符的数量,而且能够很好地进行区分。

学习代码序列:我们的方法的另一个优点是,它可以学习源代码的常见模式。模型本身就是语言模型,可以记住不同程序的可能性。我们模型的隐藏层具有记忆能力,它们不仅考虑单个标记,还考虑它们在源代码中的相对位置。

B. 对有效性的威胁因素

我们已经确定了存在以下威胁有效性的因素:

源代码是静态类型语言。由于本文研究的源代码是静态类型语言,因此它们可能不能代表动态编程语言,例如Python和JavaScript。接下来我们会将把这个模型扩展到其他编程语言。

没有明确的结构信息。本文利用语言模型来补全代码,而语言模型是在没有显式结构信息的平凡代码上训练的。此外,我们还估计了源代码语言模型的上限。在将来,我们将研究一个更好的模型来学习源代码的结构。

6 相关工作

在过去的几年里,人们对能够简化各种软件开发任务的综合技术重新产生了兴趣。Asaduzzaman等人[2]提出了一种名为上下文敏感代码补全(CSCC)的新技术,用于提高API方法调用补全的性能。为了推荐补全建议,CSCC根据候选方法的上下文与目标调用上下文之间的相似性对候选方法进行排序。CSCC只考虑了框架或库API。除了方法调用补全,Asaduzzaman等人[28]也对方法参数补全进行了研究。该工作利用源代码局部属性、静态类型和前面的代码示例来推荐方法参数。

另外,一些语言模型也被用于构建代码的概率模型。N-gram模型是源代码中最流行、使用最广泛的概率模型,由于其简单性和学习效率高,被应用于代码补全任务[14,15,16,23]。Hindle等人[23]首先利用N-gram建模源代码,并开发了一个Java代码补全引擎。它大大改进了被广泛使用的Eclipse IDE中现有的推荐工具。不久之后,各种改进被提出来解决N-gram模型存在的一些限制。Nguyen等人[15]开发了一个代码推荐引擎,它集成了语义N-grams、全局关注和成对关联。Tu等人[16]引入了一个缓存语言模型,该模型由一个N-gram和一个缓存组件组成,以利用局部属性。Raychev等人[14]基于API利用N-gram和RNN来合成带有漏洞的程序。

此外,更复杂的语言模型逐渐被用于代码补全。Raychev等人[4]介绍了一种学习代码概率模型的方法,就像在ASTs上学习领域特定语言(DSL)中的决策树一样。在进行预测时,代码的概率模型会自动确定正确的上下文。Bhoopchand等人[29]引入了一个带有稀疏指针网络的神经语言模型,来实现动态类型化编程语言Python的代码补全。指针网络的目标是捕获远程依赖关系。

7 结论

在本文中,我们提出了一种新的基于诱导标记的LSTM代码补全方法。通过诱导标记,词汇量显著减少。我们提出了两种减少词汇量的方法,约束字符级LSTM和带标识符编码器的标识级LSTM。此外,还基于这些方法开发了Deep-AutoCoder工具。Deep-AutoCoder应用于两种情况:方法调用补全和随机代码补全。我们的实证研究表明,词汇量的减少可以显著提高词汇的准确性。在将来,我们将探索更适合进行代码补全的模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值