Xiaodong Gu and Hongyu Zhang and Sunghun Kim. Deep code search. In Proceedings of the 40th International Conference on Software Engineering, 2018, 933--944.
为了实现程序功能,开发人员可以通过大规模搜索来重用以前编写的代码段和代码库。多年来,业界已经提出了许多代码搜索工具来帮助开发人员。现有方法通常将源代码视为文本文档,并利用信息检索模型来检索与给定查询匹配的相关代码段。这些方法主要依靠源代码和自然语言查询之间的文本相似性。他们对查询和源代码的语义缺乏深刻的了解。
在本文中,我们提出了一种名为 CODEnn(代码描述嵌入神经网络)的新型深层神经网络。 CODEnn 不是匹配文本相似性,而是将代码段和自然语言描述共同嵌入到高维向量空间中,以使代码段及其对应的描述具有相似的向量。使用统一的矢量表示,可以根据它们的矢量检索与自然语言查询相关的代码段。还可以识别语义上相关的单词,并且可以处理查询中不相关的关键字/噪声。
作为概念验证应用程序,我们使用 CODEnn 模型实现了一个名为 DeepCS 的代码搜索工具。我们根据从 GitHub 收集的大规模代码库经验性地评估 DeepCS。实验结果表明,我们的方法可以有效地检索相关的代码片段,并优于以前的技术。
在本文中,我们提出了一种名为 CODEnn(代码描述嵌入神经网络)的新型深层神经网络。为了弥合查询和源代码之间的词汇鸿沟,CODEnn 将代码段和自然语言描述共同嵌入到高维向量空间中,以使代码段及其对应的描述具有相似的向量。利用统一的矢量表示,可以根据它们的矢量来检索与自然语言查询语义相关的代码段。 还可以识别语义上相关的单词,并且可以处理查询中不相关的关键字/噪声。
使用 CODEnn,我们实现了代码搜索工具 DeepCS。DeepCS 在来自 GitHub 的 1820 万 Java 代码段(以注释方法的形式)上训练了 CODEnn 模型。然后,它从代码库中读取代码片段,并使用经过训练的 CODEnn 模型将其嵌入向量中。 最终,当用户进行查询时,DeepCS 会找到具有与查询向量最接近的向量的代码片段,并将其返回。
受现有联合嵌入技术的启发,我们针对代码搜索问题提出了一种名为 CODEnn(代码描述嵌入神经网络)的新型深度神经网络。 图 1 说明了 CODEnn 的总体架构。自然语言查询和代码段是异构的,无法根据其词汇标记轻松匹配。 为了弥合差距,CODEnn 将代码片段和自然语言描述共同嵌入到统一的向量空间中,以便将查询和相应的代码片段嵌入附近的向量中,并可以通过测量向量相似度进行匹配。
联合嵌入模型需要三个组件:嵌入函数和 ψ 以及相似性度量。 CODEnn 通过深度神经网络实现了这些组件。神经网络由三个模块组成,每个模块对应于联合嵌入的一个组成部分:代码嵌入网络(CoNN),用于将源代码嵌入向量中。描述嵌入网络(DeNN),用于将自然语言描述嵌入向量中。 相似度模块,用于测量代码和描述之间的相似度。
在本节中,我们对 DeepCS 进行介绍,这是一种基于所提出的 CODEnn 模型的代码搜索工具。对于给定的自然语言查询,DeepCS 推荐前 K 个最相关的代码段。图 2 显示了其整体架构。它包括三个主要阶段:离线培训,离线代码嵌入和在线代码搜索。我们首先收集大规模的代码片段,即带有相应描述的 Java 方法。我们从方法中提取子元素(包括方法名称,标记和 API 序列)。然后,我们使用语料库来训练 CODEnn 模型(离线训练阶段)。对于用户希望从其搜索代码段的给定代码库,DeepCS 提取搜索代码库中每个 Java 方法的代码元素,并使用经过训练的 CODEnn 模型的 CoNN 模块计算代码矢量(离线嵌入阶段)。最后,当用户查询到达时,DeepCS 首先使用 CODEnn 模型的 DeNN 模块计算查询的向量表示,然后返回其向量与查询向量接近的代码片段(在线代码搜索阶段)。从理论上讲,我们的方法可以搜索以任何编程语言编写的源代码。在本文中,我们将范围限制为 Java 代码。
我们按照所述的方法,使用上一节中描述的大规模语料库来训练 CODEnn 模型。 CODEnn 模型的详细实现如下:我们将双向 LSTM(RNN 的最新子类)用于 RNN 实现。所有 LSTM 在每个方向上都有 200 个隐藏单元。我们将单词嵌入的维数设置为 100。CODEnn 具有两种类型的 MLP:用于嵌入单个令牌的嵌入 MLP 和用于组合不同方面的嵌入的融合 MLP。对于嵌入的 MLP,我们将隐藏单元的数量设置为 100,对于融合的 MLP,我们将其设置为 400。CODEnn 模型通过小批量亚当算法进行训练。我们将批处理大小(即每批实例数)设置为 128。为训练神经网络,我们将词汇表的大小限制为训练数据集中最常用的 10,000 个单词。我们基于两个开源深度学习框架 Keras 和 Theano 构建模型。我们在配备一个 Nvidia K40 GPU 的服务器上训练模型。训练持续 500 个纪元,持续约 50 个小时。
给定用户的自由文本查询,DeepCS 通过训练有素的 CODEnn 模型返回相关的代码段。 它首先为搜索代码库中的每个代码段(即 Java 方法)计算代码矢量。然后,它选择并返回查询向量中前 K 个最接近向量的代码段并将其返回。 更具体地说,在搜索开始之前,DeepCS 使用代码的 CoNN 模块将代码库中的所有代码段嵌入向量中。
在本节中,我们将通过实验评估 DeepCS。我们还将 DeepCS 与相关的代码搜索方法进行了比较。
为了更好地评估 DeepCS,我们的实验是在与训练语料库不同的搜索代码库上进行的。 从搜索代码库中检索与用户查询匹配的代码段。实际上,搜索代码库可以是组织的本地代码库,也可以是从开源项目创建的任何代码库。为了构建搜索代码库,我们选择在 GitHub 中具有至少 20 星的 Java 项目。与训练语料库不同,它们被单独考虑并且包含所有代码(包括那些没有 Javadoc 注释的代码)。总共有 9,950 个项目。我们从这些项目中选择所有 16,262,602 种方法。对于每种 Java 方法,我们提取一个方法名称,API 序列,令牌三元组以生成其代码向量。
为了进行比较,我们使用了 CodeHow 和基于 Lucene 的工具进行对比实验,我们对 CodeHow 和基于 Lucene 的工具使用与评估 DeepCS 相同的实验设置
结果表明,DeepCS 产生的搜索结果通常比 Lucene 和 CodeHow 的更相关。图 3a 显示了三种方法的 FRank 的统计摘要。符号“ +”表示每种方法获得的平均 FRank 值。对于在返回的前 10 个结果中未能获得相关结果的查询,我们保守地将 FRank 视为 11。我们观察到 DeepCS 的平均 FRank 为 3.5,比 CodeHow(5.5)和 Lucene(6.0)的平均 FRank 小,从而获得了更多相关的结果。 DeepCS 的 FRank 值集中在 1 到 4 的范围内,而 CodeHow 和 Lucene 产生的方差更大,而相关的结果更少。图 3b,3c 和 3d 显示了当 k 分别为 1、5 和 10 时三种方法的 Precision@k 的统计量。我们观察到,与 CodeHow 和基于 Lucene 的工具相比,DeepCS 的总体精度值更高。为了检验统计显著性,我们使用 Wilcoxon 符号秩检验(p <0.05)比较 DeepCS 和所有相关查询的两种相关方法之间的 FRank 和 Precision@k。对于在返回的前 10 个结果中未能获得相关结果的查询,我们保守地将 FRank 视为 11。 DeepCS 与 Lucene 和 CodeHow 进行比较的 p 值均小于 0.05,表明 DeepCS 相对于相关方法的改进具有统计意义。。
通过比较实验可以发现,DeepCS 的另一个优势与关联搜索有关。也就是说,它不仅查找具有匹配关键字的代码段,而且还推荐没有匹配关键字但在语义上相关的代码段。这很重要,因为它会大大增加搜索范围,尤其是在代码库较小的情况下。此外,开发人员还需要多种用途的代码片段。关联搜索为开发人员提供了更多的代码片段选项供学习。传统的基于 IR 的方法只能匹配包含诸如 xml,object 和 read 之类的关键字的代码片段。但是,如图所示,即使在结果中不存在关键字,DeepCS 也会成功识别查询语义并返回 xml 反序列化的结果。相比之下,CodeHow 仅返回包含读取,对象和 xml 的代码段,从而缩小了搜索范围。因此表明 DeepCS 通过理解语义而不只是匹配关键字来搜索代码。类似地,一行中的 arraylist 的查询初始化返回包含“new ArrayList”的代码段,尽管该代码段不包含关键字初始化。另外,假如搜索时播放歌曲,DeepCS 不仅返回具有匹配关键字的代码片段,而且还建议使用与语义相关的单词(例如音频和语音)推荐结果。
我们提出了一种名为 CODEnn 的新型深度神经网络用于代码搜索。CODEnn 不会匹配文本相似性,而是学习源代码和自然语言查询的统一向量表示,以便可以根据它们的向量来检索与查询语义相关的代码片段。作为概念验证应用程序,我们基于提出的 CODEnn 模型实现了代码搜索工具 DeepCS。 我们的实验研究表明,该方法是有效的,并且优于相关方法。将来,我们将研究源代码的更多方面,例如控制结构,以更好地表示源代码的高级语义。 我们设计的深度神经网络也可能使其他软件工程问题受益,例如错误定位。
据我们所知,我们是第一个提出基于深度学习的代码搜索的。我们工作的主要贡献如下:我们提出了一种新型的深度神经网络 CODEnn,以学习源代码和自然语言查询的统一矢量表示形式。我们开发了 DeepCS,这是一种利用 CODEnn 检索给定自然语言查询的相关代码段的工具。我们使用大规模代码库对 DeepCS 进行了经验评估。
感谢国家重点研发计划课题:基于协同编程现场的智能实时质量提升方法与技术(2018YFB1003901)和国家自然科学基金项目:基于可理解信息融合的人机协同移动应用测试研究(61802171)支持!
本文由南京大学软件学院 2018 级硕士生段定翻译转述。