图神经网络代码_当机器学习遇到代码搜索

本文对比了三种神经网络代码搜索技术:NCS、UNIF(NCS的有监督扩展)、CODEnn和SCS。评估表明,监督学习可以提升性能,但增加复杂性不一定有益。简单的网络如UNIF在某些场景下优于复杂模型。此外,基于文档字符串的监督可能不总是最佳策略,理想化的训练语料库能显著提升性能。
摘要由CSDN通过智能技术生成

19225dbacb800156cfd58e8c7e423ecb.png

引用:José Cambronero, Hongyu Li, Seohyun Kim, Koushik Sen, and Satish Chandra.

  1. When Deep Learning Met Code Search. In Proceedings of the 27th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE ’19), August 26–30, 2019, Tallinn, Estonia. ACM, New York, NY, USA, 11 pages. https://doi.org/10.1145/3338906.3340458

摘要:最近有许多关于使用深度神经网络进行自然语言代码搜索的想法。这些建议的共同点是将代码和自然语言查询嵌入到实际向量中,然后使用向量距离来近似代码和查询之间的语义相关性的想法。存在多种学习这些嵌入的方法,包括仅依靠代码示例语料库的无监督技术,以及使用成对的代码和自然语言描述的对齐语料库的监督技术。监督的目的是产生与查询和相应的所需代码段更加相似的嵌入。

显然,可以选择是否完全使用监督技术,如果要使用监督技术,则可以选择使用哪种网络和训练方式进行监督。本文第一次系统地评估了这些选择的方法。为此,我们汇总了最新技术的实现,以在通用平台,训练和测试资料集上运行。为了探索网络复杂性的设计空间,我们还引入了一个新的设计点,即对现有无监督技术的最小监督扩展。

我们的评估表明:1.将监督添加到现有的非监督技术中可以提高性能,尽管不一定有太大提高;2.简单的监督网络比更复杂的基于序列的代码搜索网络更为有效;3.虽然通常使用文档字符串来执行监督,但是文档字符串的有效性和更适合查询的监督语料库之间存在很大的差距。

1. 介绍

代码搜索的目的是从与自然语言表达的开发人员意图最匹配的大型代码库中检索代码片段。专有代码存储库尤其面临着挑战,因为开发人员无法再依赖诸如 Google 或 Stack Overflow 之类的公共资源来寻求帮助,因为它们可能无法捕获所需的特定于组织的 API 和库使用情况。然而,学术界和工业界的最新工作都已采取行动,以实现使用深度学习进行更高级的代码搜索。我们称这种方法为神经网络代码搜索。有关基于自然语言查询检索的代码片段的一些示例,请参见图 1。图 1 中显示的查询类型以及结果也突出显示了仅基于简单的方法(例如正则表达式匹配)来解决此任务的困难性。

fe87024099167083752972ad7bbe4c5d.png

b2f7bad2a0a42a3f25dc46d9dd2ba02b.png

图 2 概述了神经网络代码搜索,并概述了不同的技术,我们将在本文中详细介绍这些技术。神经网络代码搜索系统中的核心抽象是嵌入的概念,它们是共享向量空间中输入的向量表示。通过在这些嵌入上计算向量相似度,例如余弦相似度,可以检索与用户查询在语义上相关的代码片段。例如,在图 2 中,查询语句“如何遍历一个 hashmap?”通过一种可能的技术(NCS)将映射到向量⟨1.2,−0.1,5.5⟩。候选代码片段也使用相同的技术映射到向量。在图 2 中,一个这样的代码片段,例如,public void forValuesAtSameKey ...,映射到向量⟨0.94,-0.2,1.2⟩。然后可以使用向量相似度对候选代码段进行排序。神经网络代码搜索中的一个关键问题是以向量相似度与语义相关度一致的方式学习这些嵌入。

如图 2 所示,用于学习这些表示的模型可以大致分为无监督和有监督两种。在探索神经技术优势的过程中,我们从 NCS 开始,NCS 是我们先前内置的一种有效的,无监督的神经网络代码搜索技术。由于 NCS 显示出令人鼓舞的结果,我们希望尝试通过其他设计改进来改善此基准的可能性。特别是,最近的工作提出了有前途的有监督的神经网络代码搜索技术,分别标记为 CODEnn 和 SCS,它们成功地使用了源代码和文档字符串的语料库学习了代码和自然语言嵌入。

这种监督的目的是学习一种映射,该映射可为用户查询语句和相应的所需代码生成更多类似的向量。在图 2 中,该目标由实线箭头表示,当使用监督模型进行映射时,实线箭头将使查询的嵌入和正确的代码片段靠近。

有这么多种技术可供选择,任何试图设计和部署代码搜索解决方案的人如何做出明智的选择?例如,监督听起来不错,但是相对于获取监督数据的开销而言,监督提供了多少好处?与更简单的网络相比,更复杂的网络会带来多少价值(在本文中,我们将介绍其中之一)(图 2 中的 UNIF,将在下文进一步介绍)?将模型应用于实际用户查询时,使用文档字符串执行的模型监督是否会限制性能?

在这项工作中,我们尝试定量地了解这些折衷方法。为此,我们在上述代码搜索技术的背景下制定了实验。其中的三种技术与以前的工作完全相同,并且目前处于最新状态:

•NCS:在 Facebook 上开发的一种无监督的神经网络代码搜索技术,该技术仅使用源自代码的词嵌入语料库。

•CODEnn:这是最近一篇有关使用深度神经网络进行代码搜索的指导技术的论文,该技术使用了多个基于序列到序列的网络,并且其性能优于其他最新的代码搜索技术。我们使用作者提供的实现方法。

•SCS:使用多个序列到序列网络的有监督神经网络代码搜索系统。我们使用作者在博客文章中提供的实现方法。

因为我们想了解复杂的基于词序的网络在何种程度上有所帮助,所以我们还对 NCS 技术进行了最小扩展,只增加了监督功能,而未做其他事情:

•UNIF:对我们自己创造的基础 NCS 技术的有监督扩展。UNIF 使用基于词袋的网络,与基于单词序列的网络相比,其复杂性大大降低。这个简单的模型是本文的新贡献。

我们的评估是使用以下三个研究问题构建的;我们还给出了发现问题和发现的总结:

研究问题 1:基于成对代码和自然语言描述的语料库,通过扩展有效的无监督代码搜索技术是否会提高性能?

我们的结果表明,尽管在所有数据集上均未看到改进,但在我们的基准查询中,UNIF 的性能优于 NCS。

研究问题 2:在受监督的神经网络代码搜索中,更复杂的网络是否可以提高性能?

我们的结果表明,在我们的基准测试中,UNIF 这个简单的基于词袋的网络优于基于单词序列的 CODEnn 和 SCS。额外的复杂度并没有增加价值。

研究问题 3:基于文档字符串(作为训练语料库的自然语言组成部分)的监督效果如何?

我们发现基于文档字符串的监督并不总是能提高性能。为了了解可能的改进空间,我们构建了理想的备用训练语料库,其中代码段和自然语言与基准查询不相干,但它们来自同一来源。

在使用该语料库进行训练时,所有受监督的技术都得到了显著改善,这表明,作为概念证明,如果给出与预期的用户评估相匹配的训练语料库,这些技术可以提供良好的搜索性能。

本文贡献:

  1. 我们相信这是第一篇比较同一平台上运行的最新神经网络代码搜索系统并使用同一语料库进行评估的论文。

  2. 我们提出了神经网络代码搜索系统领域的一个新设计要点:UNIF,这是对 NCS 的扩展,它最小程度地增加了监督。

  3. 我们发现 UNIF 的性能优于某些更复杂的网络设计(CODEnn 和 SCS)以及无监督技术 NCS。此外,在监督中使用的对齐语料库的选择非常相关:理想化的训练语料库表明,受监督的技术可以提供令人印象深刻的性能,并突出表现出的差异,这些差异可能无法通过对典型代码和文档字符串对齐语料库的训练而立即看到 。

2. 神经网络代码搜索模型

2.1 NCS

1af31b4c99735709dc77e37c02771316.png

093a11e526ec761e9a4d39e33640d556.png

2.2 UNIF:NCS 的有监督扩展

efa6249b17881fdd830bf979669dd510.png

177436e9e8da755bb3c8a9f31970f731.png

图 4 是 UNIF 的示意图。

8b2b81556437457d3941e09af53e6a57.png

2.3 CODEnn

与 UNIF 相似,CODEnn 也使用神经网络对 Ec 和 Eq 进行建模,并采用监督学习。但是,使用的网络更加复杂和深入。我们坚持原作者的命名,并将此模型称为 CODEnn,是 Code Description Embedding Neural Network 的缩写。CODEnn 并未将代码段视为一袋令牌,而是从包含该代码段的方法的名称,该代码段中的 API 调用序列以及该代码段的一袋令牌中提取了一系列单词。通过分割驼峰式和蛇形方法名称,提取方法名称中的词序列。

方法名称序列和 API 序列作为输入提供给两个单独的双向长短期记忆网络(bi-LSTM)。

在将两个单独的 LSTM 应用于方法名称和 API 序列后,CODEnn 获得了两个隐藏状态序列。CODEnn 总结了每个这样的隐藏状态序列,以获得单个向量。为了进行概括,CODEnn 使用了最大池方法。

分别将代码令牌包中的每个令牌作为前馈稠密神经网络的输入,并且将输出向量进行最大池化。然后,通过将这三个向量(来自 LSTM 的两个和来自前馈网络的一个)串联起来并将它们馈送到一个稠密的神经网络,从而获得最终的代码嵌入。上述所有网络共同实现功能 Ec。

CODEnn 使用双向 LSTM 实现函数 Eq,该函数将对在文档字符串中找到的代码段的描述作为输入序列以生成 eq。图 5 概述了该体系结构。

f18c79c2720a8345a9b96459978ba16b.png

2.4 SCS

我们引入了另一个基于序列的有监督深度神经网络进行代码搜索,该方法由 GitHub 上的数据科学团队描述和实现。我们将此模型称为 SCS,语义代码搜索的缩写。

SCS 分为三个单独的训练模块。序列到序列门控循环单元(GRU)网络学习在给定代码令牌序列的情况下生成文档字符串令牌序列。我们将此称为代码到文档字符串模型。

LSTM 网络学习训练语料库中文档字符串的语言模型。该模型可用于嵌入自然语言并计算给定自然语言输入的概率。

最后一个模块学习一种转换(以前馈层的形式)以预测给定代码令牌序列的查询嵌入。为了学习这种转换,该模块采用代码到文档字符串模型的编码器部分,并在代码序列输入和使用语言模型产生的相应查询嵌入方面训练网络。最后的训练阶段通过使编码器层解冻几个时期来对整个网络进行微调。SCS 将代码到文档字符串模型的此经过微调的编码器部分用作 Ec,将语言模型用作 Eq。图 6 概述了该体系结构。

表 1 概述了在学习 UNIF,CODEnn 和 SCS 的 Ec 和 Eq 时采用有监督的模型的网络详细信息。d2146d897d9a9ec52cd7932fd0bc10ee.png

d2146d897d9a9ec52cd7932fd0bc10ee.png

3. 评估方法

我们的评估使用不同的数据集和基准。为清楚起见,我们通篇使用以下术语:

  • 训练语料库 是指配对代码和自然语言的数据集。

  • 搜索语料库 是指唯一代码条目的数据集。为了避免搜索结果重复,条目是唯一的。

  • 基准查询 是指一组评估查询,用于评估经过训练的模型的性能。

我们的评估使用三种不同的训练语料库,两种搜索语料库和两组基准查询。

3.1 训练语料库

我们使用三个训练语料库来进行实验。

CODEnn-Java-Train 是公开发布的数据集。该语料库由大约 1600 万个预处理过的 Java 方法及其相应的文档字符串组成。数据集包括四种类型的输入:方法名称序列,API 序列,一组方法主体标记和文档字符串序列。我们还通过将方法名称序列与 API 序列串联并将此串联序列视为一袋令牌来得出另一个输入。此派生的输入用于训练 UNIF 和 SCS。

GitHub-Android-Train 是一个 Android 专用语料库,是通过从大约 26109 个带有 Android 标签的 GitHub 存储库中收集方法而构建的,我们采用了所有带有附带文档字符串的方法(总共约 787000 个)并将其用作训练数据。与 CODEnn-Java-Train 相似,我们得出训练 CODEnn 必需的四种类型的输入集合(方法名称序列,API 序列,方法主体标记包和文档字符串序列)。我们在为 NCS 生成的输入序列上训练 UNIF 和 SCS,它使用解析器使用相应的类,方法调用,枚举,字符串文字和源代码注释来限定方法名称,同时忽略变量名称,并应用驼峰和蛇形大小写标记化。

StackOverflow-Android-Train 是一个 Android 专用的训练语料库,我们通过收集 Stack Overflow 问题标题和代码片段答案而构建。我们通过从 Stack Exchange 公开发布的数据转储中提取所有带有 Android 标签的 StackOverflowposts 来准备此数据集。根据以下启发式方法过滤数据集:(1)代码段中不得包含 XML 标签;(2)代码段必须包含左括号以表示存在方法调用;(3)帖子标题不得包含“gradle”,“studio”和“emulator”之类的关键字。过滤后,我们最终得到 451k 对 Stack Overflow 标题和代码段。

StackOverflow-Android-Train 的目标是充当备用训练语料库,是我们评估的理想选择,它分别利用 Stack Overflow 标题和代码段作为基准查询和答案。

3.2 搜索语料库

我们在评估过程中使用了两个搜索语料库。

CODEnn-Java-Search:CODEnn 的作者发布了 400 万种独特的 Java 方法。

GitHub-Android-Search:从 GitHub 收集了 550 万种独特的 Android 方法。该语料库源自用于构建 GitHub-Android-Train 的 26,109 个存储库,但还包括没有可用文档字符串的方法。

3.3 基准查询

我们使用两组查询作为模型的评估基准。在这两个基准测试集中,这些查询对应于 Stack Overflow 标题,并且每个查询的基本事实答案是我们独立收集的相应帖子的接受答案或高度投票的答案。使用 Stack Overflow 标题作为查询,而不是使用少量的初始关键字,旨在评估不同技术将自然语言片段和代码成功映射到共享空间的程度,并被选择直接与以前的工作进行比较。

Java-50 是一组查询,用于评估原始论文中的 CODEnn。这些查询对应于前 50 个投票最多的 Java 编程问题的 Stack Overflow 标题。作者提出的问题在 Java 中具有“具体答案”,在线程中包含带有代码的公认答案,并且不是重复的问题。在此基准上进行评估时,模型会在 CODEnn-Java-Train 上进行训练。

Android-287 是 287 个特定于 Android 的查询,用于评估原始论文中的 NCS。这些问题是由符合以下条件的脚本选择的:(1)问题标题包括“Android”和“Java”标签;(2)存在一个已答应的代码答案;(3)基本实况代码段在 GitHub Android 回购库中至少具有一个匹配项。在此基准上进行评估时,除非另有说明,否则在 GitHub-Android-Train 上对模型进行训练。

表 2 总结了我们的评估中使用的训练语料库,搜索语料库和基准查询,以及我们用于结果的组合。

3.4 评估流水线

我们发现,以可重现的方式很难手动评估搜索结果的正确性,因为确定代码段相对于输入查询的相关性或正确性会因人而异。

因此,我们决定使用自动评估流水线进行评估。我们的流水线在搜索结果和地面真实代码段之间采用相似度来评估查询是否正确回答。我们可以将实验扩展到更大的问题集(例如 Android-287),并以可重复的方式评估结果的正确性。我们使用 Stack Overflow 上找到的代码答案来提供一致的评估依据。图 7 概述了该评估流程。

自动化管道确实要求我们选择一个相似性阈值来确定是否已回答查询。为了确定该值,两位作者手动评估了 CODEnn 和 UNIF 产生的 Java-50 排名前 10 位的搜索结果的相关性。这项评估是单独进行的,对相互矛盾的决定进行了交叉检查和重新评估。一旦确定了相关结果的最终集合,我们就针对适当的地面真相答案为每个结果计算了相似性度量。这产生了近似正常的分数分布。我们取均值并将其用作评估中的相似性阈值。选择的该阈值将产生 CODEnn 的评估指标,该指标通常与其原始论文中的相对应。

在我们的评估中,我们列出了前 k 个结果中回答的问题数量。我们考虑排名靠前的 1、5 和 10 个结果,并分别显示相应的问题数量,分别为6b85af6bb3a6e647268f8957b88d2561.png

3c05c1e47deb009467d23f499b6f9448.png

643cbe3068a64c2210f08e33b8e221e7.png

a3f72295b88a84341731b2db508312c0.png

4. 结果

现在,我们介绍我们的研究结果以及提出的每个研究问题的答案。

4.1 RQ1

在基于配对代码和自然语言的语料库的监督下扩展有效的无监督代码搜索技术是否能改善性能?

UNIF 是 NCS 的扩展,它增加了在训练过程中修改嵌入的监督,并替换了将代码令牌嵌入与学习注意结合起来的 TF-IDF 权重。表 3 显示 UNIF 针对 Java-50 全面回答了更多问题。UNIF 改进了 Android-287 的前 10 个结果中的答案数量,但对前 1 个结果中的答案却稍差一些。我们得出的结论是,扩展 NCS(一种无监督的技术),通过监督可以提高代码搜索的性能,但从我们数据集的结果来看并不一致。

4.2 RQ2

更复杂的网络是否可以提高有监督的神经代码搜索的性能?

在选择可能的监督技术时,神经网络代码搜索系统设计人员可以选择合并更复杂的体系结构(例如 CODEnn 或 SCS),或者选择简单的体系结构(例如 UNIF 中使用的体系结构)。为了解决这个问题,我们考虑了用不同技术回答的查询数和计算成本。

我们首先根据正确回答的查询数量比较模型性能。表 4 显示,使用简单的词袋方法的 UNIF 在两个基准查询集上均优于 CODEnn 和 SCS。在这两种情况下,CODEnn 的性能均优于 SCS。全面解释神经网络系统中的性能差异是一个悬而未决的研究问题。这样一来,就无法对影响 UNIF 效果的因素进行深入讨论。但是,我们推测 CODEnn 和 SCS 使用令牌顺序会导致过拟合,而 UNIF 的词袋式嵌入会导致形式化,从而可以在评估过程中更好地推广。但是,我们注意到,这个猜想并不是我们通过实验探索的。

复杂性折衷中的第二个考虑因素是跨架构的计算成本。由于它们执行的计算量较大,因此更复杂的网络(尤其是消耗序列并因此保持中间状态的网络)通常速度较慢。更简单的架构可以提供更快的推断并减少训练时间。

作为量化计算增量的一种方法,我们测量了嵌入 CODEnn-Java-Train 的代码和自然语言描述样本的时间。代码条目被嵌入到一批大小为 1000 的批处理中,而查询一次被嵌入一次,以反映代码搜索系统中的预期行为,该系统将代码离线嵌入并存储在索引中,而查询则被实时嵌入。

表 5 显示了每一列中相对于 UNIF 的推断时间的比率,因此,值大于 1.0 表示该列的推断速度较慢。CODEnn 和 SCS 等基于序列的网络需要更长的时间才能嵌入代码和自然语言输入。

请注意,所有系统都可以脱机嵌入代码片段,并且实时嵌入查询的时间相对较少。但是,从简单的 UNIF 到更复杂的网络(CODEnn 和 SCS)时,嵌入代码和查询的时间相对增加,突出显示了这些网络执行的计算量增加。

9504e9ca623022cfe18ce55ee376654a.png

4.3 RQ3

基于文档字符串作为训练语料库的自然语言组成部分的监督效果如何?

到目前为止,所介绍的监督技术在训练过程中使用了相同的自然语言:文档字符串。文档字符串被用作用户查询的代理,并允许神经代码搜索从业人员收集较大的对齐数据集进行训练。但是,在 GitHub-Android-Train 上进行训练时,搜索性能并不会总是得到改善,这与预期相反。

在实验中,我们使用替代的理想化训练语料库 StackOverflow-Android-Train,该语料库与基准测试 Android-287 来自同一来源,但仍然与查询脱节。凭直觉,给定训练语料库匹配最终用户查询,使用这种语料库可获得的性能可以衡量多少监督技术可以改善搜索

表 6 显示了当我们在 StackOverflow-Android-Train 上进行训练时,所有受监督的技术都得到了显著改善。如果可以访问具有自然语言成分的理想训练语料库,则可以更好地匹配用户查询,这就是监督技术可以提供的令人印象深刻的搜索性能。

0aaf6990c8aeb4a33c25050fb8bee3b0.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值