When deep learning met code search [ESEC/FSE 2019]
José Cambronero MIT CSAIL U.S.A.
Hongyu Li Facebook, Inc. U.S.A.
SeohyunKim Facebook,Inc. U.S.A.
KoushikSen EECSDepartment,UCBerkeley U.S.A.
SatishChandra Facebook,Inc. U.S.A.
最近有多个关于使用深度神经网络进行自然语言代码搜索的建议。这些建议的共同点是将代码和自然语言查询嵌入到真实的向量中,然后使用向量距离来近似代码和查询之间的语义相关性。有多种方法可用于学习这些嵌入,包括仅依赖于代码示例语料库的无监督技术,以及使用成对代码和自然语言描述的对齐语料库的有监督技术。这种监督的目标是生成与查询和相应所需代码片段更相似的嵌入。
显然,在是否使用监督技术、使用何种方法、使用何种网络和培训来进行监督方面都有选择。本文将首先系统地评估这些选择。为此,我们将最先进技术的实现汇编在一个通用平台上,训练和贬值语料库。为了探索网络复杂性中的设计空间,我们还引入了一个新的设计点,将现有的无监督技术扩展为最小监督技术。
我们的评估表明:1. 在现有的无监督技术上添加监督可以提高性能,但不一定很大; 2. 简单的监督网络比复杂的基于序列的代码搜索网络更有效; 3.虽然使用文档字符串进行监督很常见,但文档字符串的有效性与更适合查询的监督语料库之间存在相当大的差距。
一句话:系统评估监督学习,方法,网络对代码搜索任务的影响;提出新的设计点,将现有的无监督技术扩展为最小监督技术。
导论
Overview
图2提供了神经代码搜索的总体概述,并概述了不同的技术,我们将在本文中详细介绍这些技术。神经代码搜索系统的核心抽象是嵌入的概念,它是共享向量空间中输入的向量表示。通过计算向量相似度度量,如余弦相似度,在这些嵌入上,搜索可以检索与用户查询在语义上相关的代码片段。例如,在图2中,查询“我如何遍历hashmap?”'通过一种可能的技术(NCS)映射到向量。候选代码片段也使用相同的技术映射到向量。
候选代码片段可以使用向量相似性进行排序。神经代码搜索的一个关键挑战是如何以向量相似性与语义相关性相一致的方式学习这些嵌入。如图2所示,用于学习这些表示的模型可以大致分为无监督和有监督两类。在我们探索神经技术优势的过程中,我们从NCS开始,这是我们之前构建的一种有效的、无监督的神经代码搜索技术[29]。由于NCS显示出有希望的结果,我们想通过额外的设计增强来试验改进这一基线的可能性。特别是,最近的工作[15,20]提出了有前途的监督神经代码搜索技术,分别标记为CODEnn和SCS,它们成功地使用源代码和文档字符串的语料库学习代码和自然语言嵌入。
这种监督的目标是学习为用户查询生成更多相似向量的映射和相应的所需代码。在图2中,实线箭头描述了这个目标,当使用监督模型进行映射时,实线箭头将查询和正确代码片段的嵌入移动得更近。
有如此多的技术可供选择,试图设计和部署代码搜索解决方案的人如何做出明智的选择? 例如,监管听起来是个好主意,但相对于获取监管数据的开销,它能带来多少好处呢?与我们在本文中介绍的一个更简单的网络(图2中的UNIF,下面将进一步描述)相比,更复杂的网络(具有更多参数)能带来多少价值(如果有的话)?当模型应用于真实用户查询时,使用文档字符串进行的模型监督是否可能限制性能? 在这项工作中,我们试图定量地理解这些权衡。为此,我们在上述代码搜索技术的背景下制定实验。
NCS: Facebook开发的一种神经代码搜索的无监督技术[29],它只使用来自代码语料库的词嵌入。
CODEnn: 最近一篇关于使用深度神经网络进行代码搜索的论文中的一种监督技术[15],它使用多个基于序列到序列的网络,并且被证明优于其他最先进的代码搜索技术。我们使用作者提供的实现[16]。
SCS: 一个使用多个序列到序列网络的监督神经代码搜索系统。我们使用作者在博客文章[20,21]中提供的实现。
UNIF: 我们自己创造的基础NCS技术的监督扩展。UNIF使用基于词袋的网络,与基于词序列的网络相比,其复杂性显著降低。这个简单的模型是本文的一个新贡献。
Contributions
(1) 我们相信这是第一篇比较最近在同一平台上运行的神经代码搜索系统和使用相同语料库进行评估的论文。
(2) 我们提出了神经代码搜索系统谱中的一个新的设计点:UNIF,它是NCS的一个扩展,最小程度地增加了监督,没有其他任何东西。
(3) 我们的发现是,UNIF优于一些更复杂的网络设计(CODEnn和SCS)以及NCS(无监督技术)。此外,在监督中使用的对齐语料库的选择是非常相关的:一个理想化的训练语料库表明,监督技术可以提供令人印象深刻的性能,并突出了在典型代码和文档字符串对齐语料库上进行训练可能不会立即明显的性能差异。
方法
NCS
在NCS[29]中,一种以神经代码搜索的一般概念命名的特定技术,嵌入函数
E
c
E_c
Ec 和
E
q
E_q
Eq 是使用fastText[7] (类似于word2vec[27]) 和传统信息检索技术 (如TF-IDF) 的令牌级嵌入的组合来实现的。因此,该技术不使用传统的深度神经网络,也不使用监督训练。NCS计算一个嵌入矩阵
t
∈
R
∣
V
c
∣
×
d
t ∈ R^{|V_c| × d}
t∈R∣Vc∣×d,其中
∣
V
c
∣
|V_c|
∣Vc∣ 为编码标记词汇表的大小,
d
d
d 为标记嵌入的选择维数,
T
T
T 第
k
k
k 行为第
k
k
k 个单词
V
c
V_c
Vc 的嵌入。
NCS将相同的嵌入矩阵应用于代码片段和查询,如下所示。令
c
=
{
c
1
,
…
,
c
n
}
c = \{c_1, …, c_n\}
c={c1,…,cn},
q
=
{
q
1
,
…
,
q
m
}
q = \{q_1, …, q_m\}
q={q1,…,qm} 分别将代码片段和查询表示为令牌的多集(即顺序不敏感)。NCS生成一袋嵌入向量
{
T
[
c
1
]
,
…
,
T
[
c
n
]
}
\{T[c_1], …, T[c_n]\}
{T[c1],…,T[cn]} 为代码片段,
{
T
[
q
1
]
,
…
,
T
[
q
m
]
}
\{T[q_1], …, T[q_m]\}
{T[q1],…,T[qm]} 表示查询,
T
[
w
]
T[w]
T[w] 是token
w
w
w 在矩阵T中的嵌入向量。
为了将代码标记嵌入包组合成单个代码向量
e
c
e_c
ec, NCS对由其相应的TF-IDF权重加权的唯一标记集的嵌入求和。TF-IDF权重旨在增加在代码片段中频繁出现的令牌的权重,并减少在所有代码语料库中全局频繁出现的令牌的权重。
UNIF: A Supervised Extension of NCS
接下来我们将介绍UNIF,因为它是NCS技术的监督最小扩展。在该模型中,我们使用监督学习来修改初始标记嵌入矩阵
t
t
t,并分别为代码和查询标记生成两个嵌入矩阵
T
c
T_c
Tc 和
t
q
t_q
tq。我们还用学习到的基于注意力的加权方案取代了代码标记嵌入的TF-IDF加权。我们将这种扩展的方法称为嵌入统一(UNIF)。
我们假设一个对齐的代码片段语料库及其自然语言描述可用于训练。我们将这个语料库表示为
(
c
,
q
)
(c, q)
(c,q) 的集合,其中
c
c
c 是令牌包
c
1
,
…
,
c
n
c_1, …, c_n
c1,…,cn 来自一个代码片段,而
q
q
q 是来自其相应的自然语言描述的一组令牌。
函数
E
c
E_c
Ec 和
E
q
E_q
Eq 的构造如下: 设
T
q
∈
R
∣
V
q
∣
×
d
T_q ∈ R^{| V_q | × d}
Tq∈R∣Vq∣×d 和
T
c
∈
R
∣
V
c
∣
×
d
T_c ∈ R^{|V_c| × d}
Tc∈R∣Vc∣×d 为两个嵌入矩阵,分别将自然语言描述(特别是文档字符串和查询)和代码标记中的每个单词映射到长度为
d
d
d 的向量。这两个矩阵使用相同的初始权值
T
T
T 进行初始化,并在训练期间分别进行修改。
对于每个代码片段获得一个嵌入向量集合
{
T
c
[
c
1
]
,
.
.
.
,
T
c
[
c
n
]
}
\{T_c[c_1],...,T_c[c_n]\}
{Tc[c1],...,Tc[cn]}, 同样,对于每个描述
q
q
q,我们计算一个简单的平均值,将查询令牌嵌入组合成一个向量。简单平均也存在于NCS中,我们发现它在实验中优于基于注意力的权重。
为了将每一集合代码 token 向量组合成捕获相应实体语义的单个代码向量,我们使用注意力机制来计算加权平均值。注意权值
a
c
∈
R
d
a_c ∈ R^d
ac∈Rd 是一个
d
d
d 维向量,是在训练过程中习得的。
a
c
a_c
ac在NCS中充当TF-IDF权重的学习对等物。
CODEnn
与UNIF类似,CODEnn[15]也使用神经网络对
E
c
E_c
Ec 和
E
q
E_q
Eq 进行建模,并采用监督学习; 然而,使用的网络更加复杂和深入。我们坚持原作者的命名,将这个模型称为CODEnn,即代码描述嵌入神经网络的缩写。CODEnn没有将代码段视为一袋令牌,而是从包含代码段的方法的名称、代码段中的API调用序列和代码段中的一袋令牌中提取单词序列。从方法名中提取单词序列是通过将方法名拆分为骆驼大小写和蛇形大小写来实现的。
方法名序列和API序列作为两个独立的双向长短期记忆(bi-LSTM)网络的输入。在对方法名和API序列应用两个独立的 LSTM 之后,CODEnn获得两个隐藏状态序列。CODEnn总结每个这样的隐藏状态序列以获得单个向量。总结一下,CODEnn使用最大池函数。
代码标记包中的每个标记单独作为前馈密集神经网络的输入,输出向量被最大池化。最后的代码嵌入是通过将这三个向量(两个来自 LSTM,一个来自前馈网络)连接起来,并将它们提供给一个密集的神经网络,该神经网络产生一个汇总向量等。
CODEnn使用双向 LSTM 实现函数
E
q
E_q
Eq,它将在doc字符串中找到的代码片段的描述作为输入序列,以产生
E
q
E_q
Eq。图5提供了该体系结构的概述。
SCS
我们引入了另一种基于监督序列的深度神经网络,用于代码搜索,由GitHub的数据科学团队描述和实现[20]。我们将这个模型称为SCS,即语义代码搜索(Semantic Code Search)的缩写。LSTM网络[26]为训练语料库中的文档字符串学习语言模型[32]。该模型可用于嵌入自然语言并计算给定自然语言输入的概率。
最后一个模块学习一个转换(以前馈层的形式)来预测给定代码令牌序列的查询嵌入。为了学习这种转换,模块采用代码到文档字符串模型的编码器部分,冻结其层,并在代码序列输入和使用语言模型生成的相应查询嵌入上训练网络。最后的训练阶段通过将编码器层解冻几个epoch来微调整个网络。SCS使用代码到文档字符串模型的这个微调编码器部分作为
E
c
E_c
Ec,使用语言模型作为
E
q
E_q
Eq。图6提供了该体系结构的概述。
表1提供了在学习 E c E_c Ec 和 E q E_q Eq 时使用监督的模型的网络细节概述:UNIF, CODEnn和SCS。
实验
我们的评估使用不同的数据集和基准。为了清晰起见,我们使用以下术语:
Training Corpora
coden - java - train是[15]作者公开发布的数据集。这个语料库由大约1600万个预处理的Java方法及其相应的文档字符串组成,用于训练。该数据集包括四种类型的输入:方法名称序列、API序列、一组方法体令牌和文档字符串序列。另外,我们通过将方法名称序列连接到API序列并将此连接的序列视为一袋令牌来派生另一个输入。这种派生的输入用于训练联合部队和SCS。
GitHub-Android- train是一个Android专用的语料库,我们通过收集大约26,109个GitHub存储库中的Android标签来构建。我们选取了所有带有文档字符串的方法(总共大约787,000个),并将这些方法用作训练数据。
StackOverflow-Android-Train是一个android专用的训练语料库,我们通过收集StackOverflow问题标题和代码片段答案来构建。我们通过从Stack Exchange公开发布的数据转储中提取所有带有Android标签的Stack Overflow帖子来准备这个数据集[31]。
Search Corpora
CODEnn-Java- search:由CODEnn的作者发布的400万个惟一的Java方法。
GitHub-Android- search:从GitHub收集的550万个独特的Android方法。这个语料库来源于用于构建GitHub-Android-Train的相同26,109个存储库,但也包括没有可用文档字符串的方法。
Benchmark Queries
Java-50 是一组50个查询,用于评估原始论文中的CODEnn。这些查询对应于Stack Overflow票选的前50个Java编程问题。作者包括在Java中有“具体答案”的问题,包括在带有代码的线程中可接受的答案的问题,并且不是重复的问题。当在这个基准上进行评估时,模型是在coden - java - train上训练的。
Android-287 是一组287个android特定查询,用于评估原始论文中的NCS。这些问题由脚本根据以下标准选择:(1)问题标题包含“Android”和“Java”标签;(2)存在一个赞码(upvoted)答案;(3)在GitHub Android仓库的语料库中至少有一个匹配的真实代码片段。在此基准上进行评估时,除非另有说明,否则模型将在GitHub-Android-Train上进行训练。
RQ1
基于成对代码和自然语言的语料库的监督,扩展有效的无监督代码搜索技术是否会提高性能?
如3.2节所述,UNIF是NCS的扩展,它在训练过程中增加了监督来修改嵌入,并取代了用于将代码标记嵌入与学习到的注意组合在一起的TF-IDF权重。表3显示了UNIF在Java-50中回答了更多的问题。UNIF提高了Android-287中排名前10的答案的数量,但对于排名前1的答案的表现略差。我们得出的结论是,扩展NCS(一种无监督技术),通过监督可以提高代码搜索的性能,但在我们的数据集上并不一致。
RQ2
更复杂的网络是否能提高监督神经代码搜索的性能?
当选择可能的监督技术时,神经代码研究系统设计者可能会选择合并更复杂的架构,如CODEnn或SCS,或者倾向于一个简单的架构,如在UNIF中使用的架构。为了解决这个问题,我们考虑了不同技术回答的查询的数量,以及它们的计算成本。
我们首先根据正确回答的查询数量比较模型的性能。表4显示了使用简单词袋方法的UNIF在两个基准查询集上的性能都优于CODEnn和SCS。在这两种情况下,CODEnn的表现都优于SCS。
表5显示了每列中推理时间相对于UNIF的比率,因此高于1.0的值表示该列的推理较慢。基于序列的网络,如CODEnn和SCS,需要更长的时间来嵌入代码和自然语言输入。请注意,所有系统都可以离线嵌入代码片段,并且实时嵌入查询所需的时间相对较少。然而,从简单的UNIF到更复杂的网络(CODEnn和SCS),嵌入代码和查询所需时间的相对增加突出了这些网络执行的计算量的增加。
RQ3
基于文档字符串作为训练语料库的自然语言组成部分的监督效果如何?
到目前为止,所介绍的监督技术在训练期间使用了相同的自然语言:文档字符串。文档字符串被用作用户查询的代理,并允许神经代码搜索从业者收集相当大的对齐数据集用于训练。然而,当在GitHub-Android-Train上训练时,搜索性能并不总是提高,与预期相反。
表6显示,当我们在StackOverflow-Android-Train上进行训练时,所有有监督的技术都得到了显着改善(只有一个例外,使用SCS回答的查询在前1中)。这突出了有监督技术可以提供的令人印象深刻的搜索性能,如果允许访问具有更好地匹配用户查询的自然语言组件的理想训练语料库。
总结
References
[7] Piotr Bojanowski, Edouard Grave, Armand Joulin, and Tomas Mikolov. Enriching word vectors with subword information. Transactions of the Association for Computational Linguistics, 5:135–146, 2017.
[15] Xiaodong Gu, Hongyu Zhang, and Sunghun Kim. Deep code search. In Proceedings of the 40th International Conference on Software Engineering, pages 933–944. ACM, 2018.
[16] Xiaodong Gu, Hongyu Zhang, and Sunghun Kim. Deep code search github repository, 2018. URL: https://github.com/guxd/deep-codesearch/#54130b6be41fc5d73c4ebb8422942a7b53ad4024
[20] Hamel Husain and Ho-Hsiang Wu. How to create natural language semantic search for arbitrary objects with deep learning, 2018. URL:https://towardsdatascience.com/semantic-code-search-3cd6d244a39c.
[21] Hamel Husain and Ho-Hsiang Wu. Towards natural language semantic code search, 2018. URL: https://githubengineering.com/towards-natural-languagesemantic-code-search/.
[26] Stephen Merity, Nitish Shirish Keskar, and Richard Socher. Regularizing and Optimizing LSTM Language Models. arXiv preprint arXiv:1708.02182, 2017.
[27] Tomas Mikolov, Ilya Sutskever, Kai Chen, Greg S Corrado, and Jeff Dean. Distributed representations of words and phrases and their compositionality. In Advances in neural information processing systems, pages 3111–3119, 2013.
[29] Saksham Sachdev, Hongyu Li, Sifei Luan, Seohyun Kim, Koushik Sen, and Satish Chandra. Retrieval on source code: a neural code search. In Proceedings of the 2nd ACM SIGPLAN International Workshop on Machine Learning and Programming Languages, pages 31–41. ACM, 2018.
[31] Inc. Stack Exchange. datastack exchange data dump, 2018. URL: https://archive.org/details/stackexchange.
[32] Ilya Sutskever, Oriol Vinyals, and Quoc V Le. Sequence to sequence learning with neural networks. In Advances in neural information processing systems, pages 3104–3112, 2014.