Page 32 - 《软件学报》2024年第4期
P. 32
1610 软件学报 2024 年第 35 卷第 4 期
3.3 评价指标
3.3.1 代码克隆检测
代码克隆检测的评价指标有平均精度(mean average precision, MAP@R)、召回率(recall)、准确率
(precision)、F1-值(F1-score). MAP@R 用于评价给定查询在集合中检索出的 R 个最相似样本的结果, 其中, R
设置为 499, 其计算方式如公式(13):
∑ Q AvgPrecision () q
MAP@R = q= 1 (13)
Q
其中, Q 是数据集大小. 余下评估指标的计算方法如式(14):
tp tp 2*(Precision Recall )
*
Precision = , Recall = , 1F = (14)
+
tp + fp tp + fn Precision Recall
3.3.2 语义代码检索
语义代码检索任务的评价指标 [47] 有: 最佳命中率(FRank)和平均排序倒数(mean reciprocal rank, MRR).
FRank 是指第 1 个命中结果在结果列表中的排名, 是计算 MRR 的基础. MRR 是利用查询接收到的结果集中在
第 1 个正确答案的位置来评估模型的性能, 如果正确答案越靠前, 则表示模型效果越好:
1 Q
MRR = ∑ σ (FRank ≤ ) k (15)
| Q | q= 1 q
其中, 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%.
就语义代码 检索任务而 言 , 其实验结 果 见 表 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%. 造成这种现象的可能原因是, 它们的语法和表达性