选自arXiv
作者:Jose Cambronero等
机器之心编译
参与:魔王
高效搜索代码可以大幅提升开发者的工作效率,然而目前的代码搜索效果并不尽如人意。近期,越来越多的研究者开始关注利用深度学习解决代码搜索问题。这篇论文概述了神经代码搜索技术,并提出了一种新型方法 UNIF 网络。
论文地址:https://arxiv.org/pdf/1905.03813v3.pdf
近期多项研究提出利用深度神经网络和自然语言执行代码搜索,这些提议的共性是:将代码和自然语言 query 转变为真实向量,并利用向量距离近似代码和 query 之间的语义相关性。目前已有多种方法可以学习这些向量 [15, 19, 24, 26],包括仅依赖代码示例语料库的无监督方法,和使用代码和自然语言描述对语料库的监督方法。监督方法旨在生成与 query 及其对应代码段更相似的嵌入。
很明显,每个研究者都可以选择是否使用监督技术,如果使用,ta 还可以选择用哪种网络和训练方法。由 MIT CSAIL、Facebook、UC 伯克利研究者合作的这篇论文首次系统性地评估了这些选择。为此,研究者集合了在同样的平台、训练和评估数据上运行的多个当前最优技术的实现。为了探索网络复杂度的设计空间,研究者还提出了新的设计点,即对现有无监督技术添加监督信号的极小扩展变体。
评估结果表明:
- 向现有无监督技术添加监督信号可以提升性能,不过提升幅度不大;
- 简单监督网络的代码搜索效果比更复杂的序列网络更加高效;
- 尽管使用文档字符串(docstrings)添加监督是常见做法,但文档字符串的效果与更贴合 query 的监督数据之间仍存在很大差距。
代码搜索的整体图景是什么样的?
代码搜索的目标是从大型代码库中检索出与开发者需求最匹配的代码段,而开发者需求通过自然语言来表达。
近期学界和工业界都在尝试利用深度学习实现更高级的代码搜索。我们将这类方法叫做「神经代码搜索」。
下表 1 展示了一些基于自然语言 query 检索到的代码段示例,从中我们可以看出这项技术很有前景。但是,表中展示的这类 query 及其检索结果也表明,仅依靠正则表达式匹配这类简单方法很难解决代码搜索任务。
表 1:代码搜索结果示例。每一个结果都是该研究提出的 UNIF 模型找到的 top 1 结果。GitHub 网站现有的代码搜索接口对这些 query 所返回的前十个结果中都没有相关的代码段。
下图 1 提供了神经代码搜索的通用概览,并介绍了几种不同的方法。神经代码搜索系统中的核心抽象是嵌入概念,即输入在共享向量空间内的向量表示。通过对这些嵌入计算向量相似度度量(如余弦相似性),系统检索到与用户 query 最具语义相关性的代码段。
图 1:使用嵌入进行代码搜索时,query 和候选代码段都被映射至共享向量空间,二者所使用的函数分别为 E_q 和 E_c。然后,搜索即相当于最大化 query 嵌入和代码嵌入之间的向量相似度度量(如余弦相似性)。向量表示可以通过无监督方式学得,即仅使用代码,也可以通过监督方式学得,即利用代码段及其对应自然语言描述对数据。
如上图 1 所示,用于学习这些表示的模型可以大致分为无监督和有监督两类。本文探索神经代码搜索技术的优势,将从 NCS 开始说起,这是一种高效的无监督神经代码搜索技术。近期研究 [15, 19] 提出了有前景的监督式神经代码搜索技术:labeled CODEnn 和 SCS,它们利用源代码和文档字符串成功学得代码和自然语言嵌入。
使用此类监督信号的目标是,学习能够生成与用户 query 及其对应代码更相似向量的映射。图 1 中,该目标由 Shared space 中的两条实线表示,分别表示移动 query 和合适代码段的嵌入,使其更加接近。
研究贡献
该研究使用开源评估语料库对以上代码搜索技术进行了实验。其中三项技术是之前研究提出来的:
- NCS:Facebook 开发的无监督神经代码搜索技术 [26],它仅使用从代码库中得到的词嵌入;
- CODEnn:近期研究 [15] 提出的一种监督式神经代码搜索技术,它使用多个序列到序列网络,性能优化当前其他最优技术。该研究所用实现来自原作者 [16];
- SCS:使用多个序列到序列网络的监督式神经代码搜索系统。该研究所用实现来自原作者所著博客 [19, 20]。
研究者想要了解基于词序列的复杂网络所起的作用,因此他们开发了一种方法,是对 NCS 技术添加监督信号得到的极小扩展变体:
- UNIF:NCS 技术的监督扩展。该技术使用词袋网络,其复杂度显著低于基于词序列的网络。这一简单模型是该研究的新贡献。
神经代码搜索模型一览
NCS
图 2:NCS 使用 fastText [7] 嵌入将代码和 query 输入转换为向量。代码句嵌入 e_c 是通过对这些无序代码嵌入执行 TF-IDF 加权平均计算得到。query 嵌入 e_q 通过对这些无序 query 嵌入取平均得到。
UNIF
图 3:UNIF 网络使用注意力 a_c 结合 token 嵌入 T_c,并输出代码句嵌入 e_c。query 嵌入 e_q 通过对这些无序 query 嵌入 T_q 取平均得到。T_c 和 T_q 都使用 fastText 嵌入进行初始化,并在训练过程中进一步微调。
CODEnn
图 4:CODEnn 网络。它使用 RNN 嵌入方法名(r_1)、API 序列(r_2)和 query(r_3),使用前馈网络(MLP)嵌入代码主体 token(m_1),并将该嵌入与方法名嵌入和 API 序列嵌入结合起来,再使用另一个 MLP(m_2)。
SCS
图 5:SCS 使用基于代码-文档字符串的网络的编码器部分,来嵌入代码 token 序列。它另外训练了一个语言模型来处理 query token,并在代码编码器上添加一个前馈层,将代码嵌入转换为 query 嵌入(来自语言模型)。
效果
这部分展示了研究结果,以及每个研究问题的答案。
- 问题 1:基于代码和自然语言对数据,用监督信号扩展高效无监督神经代码搜索技术能否提升性能?
- 问题 2:更复杂的网络能否提升监督神经代码搜索方法的性能?
- 问题 3:使用文档字符串作为训练语料库的自然语言部分的监督技术效果如何?
下表 8 为以上每个问题提供了全面的性能总结:
表 8:评估结果总结。