Press "Enter" to skip to content

软件缺陷预测中的深度语义特征学习

分享一篇18年 Software Engineering 的文章,是作者在ICSE” 16上发表的会议论文的扩展,题目为“Deep Semantic Feature Learning for Software Defect Prediction”。

 

 

传统的缺陷预测特征不能很好地捕捉不同程序之间的语义差异。这降低了建立在这些传统特征上的预测模型的性能。为了弥合语义和缺陷预测特征之间的差距,本文作者使用深度学习从源代码文件和代码变更中学习程序的语义表示。

 

如图1所示,具有不同语义的程序可以使用相似甚至相同的传统特征来表示。因此,传统特征不能很好地区分bug代码和clean代码。

 

 

Fig. 1 Motivation示例

 

这里简单介绍几个概念,在之前的论文阅读笔记中没有提到:

 

 

文件级缺陷预测

 

 

文件级缺陷预测的目标是: 预测目标源代码文件是否存在缺陷 。

 

在进行项目内缺陷预测时,模型的测试集和训练集都是基于同一个项目构建的,如图中的Project A。而在执行跨项目缺陷预测时,训练集基于Project A构建,而测试集基于Project B构建。

 

 

变更级缺陷预测

 

 

变更级缺陷预测的目的是: 在代码提交时,预测代码变更是否存在缺陷 。

 

在变更级缺陷预测中,需要将代码修复变更和引入缺陷的变更联系起来,比如:将修复变更和引入缺陷变更表示为一个序列(参考前面分享的几篇关于JIT缺陷预测的文章)。

 

模型的框架如图2所示,核心是使用DBN网络从源代码和代码变更中提取语义特征。

 

对于文件级缺陷预测,以源代码AST的节点token作为输入,生成语义特征。对于变更级缺陷预测,模型的输入是变更后的代码片段。对于代码的向量化,模型采用映射表的方式,将每一个token按照预先设定的向量表转换成数值。模型分为4个部分:(1)源代码解析,(2)token编码,(3)特征生成和(4)模型训练与预测。

 

 

Fig. 2 模型框架

 

 

源代码解析

 

 

解析源代码文件

 

对于文件级缺陷预测,将源代码解析为AST,提取3类节点:(1)方法调用和类示例创建的节点,(2)声明节点,(3)控制流节点。

 

对于跨项目缺陷预测,提取上述3类节点,但是对于(1)和(2)类节点,使用它们的节点类型而不使用其名称,因为: 方法、类和类型的名称通常是特定于项目的 。

 

解析代码变更

 

由于代码变更的语法信息是不完整的,因此基于代码变更生成AST是具有挑战的。本文考虑对(1)code addition,(2)code deletion和(3)context code进行标签化。code addition指代码变更中添加的行(如图3中15和16行),code deletion指代码变更中删除的行(如图3中7到14行),context code指code addition和code deletion周围的代码(如图3中4到6行,17行,18行)。由于code addition、code deletion和context code的内容会出现重合的问题,如图3中第7行删除的代码和第15行添加的代码,作者向原始内容中添加了特定的前缀( added_deleted_context_ )。图4到图6是从图3中提出的代码变更token示例。

 

 

Fig. 3 代码变更示例

 

 

Fig. 4 added前缀

 

 

Fig. 5 deleted前缀

 

 

Fig. 6 context前缀

 

 

token编码

 

 

在进行token编码之前,需要对缺陷数据进行去噪(缺陷数据中的噪声主要是错误的标签数据)。这里,作者使用 编辑距离相似性 算法来定义样本之间的相似性。具体来说,给定token序列A和B,编辑距离 d(A, B) 是指将A转换成B的操作中,最小的权重序列(这里有疑惑的小伙伴可以看看编辑距离算法的详解);如果 d(A, B) 越小,则说明A和B的相似性越高。基于此,作者采用Kim等人[1]在其文章中提到的CLNI方法消除具有错误标签的样本。这里插一句解释下CLNI方法(个人理解就是聚类),简单来说就是:对于每一个样本,确定与其最近的k个邻居,如果有一定数量的邻居与样本具有相反的标签,则说明样本被标记错误。

 

在处理完数据噪声的问题后,就进入token编码阶段。这里就是非常常规的向量化流程了:确定一个向量长度,将token根据映射表映射为数值,不足长度的补0,超过长度的截断。这里需要注意,向量在送入DBN时,需要进行min-max normalization,以保证传入DBN的向量中每一位的值都在0-1的范围内。

 

 

特征生成

 

 

这里主要的目标就是训练一个DBN作为特征提取器。

 

 

Fig. 7 DBN网络结构

 

在实验部分,作者关注在 项目内缺陷预测 和 跨项目缺陷预测 场景下, 文件级 和 变更级 两个层次上,分别以non-effort-aware和effort-aware为条件,模型的性能。对于non-effort-aware,评估指标使用的是recall,precision和f1;对于effort-aware,评估指标则使用 PofB20 (通过检查20%的代码行,能够发现Bug的百分比)。

 

对于文件级缺陷预测实验,作者使用PROMISE数据集,但是作者给的数据集链接失效了,我在Github上重新找了一个:https://github.com/feiwww/PROMISE-backup;对于变更级缺陷预测实验,作者使用参考文献[2-4]中提到的数据集。分别如表1和2所示。

 

在变更级缺陷预测任务中,数据通常是不平衡的。为此,作者采用文献[3]所提方法进行数据收集,让训练集和测试集之间有一个gap,gap允许有更多的时间来发现和修复训练集中的错误变化,符合现实世界的缺陷发现和修复规律,同时也使得数据集更加平衡,如图8所示。此外,作者还使用SMOTE技术应对数据不平衡的问题。

 

 

Tab. 1 文件级缺陷预测数据集

 

 

Tab. 2 变更级缺陷预测数据集

 

 

Fig. 8 变更级缺陷预测数据采集方法

 

作者进行了大量的实验,这里列出一些实验结果供大家参考。

 

 

 

 

简单总结下吧,对于文件级缺陷预测,作者提取的是AST节点的特征,对于变更级缺陷预测,作者提取的是变更情况的特征(这里好像是废话文学,哈哈)。然后使用DBN网络作为特征提取器,最后使用分类器进行缺陷预测。这篇文章的工作量挺足的,模型其实也挺简单。最近一直在看缺陷预测的文章,总感觉每篇文章中用的特征都很简单,比如:AST节点特征,代码度量特征等等,个人感觉 单纯依靠这些特征,模型可能并不能很好地学到与缺陷预测相关的信息,比如:缺陷模式 。这是我目前的看法,等后面做实验看看,到时候再来填坑。

 

参考文献

 

[1] Kim S, Zhang H, Wu R, et al. Dealing with noise in defect prediction[C]//2011 33rd international conference on software engineering (ICSE). IEEE, 2011: 481-490.

 

[2] Jiang T, Tan L, Kim S. Personalized defect prediction[C]//2013 28th IEEE/ACM International Conference on Automated Software Engineering (ASE). Ieee, 2013: 279-289.

 

[3] Tan M, Tan L, Dara S, et al. Online defect prediction for imbalanced data[C]//2015 IEEE/ACM 37th IEEE International Conference on Software Engineering. IEEE, 2015, 2: 99-108.

 

[4] Xia X, Lo D, Wang X, et al. Collective personalized change classification with multiobjective search[J]. IEEE Transactions on Reliability, 2016, 65(4): 1810-1829.

 

声明:本文来自拨开云雾,版权归作者所有。文章内容仅代表作者独立观点,不代表本站立场,转载目的在于传递更多信息。如有侵权,请留言。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注