由于软件的无处不在和软件版本的快速迭代, GitHub, StackOverflow等开源代码仓库中的源代码爆发式增长, 代码大数据时代[1]已经来临. 据Evans Data Corporation[2]报告预计, 2024年, 专业开发人员数会将增加至2 870万. 因此, 如何有效利用海量的源代码相关数据来提高专业开发人员的工作效率, 进而推动代码相关任务的发展(称作代码智能), 已经成为软件工程领域(SE)的研究热点. 要实现代码智能, 代码表征是关键. 代码表征[3]是对源代码的语义和语法信息进行表征, 得到源代码的特征向量, 并将其应用在不同的下游任务上, 例如理解型[4]任务(代码克隆检测、语义代码检索等). 最初, 传统的基于手工的方法[5]利用统计学原理表征代码[6]. 后来, 大量的机器学习算法[7]被运用到代码表征中, 但仍然需要手工从源代码中提取代码特征[8]. 无论是传统的手工方法还是基于机器学习的方法都依赖领域专家的标注, 繁重耗时, 且无法灵活地应用于特定下游任务, 这与绿色低碳的发展理念极不相符. 为解决这个问题, 近年来, 有学者开始将基于深度学习的模型, 如循环神经网络(recurrent neural network, RNN)[9]、卷积神经网络(convolutional neural network, CNN)[10−13]和图神经网络(graph neural network, GNN)[14, 15]等引入到代码表征中, 试图表征隐藏在源代码中的更深层次的复杂特征, 进一步提高代码表征的准确性. 目前, 基于深度学习的方法已经广泛应用于各种代码智能任务.
根据源代码的抽象层次从低到高划分[16], 代码具有以下特征: 文本级特征是以自然语言方式概括函数功能的语句, 如代码注释; 语义级特征是经过词法分析的字符序列, 如代码字符; 功能级特征是以编程语言方式概括函数功能的序列, 如函数方法名和应用程序接口(application programming interface, API); 结构级特征是表示代码句法信息的树形或者图形结构, 如抽象语法树(abstract syntax tree, AST)、数据流图(data flow graph, DFG)、控制流图(control flow graph, CFG)和程序依赖图等. 由于抽象程度越高, 能够提取的信息越多, 所以大部分研究更关注结构级特征. 近年来, 对结构级特征的研究主要集中在AST上. 因为AST含有代码完整的结构信息, 而其他形式的结构表示, 如DFG和CFG都是从AST中提取的. 此外, 如果对代码只做了语义级的字符改变(如修改变量名称或者改变代码风格), 而不改变程序的执行结构, 那么修改后的代码与原始代码在结构信息上的表征是不变的. 因此, 可以利用这一点来实现跨语言表征, 有效避免不同编程语言的语法规则差异问题. 然而, AST的树形结构不适用于通用的Seq2Seq模型, 因此, AST的序列化算法成为研究AST的主要方向. 早期, TBCNN[10]使用基于树结构的CNN[17]来表征抽象语法树. 为解决CNN的长序列学习依赖问题, Code2tree[18]则使用GRU编码器对AST序列进行编码, 并在解码阶段引入注意力机制以提高代码注释的质量. CDLH[19]框架引入了基于树结构的LSTM[20]来挖掘词法信息和句法信息. Code2vec[21]将AST分解成一组路径, 并通过简单的全连接层学习如何聚合路径的原子表示. 后来, mrncs[22]提出了一种基于结构遍历的简化AST的方法, 保留关键句法信息的同时, 得到简化的AST(称作ISBT). 但是, 现有的大多数预训练模型对AST的提取并不充分, 存在一些问题, 如图 1所示. 这些问题包括结点信息的冗余, 即所有结点均出现不止一次, 例如结点A出现了2次; 还有在序列化过程中额外开销的引入, 即序列中用大量的括号来表示一棵子树, 例如子树B的完整表示是“(B(D)D(E)E(F)F)”.
|
图 1 REcomp优化的AST序列化算法的示例 |
近年来, 大规模语言模型已成为自然语言处理及其相关领域的强大工具, 展现出惊艳的性能和多样的应用潜力. 这些模型的成功, 促使研究者开始思考: 是否能将其强大的表示学习能力应用于代码智能领域? 同时, 编程语言(programming language, PL)和自然语言(natural language, NL)有诸多相似之处: 都具有可重复并带有可预测的统计学规律, 所以自然语言处理领域中很多的方法在代码智能领域同样适用. 于是, 研究者尝试将自然语言处理中能够自监督学习的预训练模型, 如Transformer[23], BERT[24], RoBERTa[25], GPT[26], BART[27]等应用到代码表征中. 为此, 编程语言预训练模型[28−32]被提出, 并逐渐统一了生成类、理解类和自回归任务, 得到的代码的通用表示能在下游任务上复用. PLBART[28]是BART[27]在编程语言方面的变体, 将文本级的注释或者语义级的代码字符单独作为代码的特征进行预训练. CodeBERT[29]是BERT在编程语言上的双模态扩展, 将注释和代码字符融合在同一个序列中以表征代码. GraphCodeBERT[30]在CodeBERT基础上进一步添加了数据流图的变量序列作为代码结构级特征的补充表示, 并设计了数据流边预测和变量结点对齐等预训练任务.然而, 在从AST中提取数据流时, 只考虑了存在数值流动关系的代码字符, 这导致部分AST结构信息的遗漏.针对数据遗漏的现象, SynCoBERT[31]直接使用完整的AST作为结构信息的代表, 并将文本级、语义级和结构级特征融合在一个输入序列进行预训练, 同时设计了多模态对比学习、AST边预测和标识符预测等3个预训练任务. 随后, UniXcoder[32]提出了新的融合AST和代码字符的一对一映射算法, 以引入结构级特征并缩短特征序列. 虽然这些编程语言预训练模型在代码智能领域取得了一定的效果, 但它们尚未完全利用代码的各个层次特征(文本级、语义级、功能级和结构级). 目前, 集成所有特征面临以下挑战: 如何减少不必要的结点引入以及如何有效缩短特征序列长度, 同时节省存储、传输和计算资源. 目前尚未有一个预训练模型能够集成所有特征, 现有模型各自涵盖的特征层次各不相同. 因此, 对于综合多个层次特征的编程语言预训练模型, 仍然需要进一步的研究和探索.
为了充分挖掘代码各个层次的特征并更加准确地表征代码的语义信息, 本文提出了一个新的编程语言预训练模型, 称作REcomp. 它旨在融合代码的文本级的注释、语义级的代码字符、功能级的函数名和结构级的AST, 并通过设计多模态对比学习的预训练方法来学习这4个特征之间的语义等价性. 与其他领域有所不同, 在代码智能研究中, 将代码不同视角或层次的特征称为代码不同的模态, 因此, 多个特征的融合称为多模态表征. 之所以选择多模态对比学习的方法对代码进行建模, 是因为它可以通过共享学习的方式将代码的不同模态特征进行交叉融合, 从而进一步提高模型表征代码语义的能力. 这种共享学习的方式不仅减少了多个单一模态模型的训练和推理过程, 也减少了计算资源的开销. 此外, 本文还设计了两种新的数据增强方法, 即编程语言型(PL型)和自然语言型(NL型), 以此构建正负样本进行对比学习.
最后, 本文在公开基准CodeXGLUE[2]数据集上进行了实验, 验证了所提模型的有效性. REcomp很大程度地减少了资源的的消耗, 仅使用了极少的计算资源就达到了极快的训练速度, 并且在极短的时间内收敛. 以初始化模型UniXcoder为例, REcomp仅使用了约UniXcoder算力资源的1/20, 就将训练至收敛的时间约缩短为UniXcoder的1/32. 在语义代码检索任务上, REcomp在CodeSeachNet[33]数据集上提升了约1.9%的准确率; 在代码克隆检测任务上, REcomp在BigCloneBench[34]数据集和POJ-104[35]数据集分别取得了4%和0.9%准确率的提升. 本文的主要贡献如下:
(1) 设计了一种优化的AST序列化方法, 它在保留AST中控制结点信息并且不破坏树结构的前提下, 按序地将非叶结点的结构信息和叶结点的语义信息融合, 得到语义级-结构级的复合特征. 相比SBT[13], 此算法消除了结点冗余和括号重复的现象, 极大程度地缩短了AST特征序列, 更简短且精准地表示AST;
(2) 设计了两种特别的数据增强方法: PL型和NL型, 集成编程语言4个不同层级的特征. PL型旨在学习符合编程语言特点的特征的语义等价性, NL型可以弥合自然语言与编程语言的语义鸿沟;
(3) 提出了多模态对比学习预训练目标, 用于增强模型的代码表征能力, 从而提升模型的下游任务表现.
本文第1节介绍REcomp所涉及的相关工作, 包括预训练编程语言模型、多模态学习和对比学习. 第2节详细地阐述REcomp的模型架构. 第3节描述REcomp的有关实验. 在第4节总结全文工作.
1 相关工作本文方法和预训练编程语言模型、多模态学习和对比学习的现有研究之间存在相关性, 下面对这些相关内容进行介绍.
1.1 预训练编程语言模型预训练模型首先通过一个或者多个任务来预先学习相对泛化的知识, 然后在微调阶段, 利用学到的具体知识进行下游任务[3]. 本节将简要地介绍CodeBERT[29], GraphCodeBERT[30], UniXcoder[32]. 这3个将分别作为REcomp预训练的初始化模型, 它们都是在开源基准数据集CodeSearchNet[33]上进行预训练的.
CodeBERT模型架构与RoBERTa[25]相同, 利用多层双向Transformer[23]进行自监督学习. CodeBERT由12个相同的层组成, 每层的维度大小为768. 模型参数总数达到125M. CodeBERT的掩码语言建模目标用的是带有函数注释的双峰数据, 然后替换令牌检测目标进一步训练在双峰和单峰样本上, 旨在学习一个代码字符是否是原始的. 在微调阶段, CodeBERT在语义代码检索和源代码文档生成上的实验表明, 它优于监督学习的方法.
GraphCodeBERT在CodeBERT基础上结合了代码的数据流, 在预训练阶段对变量之间“值从哪里来”的数值传递关系进行编码. 除了掩码语言建模, 它还引入了两个新的数据流结构感知的预训练任务: 数据流图边预测和变量间结点对齐. GraphCodeBERT利用CodeSearchNet的双峰数据进行预训练, 针对代码检索、克隆检测、代码翻译和代码细化等任务微调. 实验表明, 其微调结果超过了CodeBERT.
UniXcoder在GraphCodeBERT基础上将AST作为结构级特征, 是一种跨模态的编程语言预训练模型.它设计了一个前缀适配器, 这个适配器通过掩码注意力矩阵来控制模型的行为, 这统一了理解任务、生成任务和自回归任务. 它设计了一个AST和代码字符一对一的映射方法, 旨在将结构信息和语义信息融合. 此外, 它通过跨模态生成任务在不同编程语言之间的对齐表示来学习代码的通用表征.它在9个公开数据集上的5个代码相关的任务上进行评估, 结果表明, UniXcoder在大多数任务上都达到了显著的效果.
CodeSearchNet是含有6种编程语言的数据集, 分别包含双峰数据(注释-代码)约213万条和单峰数据(没有注释的代码)约645万条. CodeSearchNet数据集在6种语言上的数据详情见表 1.
| 表 1 关于CodeSearchNet的数据统计 |
多模态学习可以通过利用多模态数据之间的信息互补性, 从多源数据中学到更好的特征表示, 有利于下游任务的学习[36]. 因为编程语言含有多个抽象层次的特征, 所以用单个特征来表示编程语言是远远不够的, 很难覆盖所有视角. 并且不同的模态都是代码表示的平行语料, 具有语义等价性. DeepCS[37]是第一个用RNN融合功能级的API序列、函数名和语义级的代码字符等特征的代码表征模型. 然后, Comformer[38]开始关注结构级特征AST, 提出了一种简单的基于结构的AST遍历算法, 并将其序列化结果作为代码的特征, 这个特征被编码为Transformer[23]的输入序列, 在代码摘要任务中表现良好. 后来, MMAN[14]为进一步充分挖掘结构信息, 将结构级的AST, CFG和语义级的代码字符结合. DeGraphCS[15]提出在编译后, 构造一个基于变量的流图, 以进一步提高代码语义表示的准确性, 并提出一种优化算法来去除变量流图中的冗余信息.
1.3 对比学习传统的监督学习方法很大程度上依赖于大量的标注数据, 而标注数据往往需要领域的专家, 代价昂贵. 因此, 近年来, 无需外部监督信息的自监督学习方受到了研究者们的极大关注. 对比学习就是一种有效的自监督学习方法, 它通过最小化相似样本的语义向量的空间距离, 同时最大化不同样本之间的距离, 目的是帮助相近样本彼此更接近而不同样本彼此远离[39]. 它可以使模型学到样本的重要且具有区分度的内在隐藏特征, 进而将其应用于下游任务, 在计算机视觉和自然语言处理等领域得到了广泛研究, 如SimCSE[40]是一个基于对比学习的方法来表示句子的通用嵌入的框架. 近年来, 有研究将对比学习应用到各种软件工程任务中, 例如: Coder[41]是一种用于代码-代码检索、文本-代码检索和代码-文本摘要生成的对比学习方法; VarCLR[42]是基于不同的下游任务的对比学习模型, 旨在学习变量名称的语义表示. 最近, cpt-code[43]也证实了对比学习预训练可以得到代码更加丰富的语义表征. 在代码智能领域中, 设计源代码的数据增强方法成为应用对比学习的关键. ContraCode[44]通过源代码编译器在JavaScript上生成变体, 并进一步组合这些生成的变体作为数据增强的一种方法. MuCoS[45]应用一个名叫JavaTransformer[46]的工具包, 里面包含9种对Java源代码进行数据增强的方法.
2 REcomp本节将介绍REcomp, 如图 2所示.
|
图 2 基于多模态对比学习的代码表征增强模型的框架图 |
REcomp是一种基于多模态对比学习的代码表征增强的编程语言预训练模型, 是基于Transformer[23]的, 能够以多种编程语言预训练模型(如CodeBERT[29], GraphCodeBERT[30]和UniXcoder[32])为初始化标准. 下面将依次介绍多模态特征提取、REcomp的编码器、多模态对比学习的预训练任务(包含数据增强)和下游任务.
2.1 多模态特征提取如图 2(a)多模态特征提取模块所示, 需要提取源代码4个层次的特征, 分别是文本级的代码注释、语义级-结构级的融合特征序列和功能级的函数名. 下面将详细阐述需要提取源代码多个模态特征的原因以及获取语义级-结构级融合的方法(见算法1).
图 3给出了一个带有注释和AST的Python代码示例. 注释“Return the sum of two numbers”高度概括了源代码的功能, 提供了关键的语义信息. 函数名称“sum”简明扼要的描述了源代码主体函数的功能, 也是表征源代码语义信息的另一重要而不可忽视的特征. 此外, 解析源代码后得到的AST包含丰富的句法相关的结构信息, 例如: 非叶结点(控制结点)“return_statement”控制了其叶结点“return”和“result”整体行为; 非叶结点“parameters”指出来了“(x, y)”的类型是“参数”. 这里的“x”和“y”的结构是等价的. 这也是编程语言区别于自然语言的特殊的点: 编程语言中字符的语义和结构信息共同决定了它的表征, 存在同一字符表示不同语义和不同字符表示相同语义的现象. 因此, 不仅要关注语义级代码字符的信息, 也要关注隐藏的结构信息, 才能更加准确地表示源代码.
|
图 3 一个Python的AST与代码字符的融合序列示例 |
算法 1 描述了代码的语义级-结构级特征的融合的过程. 算法的输入是编程语言的类型Language∈{php, java, python, ruby, go, javascript}, 以及程序Code
算法 1 的核心是_SemanticsStructureFusion 函数(第7−17行), 它将 t(Nnonleaf)与 c(Nleaf)依次添加到集合TokensAST, 即ca(见公式(1))中. 整个算法自顶向下的遍历AST, 融合了代码的语义信息和结构信息.
算法1. 语义级-结构级特征融合(SemanticsStructureFusion).
输入: 编程语言Language, 源代码Code;
输出: 所有语义级和结构级特征的集合TokensAST.
1. Function SemanticsStructureFusion(Langauge, Code)
2. TokensAST
3. get the AST parser of Code depending on different Language
4. parse the Code to AST then get the root of the AST
5. _SemanticsStructureFusion(Code, the root of the AST parsed by Code)
6. Return TokensAST
7. Function _SemanticsStructureFusion(Code, root)
8. TokensAST
9. If root.Children=
10. For child in root.children
11. If child.type=“identifier” and child.children≠
12. tokens←AlignNodeToTokens(child is one leaf node Nleaf of the AST, Code)
13. add the tokens to the TokensAST
14. Else
15. ast←child.type and add the ast to the TokensAST
16. _SemanticsStructureFusion(Code, child)
17. Return TokensAST
18. Function AlignNodeToTokens(Nleaf, Code)
19. start←Nleaf.start_node, end←Nleaf.end_node
20. tokens←
21. If start[0]=end[0] then tokens←Code[start[0]][start[1]: end[1]]
22. Else
23. tokens←Code[start[0]][start[1]: ]
24. For i in [start[0]+1, …, end[0]]
25. concatenate Code[i] to tokens
26. concatenate Code[end[0]][: end[1]] to tokens
27. Return tokens
注意: AlignNodeToTokens函数(第18−27行)中, 根据Nleaf的start_node和end_node属性值, 在源代码中有唯一确定的tokens⊂S与Nleaf对齐. 并且start_node是一个元组, 表示为(行号, 序号). 例如图 3所示: 源代码中的字符“sum”位于第1行, 包含第5个字符到第7个字符, 因此它的start_node值为(0, 4); 同理, 它的end_point的值为(0, 6).
Code S的函数名和自然语言注释形式化为f和n, 其中, J和L是f和n应用RoBERTa[25]分词器划分的长度:
| $ ca = ({t_1},{t_2},...,{c_1},...,{t_{|{N_{nonleaf}}|}},...,{c_{|{N_{leaf}}|}}),{\text{ }}{t_j} = t(N_{nonleaf}^j),{\text{ }}{c_i} = (N_{leaf}^i) $ | (1) |
| $ f=(f_{1},f_{2},…,f_{j},…,f_{J}), 1≤j≤J, n=(n_{1},n_{2},…,n_{l}…,n_{L}), 1≤l≤L $ | (2) |
将公式(1)的ca和公式(2)的f进行拼接, 且使用特殊符号[CLS]表示是一个位于段序列最前端的特殊开始字符, [SEP]是分隔不同模态数据的特殊字符, 源代码的输入code表示如下:
| $ code=([CLS]⊕f⊕[SEP]⊕ca⊕[SEP])$ | (3) |
REcomp分别以CodeBERT, GraphCodeBERT和UniXcoder为初始化模型[3], 其编码向量函数表示为Embedding(⋅), 结合多模态输入code, 如公式(3)所示, 其中间表示ecode表示在公式(4):
| $ e_{code}=Embedding(code)$ | (4) |
如图 2(b)编码器模块所示: REcomp由N(N=12)层Transformer[23]组成, 由中间形式e作为模型输入生成每一层的隐藏状态HN, 每一层Transformer都含有一个架构相同的转换器, 该转换器使用多头注意力机制(multi-headedself-attention), 通过一个前馈神经网络(FeedForwardLayer)覆盖上一层的输出, 初始化时H0=ecode, 对于第I层的Transformer, 多头注意力机制的输出通过如下方式计算:
| $ {H^N} = \{ h_0^N,h_1^N,...,h_{n - 1}^N\} ,{\text{ }}{E^n} = LN(MultiAtt({H^{n - 1}}) + {H^{n - 1}}),{\text{ }}{H^n} = LN(FFN({E^n}) + {E^n}) $ | (5) |
其中, MultiAtt是多头注意力机制, FFN是前馈神经网络, LN是正则化操作, 最终的输出EN由下列公式得到:
| $ \begin{gathered} {Q_i} = {H^{l - 1}}W_i^Q,{\text{ }}{K_i} = {H^{l - 1}}W_i^K,{\text{ }}{V_i} = {H^{l - 1}}W_i^V,{\text{ }}hea{d_i} = softmax\left( {\frac{{{Q_i}K_i^T}}{{\sqrt {{d_k}} }}} \right){V_i} \hfill \\ {E^N} = [hea{d_1};...;hea{d_N}]W_N^O \hfill \\ \end{gathered} $ | (6) |
其中, 前一层的输出
对比学习鼓励原始样本的表示更加接近“正”增强样本的表示, 同时远离“负”样本的表示, 使得模型在不同数据之间能学习到更加均匀的决策边界点. 最近的几项工作[42, 45]试图比较相似和不同的源代码, 然而它们只比较了单个模态的特征, 却忽略了编程语言的多模态特性. 为此, 本文设计了多模态对比学习的预训练目标来探索不同模态之间交互信息的最大潜力, 鼓励模型学习编程语言不同模态的联系和语义等价性. 对比学习的关键是构造正负样本, 因此, 本文提出了两种新的数据增强的方法, 分别称作NL型和PL型, 如图 2(b)数据增强模块所示.
对于正样本的设计, 本文针对CodeSearchNet[33]中双模态(PL-NL)数据进行构造.
(1) NL型: 为了弥合编程语言与自然语言的语义鸿沟, 本文将文本级的自然语言注释单独视为一个正样本, 将它表示为code*, 如公式(7)所示:
| $ code^{*}=([CLS]⊕comment⊕[SEP])$ | (7) |
(2) PL型: 因为功能级的函数名、语义级的代码字符和结构级的AST都具有编程语言的特点, 所以为了学习这3个特征的语义等价性, REcomp交换功能级的函数名f和语义级-结构级特征的融合序列ca在输入序列中的位置, 将此作为一种数据增强的方法, 得到的另一个正样本, 将它表示为code+, 如公式(8)所示:
| $ code^{+}=([CLS]⊕ca⊕[SEP]⊕f⊕[SEP])$ | (8) |
为了让模型最大程度地学习编程语言4个模态特征的语义等价性, 本文将原始样本、PL型正样本和NL型正样本两两组合, 得到(code, code*), (code*, code+)和(code+, code)这3个组合.
对于负样本的设计, 采用的损失函数是交叉熵损失函数. 对于原始样本xi, 将原始样本batch里其余xj(j≠i)作为负样本, 简称为In-batch, 并且将正样本batch里不同对
| $ l({x_i},x_i^ + ) = - \ln \frac{{\exp ({v_i},v_i^ + )}}{{\exp ({v_i},v_i^ + ) + \sum\nolimits_1^{2N - 2} {\exp ({v_i},v_i^ - )} }} $ | (9) |
其中, vi是xi对应的语义向量, 由公式(7)得到;
| $ Los{s_{MCL}} = \sum\nolimits_1^N {[l({x_i},x_i^ + ) + l({x_i},x_i^*) + l(x_i^*,x_i^ + )]} $ | (10) |
其中, xi是原始样本,
本文将经过多模态对比学习预训练后的编码器形式化为Encoder. 为探究模型是否增强了代码表征的能力, 本文选取了两个典型的理解型下游任务(代码克隆检测和语义代码检索)对模型的有效性进行评估.
2.4.1 代码克隆检测代码克隆检测是一个通过测量两个源代码之间的相似性来识别代码克隆问题是否存在的任务, 这个问题形式化定义为: 给定一个源代码c1和一个待检测的代码c2, 根据c1和c2的相似性分数, 返回0/1标签, 标签0表示c2不是c1的克隆体, 标签1则表示c2是c1的克隆体. 本文选择余弦相似性(记作cosSim)作为相似性分数的计算函数, 来对它们进行相似度分数计算, 计算表示如公式(11):
| $ {e_{{c_1}}} = Encoder({c_1}),{\text{ }}{e_{{c_2}}} = Encoder({c_2}),{\text{ }}score = cosSim({e_{{c_1}}},{e_{{c_2}}}) $ | (11) |
语义代码检索是一个根据用户的查询意图, 从代码语料库中匹配最具相关性的源代码的任务. 这个问题形式化定义为: 给定一个自然语言形式的查询语句n, 与代码语料库UC={c1, c2, c3, …, ci, …, cI}中的代码ci∈UC进行相似度分数计算(I表示UC中代码的总数量), 并且从UC中返回具有最高分数的源代码
| $ {e_{{c_i}}} = Encoder({c_i}),{\text{ }}{e_n} = Encoder(n),{\text{ }}{\hat c_\tau } = \mathop {\arg \max }\limits_{{c_i}} cosSim({e_{{c_i}}},{e_n}) $ | (12) |
REcomp使用的是一个代码智能领域的公开基准数据集CodeXGLUE[2]. 本文选取代码克隆检测任务的两个数据集——BigCloneBench[34]和POJ-104[35]以及代码检索任务的CodeSearchNet[33]数据集.
BigCloneBench是一种广泛被使用的大型代码克隆基准, 包含约6 000 000真的克隆对和260 000个假的克隆对, 这些克隆对来自10个不同功能的克隆对语料库. 它们[34]通过对没有任何标记的真假克隆对的源代码进行过滤, 最后将数据集划分成901 208 / 415 415 / 415 416个示例, 分别用于训练、验证和测试;
POJ-104数据集来自一个教学的开放编程平台, 它包含104个问题, 每个问题包含500个学生编写的C/C++程序. 它被划分成32 000 / 8 000 / 12 000条数据, 分别用于训练、验证和测试;
CodeSearchNet中每个示例都包含一个与文档配对的函数, 它们[33]选取文档的第1段作为代码功能描述的注释, 通过删除满足一定条件的示例来对其进行数据过滤, 进而提高数据集的质量. 上述数据过滤的条件分别是: 去除源代码存在编译错误且无法解析成为抽象语法树的示例; 去除源代码的文档(即自然语言注释)字符数量小于3或者大于256的示例; 去除源代码的文档中含有特殊表示和一些与功能无关的内容, 如指向外部资源的链接或者HTML标签等示例; 去除源代码的文档里含有非英文字符的示例. 过滤后的CodeSearchNet数据集统计信息见表 2.
| 表 2 代码检索任务中CodeSearchNet的数据统计 |
为了公平比较, 本文同样在CodeSearchNet[33]数据集上预训练REcomp. REcomp(C/G/U)表示分别以CodeBERT, GraphCodeBERT, UniXcoder初始化的REcomp, 他们的训练集大小分别为48/60/64, 学习率为1e−5, 优化器采用AdmW, 原始样本和PL型正样本输入大小为300, NL型正样本的输入大小为64. 然后, 用1个NVIDIA Tesla A100(大小为40 GB)分别训练28k, 22k和21k训练步.
3.3 评价指标 3.3.1 代码克隆检测代码克隆检测的评价指标有平均精度(mean average precision, MAP@R)、召回率(recall)、准确率(precision)、F1-值(F1-score). MAP@R用于评价给定查询在集合中检索出的R个最相似样本的结果, 其中, R设置为499, 其计算方式如公式(13):
| $ {\text{MAP@R}} = \frac{{\sum\nolimits_{q = 1}^Q {AvgPrecision(q)} }}{Q} $ | (13) |
其中, Q是数据集大小. 余下评估指标的计算方法如式(14):
| $ Precision = \frac{{tp}}{{tp + fp}},{\text{ }}Recall = \frac{{tp}}{{tp + fn}},{\text{ }}F1 = \frac{{2*(Precision*Recall)}}{{Precision + Recall}} $ | (14) |
语义代码检索任务的评价指标[47]有: 最佳命中率(FRank)和平均排序倒数(mean reciprocal rank, MRR). FRank是指第1个命中结果在结果列表中的排名, 是计算MRR的基础. MRR是利用查询接收到的结果集中在第1个正确答案的位置来评估模型的性能, 如果正确答案越靠前, 则表示模型效果越好:
| $ MRR = \frac{1}{{|Q|}}\sum\nolimits_{q = 1}^Q {\sigma (FRan{k_q} \leqslant k)} $ | (15) |
其中, Q是查询语句的集合. δ(⋅)是特征函数, 满足(⋅)时, δ(⋅)=1; 否则, δ(⋅)=0.
3.4 实验结果分析本节分为以下6个小节: 第3.4.1节分析REcomp的整体性能; 第3.4.2节验证REcomp中单个组件的有效性; 第3.4.3节对比REcomp与基准模型[29−32]的预训练资源使用情况; 第3.4.4节验证优化的AST序列化算法的有效性; 第3.4.5节阐述批量大小与模型性能的关系; 第3.4.6节进行案例分析, 通过对部分案例的语义向量可视化, 来验证REcomp的有效性.
3.4.1 主要实验结果主要实验旨在测试基于多模态对比学习的代码表征增强模型的整体效果, 验证多模态对比学习预训练目标的有效性. 本文将在两个代码理解型的下游任务(代码克隆检测和语义代码检索)上比较REcomp和10个基准方法的实验结果. 这10个基准方法分为两类: 第一类是从头到尾都是在评估任务上进行训练; 第二类是模型先在未标记的语料库进行预训练, 然后在评估任务上进行评估. 这10个基准方法分别是TextCNN[12], BiLSTM[48], Transformer[23], RoBERTa[25], RoBERTa(code), PLBART[28], CodeBERT[29], GraphCodeBERT[30], SynCoBERT[31], UniXcoder[32]. 为了公平起见, 在下游任务评估时, 与UniXcoder保持一致, 本文只用语义级特征代码字符来表征源代码. 除学习率外, REcomp在下游任务上微调的参数分别与其初始化模型保持一致. REcomp在CodeSearchNet[33], BigCloneBench[34]和POJ-104[35]数据集上的学习率分别为8e−06, 2e−5, 1e−5.
就代码克隆检测而言, 其结果见表 3: 在POJ-104数据集上, REcomp(C/G/U)分别比初始化模型CodeBERT, GraphCodeBERT和UniXcoder提升了约7.2%, 3.5%和1.4%的MAP@R. REcomp(C)不仅超过了GraphCodeBERT约4.7%, 还超过了REcomp(G), 表明CodeBERT在代码理解任务上的提升空间很大. 在BigCloneBench数据集上, REcomp(C)相比于CodeBERT提升了约0.6%的准确率; 在召回率上, REcomp(U)超过了UniXCoder近2.1%.
| 表 3 代码克隆检测任务的评价结果(%) |
就语义代码检索任务而言, 其实验结果见表 4, REcomp(C/G/U)分别比初始化模型CodeBERT, GraphCodeBERT和UniXcoder提升了平均MRR约2.2%, 2.7%和0.7%. 在Ruby上, 模型表现显著, 最高提升了5%的准确率. 在JavaScript和Go上, REcomp(C)的性能超过了GrapCodeBERT. REcomp在不同语言的数据集上性能提升各有不同, 是因为不同编程语言的自身特点区别鲜明. 例如, REcomp(U)在Ruby数据集上的MRR增加了2.4%, 而Java数据集的MRR只增加了0.2%. 造成这种现象的可能原因是, 它们的语法和表达性不同: Ruby语言的语法简洁, 它注重代码的可读性和易于理解, 尽量使用更少的语法结构和标点符号, 使得代码看起来更接近自然语言, 因此, REcomp极大地拉近了它与自然语言的语义鸿沟; 相比之下, Java语言的语法更为严格, 需要使用更多的关键字和符号来定义代码结构, 因此在拉近代码和查询之间的语义距离还需要更多的结构信息. 根据Go和Python数据集进一步验证上述猜想, 它们的MRR分别增加了0.4%和0.6%, 并且Go和Python都注重代码的简洁性和可读性, 相比Java其结构更加简单. 它们都采用了清晰简洁的语法和规范, 使得代码更易于编写、理解和维护, 因此它们MRR的提升都高于语法结构更加复杂的Java.
| 表 4 6种编程语言的代码检索任务的评价结果(%) |
综上所述, REcomp提高了代码表征的准确性, 从而增强了模型在代码理解型任务上的性能. 这有助于减少代码调试和优化的需求, 提高了代码的运行效率, 促进了代码的重用和模块化开发. 这样有益于节约能源、减少计算机软硬件资源的使用, 并减少对相关电力和碳排放的依赖.
3.4.2 消融实验本小节将验证3个问题.
(1) PL型正样本能否让模型学习到具有编程语言特点的特征的语义等价性?
(2) NL型正样本能否弥合自然语言和编程语言的语义鸿沟?
(3) PL与NL的组合型是否增强了模型代码表征的能力?
本文用-w/o定义了“删除”操作符, 用来检测单个组件的有效性, 则有:
● -w/o PL: 表示删除PL型正样本, 进行多模态对比学习预训练任务时只使用NL型正样本;
● -w/o NL: 表示删除NL型正样本, 进行多模态对比学习预训练任务时只使用PL型正样本;
● -w/o MCL: 表示没有经过多模态对比学习预训练任务, 直接用初始化模型对下游任务进行评估.
(1) NL型的有效性
就克隆检测任务而言, 从表 5观察到: REcomp(C/G/U)去掉NL型, 比NL+PL型下降了约0.14%, 0.4%和0.9%, 高出基准方法约7.1%, 3.1%和0.54%. 在语义代码检索任务上, 仅用NL型作为正样本预训练, 即REcomp(C/G/U, -w/o PL), 在MRR上高出其基准分别约2.1%, 2.6%和0.9. REcomp(C/G, -w/o NL)相比REcomp(C/G)下降了1.8%, 1.4%和0.7%, 可以得出, REcomp(C/G/U)是NL型敏感的, 即它们的性能会受到具有自然语言特点的代码特征的影响. 此外还可以发现, REcomp(U)是强NL型敏感的, 因为REcomp(U, NL)在MRR上比REcomp(U)高了0.2%.
| 表 5 语义代码检索任务上的消融实验的结果(%) |
(2) PL型的有效性
在代码克隆检测任务上, 以POJ-104数据集为例, 其结果见表 5, 仅使用PL型进行预训练, 即REcomp (C/G, -w/o NL), 在MAP@R上分别高出基准模型CodeBERT, GraphCodeBERT和UniXcoder约7.1%, 3.1%和0.54%. 并且去掉PL型后, REcomp(C/G)的准确率有所下降. 因此可以得出, CodeBERT和GraphCodeBERT是PL型敏感的, 即它们会受到具有编程语言特点的代码特征的影响.
在语义代码检索任务上, REcomp去掉NL型正样本的结果如表 6所示, 即REcomp只使用PL型正样本进行预训练REcomp(C/G/, -w/o NL), 其性能仍然高出基准的CodeBERT和GraphCodeBERT约0.4%和1.3%. 从NL型与PL+NL组合型的结果比较的角度来验证, 去掉PL型组件后, REcomp(C/G)总体性能下降了约0.1%.
| 表 6 代码克隆检测(POJ-104)消融实验的MAP@R(%)结果 |
(3) PL与NL组合型的有效性
PL与NL组合型的有效性就是本文第3.4.1节主要实验的内容, 在第3.4.1节中, 已经证实了多模态对比学习模块(PL与NL组合型)的有效性.
总结: 模型对PL型的敏感程度不及NL型, NL型起到了主要作用, 特别是在REcomp(C/U)中, 去掉PL型后, 模型在Ruby, JavaScript, Go和Java上进一步提升了, 但在Python和PHP上, 仍是PL+NL强于NL. 总体来说, 增加PL型的REcomp的性能都是优于其初始化模型的. 因为初始化模型、编程语言和数据集的不同, REcomp对NL型和PL型正样本的敏感程度不一样, 所以存在少数PL型或者NL型优于PL与NL组合型的现象.
3.4.3 预训练资源对比实验本文罗列了基准方法中预训练模型在预训练阶段的计算资源的使用详情, 见表 7. 从表 7中可以看出, REcomp仅使用极少的计算资源和小批量训练集就在较短的时间迅速收敛. 因此可以看出, 多模态对比学习是一种环保、低碳的学习方法, 它通过共享学习和特征融合等方式来减少模型推理和训练的过程, 进而降低能源消耗和环境压力, 为可持续发展提供了一种新的解决方案.
| 表 7 各模型预训练使用的资源统计 |
语义级-结构级融合算法旨在验证REcomp优化的序列化AST方法能否有效缩短模型特征序列的长度. 因为在基准方法的预训练模型里, 只有SynCoBERT和UniXcoder用AST作为代码表征的一部分, 所以本文将SynCoBERT, UniXcoder和REcomp对CodeSearchNet[33]中6种编程语言的训练集的AST序列化后的平均长度进行统计, 其结果如图 4所示. 它们分别是244, 530和139. 由此得出: REcomp相比于UniXcoder和SynCoBERT, 其AST的序列化结果缩短约381%和176%. 因此, REcomp中优化的序列化AST方法, 极大程度地减少了代码的冗余特征, 并且缩短了模型的特征序列的长度, 进而减少了数据存储和传输中的能量消耗, 最终节省了计算资源.
|
图 4 模型在AST序列长度上的对比 |
REcomp作为预训练模型, 其性能受到参数的影响. 因此, 本小节就实验中重要的几个参数之一的训练批量大小进行讨论. 本文选择语义代码检索任务里的随机一种编程语言, 本次实验的随机结果是Ruby语言, 以此进行实验, 其余参数与微调时相同, 训练轮数设置为2, 实验结果如图 5所示. 从图 5中可以看出, batch size越大, 检索任务的准确性越高. 因此, batch size对检索结果起正向作用. 但是batch size过大, 会导致训练时占用显卡资源过多; 而且, 当batch size达到某个阈值时, 模型在性能上的增长趋于平缓, 但资源上的消耗却更大了. 因此, 考虑到这一点, 本文将batch size设置为64.
|
图 5 批量大小与准确性的相关性 |
DeepCS[37]提出: 在向量空间中, 两个向量语义越接近, 其距离越小. 基于这个前提, 本文从CodeSearchNet[33]中随机选取7个功能不同的源代码, 作为7个类别. 如图 6示: 用7种不同颜色表示7个类别, 相同颜色的不同符号具有语义等价性, 圆形、菱形和三角形分别表示原始样本、PL型正样本和NL型正样本. 在图 6(a)中, 向量空间的所有点是通过初始化模型UniXcoder[32]编码得到的, 相同颜色不同符号的点彼此距离较远, 如红色虚线区域的紫色向量. 图 6(b)中, REcomp(U)表征的语义向量, 呈现出相同颜色不同符号的点相互聚拢的趋势, 如红色虚线覆盖区域所示. 因为PL型跟原始样本都是编程语言, 而NL型是自然语言, 所以圆形点与菱形点的距离比其与三角形点的距离更为接近.
|
图 6 不同表征方法下的语义向量类别的可视化 |
根据上述现象得出结论: 经过多模态对比学习预训练任务后, 模型有效地学习到了编程语言4个不同抽象层次的特征的语义等价性. 相比NL型(文本级的自然语言注释), 具有编程语言特点的PL型与原始样本的空间距离更为接近, 侧面验证了编程语言与自然语言之间存在语义鸿沟.
3.5 实验环境研究中涉及的所有实验均基于PyTorch框架实现, 通过使用tree-sitter (https://github.com/tree-sitter/tree-sitter)、apex库(https://github.com/NVIDIA/apex)以及Transformer (https://github.com/huggingface/transformers)来实现REcomp. 表 8给出了微调时, 代码克隆检测和语义代码搜索的超参数和具体的取值, 这些取值基于已有文献的推荐取值和我们实证研究中的实际性能. 在代码克隆检测任务中输入1是源代码, 输入2是待检测代码; 在语义代码检索任务中, 输入1是代码, 输入2是自然语言. 优化器采用AdmW, 并且采用了FP16混合精度来加速训练. 此外, 我们根据基准方法的描述重现了这些方法, 并且这些方法的执行结果与原始文献中的结果接近. 实验运行的计算机的配置信息是: Inter i5-8265U CPU、32 GB内存的Tesla V100-SXM2、Linux操作系统.
| 表 8 REcomp涉及的超参数和对应取值 |
大规模编程语言模型的发展, 给代码智能领域带来了机遇和挑战. 本文提出了基于多模态对比学习的预训练方法(REcomp), 旨在增强模型代码表征的能力, 并且在公开基准数据集CodeXGLUE[2]上验证了其在下游任务——代码克隆检测和语义代码检索上的有效性. REcomp利用对比学习对融合了源代码所有抽象层次特征(包括文本级代码注释、语义级代码字符、功能级函数名和结构级的AST)的语义向量建模, 充分挖掘了各个模态特征的隐藏信息, 提高了代码表征的准确性. 除此之外, REcomp优化了序列化AST的方法, 在保留完整的非叶结点的控制信息和叶子结点的语义信息的同时, 避免了结点冗余和序列过长等问题, 极大程度缩短了输入的特征序列. 更短的特征序列促使模型仅使用极少的计算资源和小批量训练集, 就在较短的时间迅速收敛, 并在公开数据集上达到了不错的效果.
| [1] |
Rey SJ. Big code. Geographical Analysis, 2023, 55(2): 211-224.
[doi:10.1111/gean.12330] |
| [2] |
Lu S, Guo D, Ren S, et al. CodeXGLUE: A machine learning benchmark dataset for code understanding and generation. arXiv: 2102. 04664, 2021.
|
| [3] |
Cheng SQ, Liu JX, Peng ZL, et al. CodeBERT based code classification method. Computer Engineering and Applications, 2023, 59(24): 277-288(in Chinese with English abstract).
[doi:10.3778/j.issn.1002-8331.2209-0402] |
| [4] |
Jiang Y, Li M, Zhou ZH. Software defect detection with Rocus. Journal of Computer Science and Technology, 2011, 26(2): 328-342.
[doi:10.1007/s11390-011-1135-6] |
| [5] |
Jiang L, Misherghi G, Su Z, et al. Deckard: Scalable and accurate tree-based detection of code clones. In: Proc. of the 29th Int'l Conf. on Software Engineering (ICSE 2007). IEEE, 2007. 96−105.
|
| [6] |
Russell R, Kim L, Hamilton L, et al. Automated vulnerability detection in source code using deep representation learning. In: Proc. of the 17th IEEE Int'l Conf. on Machine Learning and Applications (ICMLA). IEEE, 2018. 757−762.
|
| [7] |
Zhou ZH, Chen SF. Neural network ensemble. Chinese Journal of Computer, 2002, 25(1): 1-8(in Chinese with English abstract).
https://www.cnki.com.cn/Article/CJFDTOTAL-JSJF202101009.htm |
| [8] |
Hindle A, Barr ET, Gabel M, et al. On the naturalness of software. Communications of the ACM, 2016, 59(5): 122-131.
[doi:10.1145/2902362] |
| [9] |
Nachmani E, Marciano E, Burshtein D, et al. RNN decoding of linear block codes. arXiv: 1702.07560, 2017.
|
| [10] |
Mou L, Li G, Jin Z, et al. TBCNN: A tree-based convolutional neural network for programming language processing. arXiv: 1409. 5718, 2014.
|
| [11] |
Shuai J, Xu L, Liu C, et al. Improving code search with co-attentive representation learning. In: Proc. of the 28th Int'l Conf. on Program Comprehension. 2020. 196−207.
|
| [12] |
Kim Y. Convolutional neural network for sentence classification [MS. Thesis]. University of Waterloo. arXiv: 1408.5882v2, 2014.
|
| [13] |
Li Z, Wu Y, Peng B, et al. SeCNN: A semantic CNN parser for code comment generation. Journal of Systems and Software, 2021, 181: 111036.
[doi:10.1016/j.jss.2021.111036] |
| [14] |
Wan Y, Shu JD, Sui YL, et al. Multi-modal attention network learning for semantic source code retrieval. In: Proc. of the 2019 34th IEEE/ACM Int'l Conf. on Automated Software Engineering (ASE). IEEE, 2019. 13−25.
|
| [15] |
Zeng C, Yu Y, Li S, et al. DeGraphCS: Embedding variable-based flow graph for neural code search. ACM Trans. on Software Engineering and Methodology, 2023, 32(2): 1-27.
|
| [16] |
Xie CL, Liang Y, Wang X. Survey of deep learning applied in code representation. Computer Engineering and Applications, 2021, 57(20): 53-63(in Chinese with English abstract).
[doi:10.3778/j.issn.1002-8331.2106-0368] |
| [17] |
Hu X, Li G, Xia X, et al. Deep code comment generation. In: Proc. of the 26th Conf. on Program Comprehension. 2018. 200−210.
|
| [18] |
Wen W, Chu J, Zhao T, et al. Code2tree: A method for automatically generating code comments. Hindawi Scientific Programming, 2022. https://doi.org/10.1155/2022/6350686
|
| [19] |
Wei H, Li M. Supervised deep features for software functional clone detection by exploiting lexical and syntactical information in source code. In: Proc. of the IJCAI. 2017. 3034−3040.
|
| [20] |
Graves A. Supervised Sequence Labelling with Recurrent Neural Networks. Springer, 2012. 37−45.
|
| [21] |
Alon U, Zilberstein M, Levy O, et al. Code2vec: Learning distributed representations of code. Proc. of the ACM on Programming Languages, 2019, 3(POPL): 1-29.
|
| [22] |
Gu J, Chen Z, Monperrus M. Multimodal representation for neural code search. In: Proc. of the 2021 IEEE Int'l Conf. on Software Maintenance and Evolution (ICSME). IEEE, 2021. 483−494.
|
| [23] |
Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need. In: Proc. of the Advances in Neural Information Processing Systems. 2017. 30
|
| [24] |
Devlin J, Chang MW, Lee K, et al. BERT: Pre-training of deep bidirectional transformers for language understanding. arXiv: 1810. 04805, 2018.
|
| [25] |
Liu Y, Ott M, Goyal N, et al. RoBERTa: A robustly optimized BERT pretraining approach. arXiv: 1907.11692, 2019.
|
| [26] |
Radford A, Narasimhan K, Salimans T, et al. Improving language understanding by generative pre-training. OpenAI, 2018.
|
| [27] |
Lewis M, Liu Y, Goyal N, et al. BART: Denoising sequence-to-sequence pre-training for natural language generation, translation, and comprehension. arXiv: 1910.13461, 2019.
|
| [28] |
Ahmad WU, Chakraborty S, Ray B, et al. Unified pre-training for program understanding and generation. arXiv: 2103.06333, 2021.
|
| [29] |
Feng Z, Guo D, Tang D, et al. CodeBERT: A pre-trained model for programming and natural languages. arXiv: 2002.08155, 2020.
|
| [30] |
Guo D, Ren S, Lu S, et al. GraphCodeBERT: Pre-training code representations with data flow. arXiv: 2009.08366, 2020.
|
| [31] |
Wang X, Wang Y, Mi F, et al. SynCoBERT: Syntax-guided multi-modal contrastive pretraining for code representation. arXiv: 2108.04556, 2021.
|
| [32] |
Guo D, Lu S, Duan N, et al. UniXcoder: Unified cross-modal pre-training for code representation. arXiv: 2203. 03850, 2022.
|
| [33] |
Husain H, Wu HH, Gazit T, et al. CodeSearchNet challenge: Evaluating the state of semantic code search. arXiv: 1909.09436, 2019.
|
| [34] |
Svajlenko J, Islam JF, Keivanloo I, et al. Towards a big data curated benchmark of inter-project code clones. In: Proc. of the 2014 IEEE Int'l Conf. on Software Maintenance and Evolution. IEEE, 2014. 476−480.
|
| [35] |
Mou L, Li G, Zhang L, et al. Convolutional neural networks over tree structures for programming language processing. In: Proc. of the 30th AAAI Conf. on Artificial Intelligence (AAAI-16). 2016.
|
| [36] |
Lü TG, Hong RC, He J, et al. Multimodal-guided local feature selection for few-shot learning. Ruan Jian Xue Bao/Journal of Software, 2023, 34(5): 2068−2082 (in Chinese with English abstract). http://www.jos.org.cn/1000-9825/6771.htm[doi: 10.13328/j.cnki.jos.006771]
|
| [37] |
Gu X, Zhang H, Kim S. Deep code search. In: Proc. of the 40th Int'l Conf. on Software Engineering. 2018.
|
| [38] |
Yang G, Chen X, Cao J, et al. Comformer: Code comment generation via transformer and fusion method-based hybrid code representation. In: Proc. of the 8th Int'l Conf. on Dependable Systems and Their Applications (DSA). 2021.
|
| [39] |
Liu B, Li RL, Feng JF. A brief introduction to deep metric learning. CAAI Trans. on in Telligent Systems, 2019, 14(6): 1064-1072(in Chinese with English abstract).
https://www.cnki.com.cn/Article/CJFDTOTAL-ZNXT201906001.htm |
| [40] |
Gao T, Yao X, Chen D. SimCSE: Simple contrastive learning of sentence embeddings. arXiv: 2104.08821, 2021.
|
| [41] |
Bui ND, Yu Y, Jiang L. Self-supervised contrastive learning for code retrieval and summarization via semantic-preserving transformations. In: Proc. of the 44th Int'l ACM SIGIR Conf. on Research and Development in Information Retrieval. 2021. 511−521.
|
| [42] |
Chen Q, Lacomis J, Schwartz EJ, et al. VarCLR: Variable semantic representation pre-training via contrastive learning. In: Proc. of the 44th Int'l Conf. on Software Engineering. 2022. 2327−2339.
|
| [43] |
Neelakantan A, Xu T, Puri R, et al. Text and code embeddings by contrastive pre-training. arXiv: 2201.10005, 2022.
|
| [44] |
Jain P, Jain A, Zhang T, et al. Contrastive code representation learning. arXiv: 2007.04973, 2020.
|
| [45] |
Du L, Shi X, Wang Y, et al. Is a single model enough? MuCoS: A multi-model ensemble learning for semantic code search. arXiv: 2107.04773, 2021.
|
| [46] |
Rabin MR, Bui ND, Wang K, et al. On the generalizability of neural program models with respect to semantic-preserving program transformations. Information and Software Technology, 2021, 135: 106552.
[doi:10.1016/j.infsof.2021.106552] |
| [47] |
Wei M, Zhang LP. Research progress of code search methods. Application Research of Computers, 2021, 38(11): 3215-3221, 3230(in Chinese with English abstract).
[doi:10.19734/j.issn.1001-3695.2021.04.0096] |
| [48] |
Cho K, Van Merriënboer B, Bahdanau D, et al. On the properties of neural machine translation: Encoder-decoder approaches. arXiv: 1409.1259, 2014.
|
| [3] |
成思强, 刘建勋, 彭珍连, 等. 以CodeBERT为基础的代码分类研究. 计算机工程与应用, 2023, 59(24): 277-288.
[doi:10.3778/j.issn.1002-8331.2209-0402] |
| [7] |
周志华, 陈世福. 神经网络集成. 计算机学报, 2002, 25(1): 1-8.
https://www.cnki.com.cn/Article/CJFDTOTAL-JSJF202101009.htm |
| [16] |
王霞, 梁瑶, 谢春丽. 深度学习在代码表征中的应用综述. 计算机工程与应用, 2021, 57(20): 53-63.
[doi:10.3778/j.issn.1002-8331.2106-0368] |
| [36] |
吕天根, 洪日昌, 何军, 等. 多模态引导的局部特征选择小样本学习方法. 软件学报, 2023, 34(5): 2068−2082. http://www.jos.org.cn/1000-9825/6771.htm[doi: 10.13328/j.cnki.jos.006771].
|
| [39] |
刘冰, 李瑞麟, 封举富. 深度度量学习综述. 智能系统学报, 2019, 14(6): 1064-1072.
https://www.cnki.com.cn/Article/CJFDTOTAL-ZNXT201906001.htm |
| [47] |
魏敏, 张丽萍. 语义代码检索方法研究进展. 计算机应用研究, 2021, 38(11): 3215-3221, 3230.
[doi:10.19734/j.issn.1001-3695.2021.04.0096] |