当前位置: 首页 > 科技观察

如何提高代码搜索性能?GitHub团队打造了代码搜索领域的GLUE数据集

时间:2023-03-15 00:27:19 科技观察

想要提高代码搜索的效果?首先,您必须知道什么算作改进。GitHub团队创建了CodeSearchNet语料库,为代码搜索领域提供基准数据集,提高代码搜索结果的质量。搜索代码以重用、调用或查看其他人如何解决问题是软件开发人员日常工作中最常见的任务之一。然而,代码搜索引擎通常不是很有效,而且与常规网络搜索引擎不同,它不能完全了解您的需求。GitHub团队尝试使用现代机器学习技术改进代码搜索结果,但很快意识到一个问题:他们无法衡量改进。自然语言处理领域有GLUEbenchmark,代码搜索评估领域没有合适的标准数据集。因此GitHub与Weights&Biases合作,昨天推出了CodeSearchNetChallenge评估环境和排行榜。同时,GitHub还发布了一个大型数据集来帮助数据科学家构建适合该任务的模型,并提供了几个代表当前技术水平的基线模型。该排行榜使用查询注释数据集来评估代码搜索工具的质量。论文地址:https://arxiv.org/abs/1909.09436语料和基线模型地址:https://github.com/github/CodeSearchNet挑战地址:https://app.wandb.ai/github/codesearchnet/benchmarkCodeSearchNet语料库使用专家注释来创建足够大的数据集来训练高容量模型是昂贵且不切实际的,因此GitHub创建了一个质量较低的代理数据集。GitHub遵循[5,6,9,11]中的做法,将开源软件中的功能与其相应文档中的自然语言相匹配。但是,这样做需要大量的预处理步骤和启发式方法。通过对常见错误案例的深入分析,GitHub团队提出了一些通用规则和决策。CodeSearchNet语料库收集过程GitHub团队从开源非forkGitHubrepo收集语料库,使用libraries.io确认所有项目至少被另一个项目使用,并按“流行度”排序(流行度是基于star和货叉号)。然后,删除没有许可证或未明确允许重新分发的项目。然后,GitHub团队使用其通用解析器TreeSitter对所有Go、Java、JavaScript、Python、PHP和Ruby函数(或方法)进行标记化,并使用启发式正则表达式对与函数对应的文档文本进行标记化。筛选为了为CodeSearchNet挑战生成训练数据,GitHub团队首先考虑了语料库中具有相关文档的函数。这会产生一组(c_i,d_i)对,其中c_i是函数,d_i是相应的文档。为了让数据更适合代码搜索任务,GitHub团队进行了一系列的预处理步骤:文档d_i被截断,只保留第一个完整的段落,使文档长度与搜索查询相匹配,而in-删除了函数参数和返回值的深度分析。讨论。删除d_i短于三个标记的对,因为此类注释不提供信息。删除c_i实现少于三行的对,因为它们通常包含未实现的方法、getter、setter等。删除名称包含子字符串“test”的函数。同样,删除构造函数和标准扩展方法,如Python中的__str__和Java中的toString。识别(近似)数据集中的重复函数,只保留它们的一个副本,从而删除数据集中的重复项。这消除了多个版本的自生成代码和复制粘贴。过滤后的语料和数据提取代码详见:https://github.com/github/CodeSearchNet数据集详情该数据集包含200万个函数-文档对和约400万个没有对应文档的函数(见下表1)).GitHub团队将数据集按照80-10-10的比例划分为训练集/验证集/测试集,建议用户按照这个比例使用该数据集。表1:数据集详细信息限制数据集非常嘈杂。首先,文档和查询有本质区别,它们使用不同的语言形式。文档通常是代码作者在编写代码时编写的,他们倾向于使用相同的词汇,这与搜索查询不同。其次,虽然GitHub团队在创建数据集的过程中进行了数据清洗,但他们无从知晓每个文档d_i对对应代码段c_i的描述有多准确。最后,一些文档是用非英文文本编写的,而CodeSearchNetChallenge评估数据集主要关注英文查询。CodeSearchNet基线模型基于GitHub之前在语义代码搜索领域的努力,该团队发布了一组基线模型,这些模型利用现代技术来学习序列,包括类似BERT的自注意力模型,以帮助数据科学家解锁代码搜索。与之前的工作一样,GitHub团队使用代码和查询的联合嵌入实现了神经搜索系统。该架构对每种输入(自然或编程)语言使用一个编码器,并对其进行训练,使输入映射到一个联合向量空间。它的训练目标是将代码及其对应的语言映射到相邻的向量,这样我们就可以嵌入查询进行搜索,然后返回嵌入空间中“附近”代码段的集合。考虑到查询和代码之间更多交互的更复杂模型当然会表现得更好,但是为每个查询或代码段生成单个向量可以实现更高效的索引和搜索。为了学习这些嵌入函数,GitHub团队在架构中加入了一个标准的序列编码器模型,如图3所示。首先,根据其语义对输入序列进行预处理:将代码令牌中的标识符拆分为子令牌(例如,变量camelCase变成了两个子词法:camel和case),使用字节对编码(byte-pairencoding,BPE)来分割自然语言词法。图3:模型架构概述然后使用以下架构之一处理令牌序列以获得(上下文化的)令牌嵌入。神经词袋模型:每个(子)标记都被转换成可学习的嵌入(向量表示)。双向RNN模型:使用GRU单元汇总输入序列。一维卷积神经网络:用于处理输入的token序列。自注意力模型:它的多头注意力用于计算序列中每个标记的表示。之后,这些标记嵌入使用池化函数组合成序列嵌入,GitHub团队实现了均值/最大池化和类注意力的加权求和机制。下图显示了基线模型的总体架构:CodeSearchNetChallenge为了评估代码搜索模型,GitHub团队收集了一组代码搜索查询,并要求程序员标记查询与可能结果的相关性。他们首先从Bing收集了一些常见的搜索查询,结合StaQC中的查询,得到了总共99个与代码概念相关的查询(GitHub团队删除了API文档查询问题)。图1:按照注释者的指导,GitHub团队使用标准Elasticsearch和基线模型从CodeSearchNet语料库中为每个查询获得了10个可能的结果。最后,GitHub团队要求程序员、数据科学家和机器学习研究人员根据标准[0,3]标记每个结果与查询的相关程度(0表示“完全不相关”,3表示“完全相关”匹配”)。未来,GitHub团队希望在此评估数据集中包含更多语言、查询和注释。在接下来的几个月里,他们将继续添加新数据,为下一版CodeSearchNet挑战赛创建扩展数据集。