«上一篇 下一篇»
  计算机工程  2022, Vol. 48 Issue (7): 168-176, 198  DOI: 10.19678/j.issn.1000-3428.0062165
0

引用本文  

艾成豪, 高建华, 黄子杰. 混合特征选择和集成学习驱动的代码异味检测[J]. 计算机工程, 2022, 48(7), 168-176, 198. DOI: 10.19678/j.issn.1000-3428.0062165.
AI Chenghao, GAO Jianhua, HUANG Zijie. Code Smell Detection Driven by Hybrid Feature Selection and Ensemble Learning[J]. Computer Engineering, 2022, 48(7), 168-176, 198. DOI: 10.19678/j.issn.1000-3428.0062165.

基金项目

国家自然科学基金(61672355)

作者简介

艾成豪(1995—),男,硕士研究生,主研方向为Web安全测试、软件测试;
高建华,教授、博士;
黄子杰,博士研究生

文章历史

收稿日期:2021-07-22
修回日期:2021-09-16
混合特征选择和集成学习驱动的代码异味检测
艾成豪1 , 高建华1 , 黄子杰2     
1. 上海师范大学 计算机科学与技术系, 上海 200234;
2. 华东理工大学 计算机科学与工程系, 上海 200237
摘要:代码异味是违反基本设计原理或编码规范的软件特征,源代码中若存在代码异味将提高其维护的成本和难度。在代码异味检测方法中,机器学习相较其他方法能够取得更好的性能表现。针对使用大量特征进行训练可能会引起“维度灾难”以及单一模型泛化性能不佳的问题,提出一种混合特征选择和集成学习驱动的代码异味检测方法。通过ReliefF、XGBoost特征重要性和Pearson相关系数计算出所有特征的权重并进行融合,删除融合后权重值较低的无关特征,以得到特征子集。构建具有两层结构的Stacking集成学习模型,第一层的基分类器由3种不同的树模型构成,第二层以逻辑回归作为元分类器,两层结构的集成学习模型能够结合多样化模型的优点来增强泛化性能。将特征子集输入Stacking集成学习模型,从而完成代码异味分类与检测任务。实验结果表明,该方法能够减少特征维度,与Stacking集成学习模型第一层中的最优基分类器相比,其在F-measure和G-mean指标上最高分别提升1.46%和0.87%。
关键词代码异味    特征选择    集成学习    权重融合    Stacking模型    
Code Smell Detection Driven by Hybrid Feature Selection and Ensemble Learning
AI Chenghao1 , GAO Jianhua1 , HUANG Zijie2     
1. Department of Computer Science and Technology, Shanghai Normal University, Shanghai 200234, China;
2. Department of Computer Science and Engineering, East China University of Science and Technology, Shanghai 200237, China
Abstract: Code smell is a software feature that violates basic design principles or coding standards.When introduced into a source code, code smell increases the cost and difficulty of its maintenance.Machine learning can outperform other code smell detection methods.A code smell detection method based on hybrid feature selection and ensemble learning is proposed to address the possible 'dimension disaster' issue from the use of too many features in training, and the poor generalization performance of a single model.The weights of all features are calculated and fused using ReliefF, XGBoost feature importance, and the Pearson correlation coefficient, and irrelevant features with lower weights after fusion are deleted to obtain feature subsets. A two-layer Stacking ensemble learning model is constructed.The base classifier in the first layer comprises three different tree models, and the second layer uses Logistic Regression(LR) as a meta-classifier.The two-layer Stacking ensemble learning model combines the advantages of diversified models to enhance generalization performance.Inputting the feature subset into the Stacking ensemble learning model completes the code smell classification and detection.The experimental results show that the proposed method can reduce the feature dimension.Compared with the optimal base classifier in the first layer of the Stacking ensemble learning model, the maximum improvements in F-measure and G-mean indicators are 1.46% and 0.87%, respectively.
Key words: code smell    feature selection    ensemble learning    weight fusion    Stacking model    

开放科学(资源服务)标志码(OSID):

0 概述

为了评估软件的可维护性,FOWLER等[1]引入代码异味的概念,其表示开发人员在实现软件系统的过程中使用的不良设计和代码实现。代码异味使软件的易变性和易错性提高[2],且其拥有很长的生命周期[3]。若代码异味未被及时消除,因它们所导致的工作量和维护成本将会成倍增加,消除代码异味也会变得更加困难[4],及时检测出源代码中所含的代码异味能够有效避免此类问题的产生。

目前,已经有很多研究人员提出多种代码异味检测技术[5-7],它们中的大多数都是基于规则或启发式方法,即应用检测规则从源代码中计算相关度量值,并与统计所得的阈值进行比较,以确定源代码中是否含有代码异味[8]。然而,这些技术均存在一定的局限性,如开发人员对代码异味的理解不同,在对阈值的设定和度量的选择过程中带有主观性[9],从而导致不同检测技术对相同代码异味的检测结果存在差异[10]。机器学习技术被视为解决上述问题的一种有效方法,其能自动地组合代码度量,且无需指定任何阈值。目前大部分通用机器学习算法都能取得较高的检测性能[11],但是它们仍然存在待改进的部分。

在模型选择方面,没有一种单一模型能在所有代码异味检测中都取得良好的表现[12]。为此,集成学习方法被应用于代码异味检测,但是,以往的研究都侧重于使用同构集成学习,而对于异构集成学习的研究较少。

在类平衡方面,代码异味的数据普遍存在不平衡的问题,受代码异味影响的样本偏少[13]。相关学者首先使用采样技术平衡代码异味正、负(即有异味与无异味)样本比例,然后利用特征选择方法得到最优特征子集,将其送入机器学习方法中进行检测,最终取得较高的检测性能[14-15]。然而,近期有相关研究指出,类平衡算法可能会降低模型性能,从类对于软件系统重要性的角度出发,也没有任何的类需要“被平衡”[16]

在特征选择方面,若使用大量特征进行训练可能会造成“维度灾难”问题,从而增加模型训练时间并使其产生过拟合[17]。然而,代码异味的特征度量可能存在高度共线问题[18],这意味着在原始数据集中存在的多数度量对代码异味预测没有任何帮助,而且会导致模型过拟合。文献[19]结合多种特征选择方法,首先使用Spearman相关系数检测特征对之间的相关性,选出相关性较高的特征对,然后删除特征对中信息增益率较小的部分,分析结果表明,该方法的分类性能取得一定提升。

本文针对上述模型和特征选择中存在的问题,提出一种混合特征选择和集成学习驱动的代码异味检测方法。比较多种机器学习模型在不同代码异味上的分类性能,以选择适合被测异味的模型。设计一种混合特征选择方法,用于去除对分类结果影响较小的无关特征。在此基础上,构建一种两层结构的Stacking集成学习模型,通过集成单一模型的优点来提升分类性能。

1 相关技术 1.1 代码异味

代码异味最初的版本涵盖了22种异味,其为一种设计上的缺陷,会对软件维护带来一定的影响,通常利用重构对代码异味进行干预。本文主要研究以下4种在开发过程中较为常见的代码异味:

1)LM(LongMethod):类中方法具有过长的代码行数[4]

2)LC(LazyClass):复杂性较低的类,包含简单的方法[4]

3)CDSBP(ClassDataShouldBePrivate):类存在公开(Public)字段,因而违反了封装中的可见性要求[20]

4)LPL(LongParameterList):类中方法存在过长的参数列表[20]

1.2 源代码度量

源代码度量(即特征度量)是一组从不同角度对软件系统进行描述的值,其能使开发人员更好地了解他们正在编写的代码。源代码度量标准主要分为产品度量和过程度量两大类,产品度量包括代码规模度量、复杂性度量等,过程度量包括代码变更度量、开发人员度量等。源代码度量是代码异味检测中的重要依据,不同代码异味对应的源代码度量不同,表 1所示为一些常见的代码异味检测规则。

下载CSV 表 1 代码异味检测规则 Table 1 Code smell detection rules
1.3 特征选择

从源代码中提取的大量代码度量可能是无关的,即特征与分类标签(是否为异味)之间的相关性较低。若存在大量无关的特征,会产生“维度灾难”问题,从而增加模型运行时间并降低分类性能。特征选择是解决此类问题最有效的方法之一。特征选择主要分为过滤法(Filter)、包装法(Wrapper)和嵌入法(Embedded)[25]3种:过滤法选取所有特征中最具区别性、不依赖于任何分类算法的特征,其计算所有特征与分类标签之间的相关性,过滤掉相关性较低的特征,将保留的高相关性特征作为后续模型的输入;包装法依据分类算法的预测性能来评判所选特征子集的质量,其预先制定好一种搜索策略,将搜索得到的特征子集送入分类器,预测结果越好,则该子集越有效;嵌入法结合了上述两者的思想,即将特征选择过程嵌入到分类算法中,从而筛选出最优子集。

本文采用一种混合特征选择方法,该方法结合过滤法和嵌入法的优点,融合通过ReliefF、XGBoost特征重要性和Pearson相关系数得到的特征权重值,以去除与分类标签无关的特征。

1.3.1 ReliefF

ReliefF是对Relief的扩展,其能够处理多分类数据。ReliefF是一种过滤法,根据特征对近距离样本的区分能力赋予特征不同的权重,权重越大,则分类能力越强。每次从样本集中随机选择一个样本S,寻找与它同类别的K个近邻样本,记为$ \mathrm{N}\mathrm{H} $;从不同于样本S的类别中各选出K个近邻样本,记为$ \mathrm{N}\mathrm{M}\left(C\right) $。迭代更新所有特征的权重$ \omega \left(x\right) $[26],如式(1)所示:

$ \omega \left(x\right)=\omega \left(x\right)-\sum\limits _{j=1}^{k}\frac{\mathrm{d}\mathrm{i}\mathrm{f}\mathrm{f}\left(X, S, \mathrm{N}{\mathrm{H}}_{j}\right)}{m\cdot k}+ $
$ \sum\limits _{C\ne \mathrm{C}\mathrm{l}\mathrm{a}\mathrm{s}\mathrm{s}\left(S\right)}\frac{\left[\frac{p\left(C\right)}{1-p\left(\mathrm{C}\mathrm{l}\mathrm{a}\mathrm{s}\mathrm{s}\left(S\right)\right)}\cdot \sum\limits _{j=1}^{k}\mathrm{d}\mathrm{i}\mathrm{f}\mathrm{f}\left(X, S, \mathrm{N}\mathrm{M}{\left(C\right)}_{j}\right)\right]}{m\cdot k} $ (1)

其中:m为迭代次数;PC)为第C类的概率;Class(S)为样本S所属的类别;$ \mathrm{N}{\mathrm{H}}_{j} $为与S同类别的第j个近邻;$ \mathrm{N}\mathrm{M}{\left(C\right)}_{j} $为与S不同类别的第j个近邻;$ \mathrm{d}\mathrm{i}\mathrm{f}\mathrm{f}(X, S, {S}') $为特征X上样本S$ {S}' $之间的距离。$ \mathrm{d}\mathrm{i}\mathrm{f}\mathrm{f}(X, S, {S}') $的计算如式(2)所示:

$ \mathrm{d}\mathrm{i}\mathrm{f}\mathrm{f}\left(X, S, {S}'\right)=\left\{\begin{array}{c}\frac{\left|S\left[X\right]-{S}'\left[X\right]\right|}{\mathrm{m}\mathrm{a}\mathrm{x}\left(X\right)-\mathrm{m}\mathrm{i}\mathrm{n}\left(X\right)}, X\mathrm{连}\mathrm{续}\\ 0, X\mathrm{离}\mathrm{散}\mathrm{且}S\left[X\right]={S}'\left[X\right]\\ 1, X\mathrm{离}\mathrm{散}\mathrm{且}S\left[X\right]\ne {S}'\left[X\right]\end{array}\right. $ (2)
1.3.2 Pearson相关系数

Pearson相关系数是一种过滤法,其能够衡量2个变量XY之间相关性的强弱,当一个变量的变化能引起另一个变量改变时,则称它们之间具有相关性[27]。Pearson相关系数的计算公式如式(3)所示:

$ \rho =\mathrm{c}\mathrm{o}\mathrm{r}\mathrm{r}\left(X, Y\right)=\frac{\mathrm{c}\mathrm{o}\mathrm{v}\left(X, Y\right)}{{\sigma }_{X}{\sigma }_{Y}}= $
$ \frac{\sum\limits _{i=1}^{n}\left({x}_{i}-\stackrel{-}{x}\right)\left({y}_{i}-\stackrel{-}{y}\right)}{\sqrt[]{\sum\limits _{i=1}^{n}{\left({x}_{i}-\stackrel{-}{x}\right)}^{2}}\sqrt[]{\sum\limits _{i=1}^{n}{\left({y}_{i}-\stackrel{-}{y}\right)}^{2}}} $ (3)

其中:$ {\sigma }_{X} $$ {\sigma }_{Y} $分别表示2个变量的标准差;$ \mathrm{c}\mathrm{o}\mathrm{v}\left(X, Y\right) $表示2个变量的协方差;n为样本数量;$ \stackrel{-}{x} $$ \stackrel{-}{y} $分别为变量XY的均值。

Pearson相关系数输出值$ \rho $的取值范围在-1~1之间:当取值为负数时,表示2个变量呈负相关;当取值为0时,表示2个变量之间独立;当取值为正数时,表示2个变量呈正相关。$ \rho $的绝对值越接近1,则2个变量的相关性越高,它们之间的联系也越紧密。

1.3.3 XGBoost特征重要性

XGBoost由CHEN等[28]于2016年提出,其为一种高效、可扩展的机器学习模型。XGBoost是基于梯度提升决策树(GBDT)改进的模型,通过Boosting方式组合多棵CART决策树,其主要思想是通过迭代添加新的分类器来拟合之前的残差。XGBoost对损失函数进行二阶泰勒展开来近似目标函数,并通过向目标函数添加控制模型复杂度的正则项来获取更好的泛化性,从而避免过拟合问题。此外,XGBoost能充分发挥多核CPU的优势进行并行计算,大幅缩短了运行时间。

XGBoost特征重要性(XGBI)是嵌入法中的一种,其通过XGBoost在训练过程中得到每个特征的重要性,特征重要性值越高,则该特征在模型构建与训练过程中的贡献越大。XGBoost利用贪心算法来确定树的结构,即寻找最优切分点,其通过遍历所有节点并计算分裂前后的差值得到增益,选择增益最大的节点进行分裂[29]

增益的计算公式如式(4)所示:

$ {G}_{\mathrm{G}\mathrm{a}\mathrm{i}\mathrm{n}}=\frac{1}{2}\left[\frac{{G}_{L}^{2}}{{H}_{L}+\delta }+\frac{{G}_{R}^{2}}{{H}_{R}+\delta }-\frac{{\left({G}_{L}+{G}_{R}\right)}^{2}}{{H}_{L}+{H}_{R}+\delta }\right]-\gamma $ (4)
1.4 集成学习

集成学习利用特定的策略组合多个基分类器(即机器学习模型)来构建相对稳定和准确的模型。与单个分类器相比,集成学习能取得更好的结果和更强的泛化能力。在通常情况下,集成学习遵循以下2个原则:

1)基分类器的准确率高于随机猜测。

2)基分类器之间具有多样性[30]

集成学习主要分为Boosting、Bagging和Stacking这3种:Boosting是串行关系,其按顺序逐一构造多个基分类器,并以迭代方式调整前一个分类器错误分类的样本权重,用于训练下一个分类器;Bagging对训练样本采用Bootstrap抽样策略,并行地训练多个独立的基分类器,并将它们的结果以多数投票或取平均的方法进行结合。以上2种集成学习是同质集成,即只包含同种类型的基分类器。本文采用的Stacking是一种异构集成学习模型,该模型由WOLPERT[31]于1992年提出,其通过结合多种不同类型的机器学习模型,使得模型的边界变得更稳定,避免单一模型预测性能不佳、鲁棒性较差的问题。Stacking集成学习模型通常被设计为两层框架的结构,为此引入了基分类器和元分类器的概念。第一层由多个基分类器组成,为了防止过拟合,采用K折交叉验证对其进行训练,合并它们的预测结果形成新数据集后输入第二层的元分类器中,从而得到最终的结果。Stacking集成学习模型的构建过程如图 1所示,第一层以5折交叉验证为例,其实现过程如算法1所示。

Download:
图 1 Stacking集成学习模型构建过程 Fig. 1 Construction procedure of Stacking ensemble learning model

算法1  Stacking集成学习模型算法

输入  数据集D

输出  模型预测结果

1.将数据集D按比例划分成训练集Dtrain和测试集Dtest

2.采用K折交叉验证方法,把Dtrain划分成K个子集$ \left\{{\mathrm{D}}_{1}, {\mathrm{D}}_{2}, \cdots , {\mathrm{D}}_{\mathrm{k}}\right\} $,取$ {\mathrm{D}}_{\mathrm{j}}\left(\mathrm{j}=\mathrm{1, 2}, \cdots , \mathrm{k}\right) $作为测试集,其余部分作为训练集,记为$ {\mathrm{D}}^{\mathrm{*}} $

3.将$ {\mathrm{D}}^{\mathrm{*}} $$ {\mathrm{D}}_{\mathrm{j}} $分别作为基分类器$ {\mathrm{C}}_{1} $的训练集与测试集,得到预测结果$ {{\rm{ \mathsf{ α} }}}_{1} $。同时,用经过训练的基分类器对Dtest进行预测,得到预测结果$ {{\rm{ \mathsf{ β} }}}_{1} $

4.对上一步循环K次得到$ \left\{{{\rm{ \mathsf{ α} }}}_{1}, {{\rm{ \mathsf{ α} }}}_{2}, \cdots , {{\rm{ \mathsf{ α} }}}_{\mathrm{k}}\right\} $,并将其按列合并成一个列向量,记为$ {\mathrm{A}}_{1} $。对$ \left\{{{\rm{ \mathsf{ β} }}}_{1}, {{\rm{ \mathsf{ β} }}}_{2}, \cdots , {{\rm{ \mathsf{ β} }}}_{\mathrm{k}}\right\} $取平均得到列向量,记为$ {\mathrm{B}}_{1} $

5.对剩余分类器$ {\mathrm{C}}_{2}, {\mathrm{C}}_{3}, \cdots , {\mathrm{C}}_{\mathrm{n}} $依次执行步骤3、步骤4,得到$ {\mathrm{A}}_{2}, {\mathrm{A}}_{3}, \cdots , {\mathrm{A}}_{\mathrm{n}} $$ {\mathrm{B}}_{2}, {\mathrm{B}}_{3}, \cdots , {\mathrm{B}}_{\mathrm{n}} $

6.将$ \left\{{\mathrm{A}}_{1}, {\mathrm{A}}_{2}, \cdots , {\mathrm{A}}_{\mathrm{n}}\right\} $与Dtrain的标签Y合并后作为新训练集,训练元分类器,再将$ \left\{{\mathrm{B}}_{1}, {\mathrm{B}}_{2}, \cdots , {\mathrm{B}}_{\mathrm{n}}\right\} $作为元分类器的测试集进行预测,得到最终结果。

2 本文代码异味检测方法

针对使用大量特征进行训练可能引起“维度灾难”以及单一模型泛化性能不佳的问题,本文提出一种混合特征选择和集成学习驱动的代码异味检测方法。该方法首先从开源项目中提取度量并与对应的分类标签合并构成代码异味数据集,然后对数据归一化后的数据集进行混合特征选择,最后将得到的特征子集送入后续的Stacking集成学习模型进行分类。本文方法流程如图 2所示。

Download:
图 2 本文代码异味检测方法流程 Fig. 2 The procedure of code smell detection method in this paper
2.1 数据集

本文考虑4个大小不一且属于不同领域的Java开源项目,分别为Rhino 1.6R6、ArgoUML0.26、Mylyn 3.1.1和Eclipse 3.3.1,用以构建代码异味数据集。由于本文方法需要大量自变量,即面向对象的度量值,因此使用SourceMeter和CKJM extended这2种常用的度量计算工具,共提取78个度量,度量说明如表 2表 3所示。

下载CSV 表 2 SourceMeter提取的度量 Table 2 Metrics extracted by SourceMeter
下载CSV 表 3 CKJM extended提取的度量 Table 3 Metrics extracted by CKJM extended

在所提取的度量中,存在一小部分相同的度量,本文按照文献[32]中的做法将它们保留,保留的原因是所用的度量计算工具针对的对象不同,SourceMeter是针对源文件,而CKJM extended是对字节码文件进行计算,因此,两者得到的度量值不同[33]。数据集中的异味标签均来自于文献[20],最后,利用类名作为匹配键合并度量与异味标签,得到一个含有14 063条样本、78个度量以及4种代码异味的数据集,数据集格式如图 3所示。

Download:
图 3 数据集格式 Fig. 3 Dataset format
2.2 数据归一化

在模型构建之前,通常需要将不同规格的数据转换为统一规格,或将不同分布的数据转换成所需的特定分布,即数据需要无量纲化。文献[34]指出数据归一化不仅能够增强分类器的性能,而且可以加快求解速度,提高模型的求解质量。Min-Max归一化是最常用的数据归一化方法,其对原始数据进行线性变换,转换公式如式(5)所示:

$ {X}_{i}^{*}=\frac{{X}_{i}-{X}_{\mathrm{m}\mathrm{i}\mathrm{n}}}{{X}_{\mathrm{m}\mathrm{a}\mathrm{x}}-{X}_{\mathrm{m}\mathrm{i}\mathrm{n}}} $ (5)

其中:XminXmax分别是第i个特征的最小值和最大值;X*的取值在$ \left[\mathrm{0, 1}\right] $范围内。

2.3 混合特征选择

使用原始的高维特征集不但会增加分类器的计算成本,还可能降低其识别性能,因此,需要使用特征选择方法优化特征数量。文献[25]指出单一的特征选择方法可能会在筛选特征的过程中忽略一些潜在信息,导致结果不稳定。文献[35]通过结合多种特征选择方法来提高特征选择的鲁棒性。本文提出一种混合特征选择方法,该方法结合ReliefF、XGBoost特征重要性和Pearson相关系数这3种常见的特征选择方法,计算出特征权重并进行融合,然后去除权重值较低的无关特征。在对特征权重向量融合的过程中,需要确保不同方法所生成的权重具有可比性,因此,在此之前需对权重向量进行Min-Max归一化。本文混合特征选择方法的输入是归一化后的数据集,输出是特征子集,具体步骤如下:

步骤1  由ReliefF、XGBoost特征重要性和Pearson相关系数分别生成含有所有特征的权重向量。

由ReliefF得到的权重向量为:

$ {\boldsymbol{W}}_{\mathrm{R}}=\left[{\omega }_{1}\left(x\right), {\omega }_{2}\left(x\right), \cdots , {\omega }_{n}\left(x\right)\right] $ (6)

由XGBoost特征重要性得到的权重向量为:

$ {\boldsymbol{W}}_{\mathrm{X}}=\left[\mathrm{G}\mathrm{a}\mathrm{i}{\mathrm{n}}_{1}, \mathrm{G}\mathrm{a}\mathrm{i}{\mathrm{n}}_{2}, \cdots , \mathrm{G}\mathrm{a}\mathrm{i}{\mathrm{n}}_{n}\right] $ (7)

由Pearson相关系数得到的权重向量为:

$ {\boldsymbol{W}}_{\mathrm{P}}=\left[{\rho }_{1}, {\rho }_{2}, \cdots , {\rho }_{n}\right] $ (8)

步骤2  利用融合策略,将通过3种特征选择方法得到的权重向量进行合并,融合策略为:

$ \boldsymbol{W}={\boldsymbol{W}}_{\mathrm{R}}+{\boldsymbol{W}}_{\mathrm{X}}+{\boldsymbol{W}}_{\mathrm{P}} $ (9)

步骤3  将特征权重融合后的值按从高到低降序排列,删除权重值较低的后20%的特征,这些特征与分类标签的相关性较弱。

不同特征选择方法的侧重点不同,将它们结合可能会在特征空间中产生更好的表示以描述数据,从而弥补单一特征选择方法偏向某一方面的缺陷。本文方法能在一定程度上减少无关特征,避免有效特征信息损失,以达到降低计算成本并提高后续算法性能的目的。

2.4 Stacking集成学习模型构建

为了更好地检测代码异味,避免单一模型泛化性能不佳的问题,本文构建一种两层结构的Stacking集成学习模型。该模型的第一层由异构基分类器构成,这些基分类器需要具有较高的准确性以及多样性,为此本文使用LGB(LightGBM)、XGB(XGBoost)和RF(Random Forest)这3种理论较成熟的模型,它们之间具有一定差异,能通过使用不同的学习策略来从不同角度和空间学习特征,实现模型间的互补,从而提升Stacking集成学习模型的整体性能。

第一层采用K折交叉验证对基分类器进行训练,即将数据随机划分成K份,其中的K-1份作为训练集,剩余的1份作为测试集,重复K次。由于代码异味数据集大多呈不平衡状态,因此本文在此层的每一折中都应用分层抽样,以保证代码异味的分布与原始训练集中的分布相同[23]

第二层元分类器的输入不再是原始数据的特征,而是各基分类器的预测结果合并变换后的数据。文献[36]指出基分类器使用复杂的非线性变换提取数据特征,容易过拟合,元分类器无需使用复杂的分类器,因此,本文使用与其相同的分类器LR(Logistic Regression),该分类器通常被用来处理二分类问题,其结构简单且可以通过正则化进一步防止过拟合。

本文所构建的Stacking集成学习模型流程如图 4所示。

Download:
图 4 Stacking集成学习模型流程 Fig. 4 The procedure of Stacking ensemble learning model
3 实验结果与分析

本节在4个项目上验证混合特征选择和集成学习驱动的代码异味检测方法的有效性,主要解决如下4个问题:

Q1:哪些机器学习模型能够在本文所检测的代码异味中取得良好的表现?

Q2:混合特征选择方法是否有效?

Q3:Stacking集成学习模型能否提高代码异味检测的性能?

Q4:与其他方法相比,本文所提方法是否具有优势?

3.1 实验环境

本文实验环境设置:操作系统为Windows 10,处理器为Intel® CoreTM i7-8550U @1.80 GHz,内存为16 GB,实验工具为Jupyter Notebook,编程语言为Python。在实验过程中,采用10$ \times $5折交叉验证的方式进行验证,即取10次5折交叉验证的平均值,以确保结论的可靠性。

3.2 评价指标

由于本文构建的模型是用于检测模块中是否含有代码异味,属于二分类问题,因此模型性能的好坏可以通过混淆矩阵展现,混淆矩阵如表 4所示。

下载CSV 表 4 混淆矩阵 Table 4 Confusion matrix

混淆矩阵中各元素的含义分别为:1)TTP(True Positive):正确识别为异味的异味样本数;2)TTN(True Negative):正确识别为无异味的无异味样本数;3)FFN(False Negative):错误识别为无异味的异味样本数;4)FFP(False Positive):错误识别为异味的无异味样本数。

由混淆矩阵衍生出多种评价指标,为了更直观地评估本文方法的性能,考虑F-measure和G-mean这2种指标,F-measure和G-mean均含有精确率(Precision)和召回率(Recall)。

Precision表示预测为异味的样本中真正为异味的样本占比,如式(10)所示:

$ {P}_{\mathrm{P}\mathrm{r}\mathrm{e}\mathrm{c}\mathrm{i}\mathrm{s}\mathrm{i}\mathrm{o}\mathrm{n}}=\frac{{T}_{\mathrm{T}\mathrm{P}}}{{T}_{\mathrm{T}\mathrm{P}}+{F}_{\mathrm{F}\mathrm{P}}} $ (10)

Recall表示正确预测为有异味的样本占真实异味样本的比例,如式(11)所示:

$ {R}_{\mathrm{R}\mathrm{e}\mathrm{c}\mathrm{a}\mathrm{l}\mathrm{l}}=\frac{{T}_{\mathrm{T}\mathrm{P}}}{{F}_{\mathrm{F}\mathrm{N}}+{T}_{\mathrm{T}\mathrm{P}}} $ (11)

F-measure是一个综合评价指标,因为Precision和Recall会出现相互矛盾的状况,存在一定的局限性,难以单独用于评价分类性能,因此,必须综合考虑这两者。F-measure是Precision和Recall的加权调和平均值,其值越大,则模型性能较好。F-measure计算如式(12)所示:

$ \mathrm{F-m}\mathrm{e}\mathrm{a}\mathrm{s}\mathrm{u}\mathrm{r}\mathrm{e}=2\times \frac{{P}_{\mathrm{P}\mathrm{r}\mathrm{e}\mathrm{c}\mathrm{i}\mathrm{s}\mathrm{o}\mathrm{n}}\times {R}_{\mathrm{R}\mathrm{e}\mathrm{c}\mathrm{a}\mathrm{l}\mathrm{l}}}{{P}_{\mathrm{P}\mathrm{r}\mathrm{e}\mathrm{c}\mathrm{i}\mathrm{s}\mathrm{i}\mathrm{o}\mathrm{n}}+{R}_{\mathrm{R}\mathrm{e}\mathrm{c}\mathrm{a}\mathrm{l}\mathrm{l}}} $ (12)

代码异味数据集通常呈现类不平衡状态,G-mean指标能够更直观地评价类不平衡性能,其计算如式(13)所示:

$ \mathrm{G} - \mathrm{m}\mathrm{e}\mathrm{a}\mathrm{n}=\sqrt[]{\frac{{T}_{\mathrm{T}\mathrm{P}}}{{F}_{\mathrm{F}\mathrm{N}}+{T}_{\mathrm{T}\mathrm{P}}}+\frac{{T}_{\mathrm{T}\mathrm{N}}}{{T}_{\mathrm{T}\mathrm{N}}+{F}_{\mathrm{F}\mathrm{P}}}} $ (13)
3.3 结果分析

1)解决Q1问题。

表 5所示为XGB(XGBoost)、LGB(LightGBM)、随机森林(RF)、决策树(DT)、K最近邻(KNN)和朴素贝叶斯(NB)这6种机器学习模型在不同代码异味上的检测性能,最优结果加粗表示。从表 5可以看出,综合性能排在前三的模型为XGB、LGB和RF,它们都是基于树的模型,与文献[37]中的结论相符,即基于树的模型在代码异味检测中都有着良好的表现。分析表中的数据可以发现,在LC、CDSBP、LPL这3种代码异味上XGB表现最好,而LGB在LM这一种异味上优于其他模型,由此可得,并没有一种模型适合检测所有的代码异味。因此,本文选择XGB、LGB和RF作为后续Stacking集成学习模型的基分类器,以避免单一模型泛化性能不佳的问题。

下载CSV 表 5 不同分类器的代码异味检测结果 Table 5 Code smell detection results of different classifiers

2)解决Q2问题。

表 6所示为特征选择前后XGB、LGB和RF模型在不同代码异味上的F-measure对比结果。从表 6可以看出,在多数情况下,特征选择前后的F-measure值相差不大,由此可得数据集中存在无关特征,去除这些无关特征并不会对结果造成影响。

下载CSV 表 6 特征选择前后模型的F-measure值对比 Table 6 Comparison of F-measure values of models before and after feature selection

图 5所示为所选机器学习模型在4种代码异味数据集上进行特征选择前后的平均训练时间,即进行一次5折交叉验证的时间。从图 5可以看出,XGB、LGB与RF在特征选择后的平均训练时间相较特征选择前都有所降低,其中,XGB下降幅度最大,RF其次,下降幅度最小的是LGB。以XGB为例,在特征选择前,其在4种代码异味数据集上的训练时间为31.23 s,而经过特征选择后,训练时间减少至26.18 s,时间缩短效率为16.17%。由此可见,特征选择在确保F-measure的同时能够在一定程度上缩短模型的训练时间。

Download:
图 5 特征选择前后模型的平均训练时间对比 Fig. 5 Comparison of average training time of models before and after feature selection

3)解决Q3问题。

表 7可以看出,相较单一模型,Stacking集成学习模型在特征选择后的数据中都能够取得良好的分类性能,在F-measure和G-mean评价指标上均有一定提升。经分析,Stacking集成学习模型优于单一模型的原因如下:Stacking集成学习模型能够结合多样化的模型,这些模型能够从不同角度来观测数据,从而充分发挥每一种模型的优势,同时屏除分类结果较差的部分,以纠正单一模型的预测偏差;从模型优化的角度来看,单一模型在训练过程中可能会有陷入局部最优的风险,导致其泛化性能不佳,而集成多种模型可以减少此类风险发生的概率[38];Stacking集成学习模型通常为两层结构,第二层结构能纠正第一层结构产生的误差,从而提高模型的分类精度。

下载CSV 表 7 特征选择后单一模型和Stacking集成学习模型的性能比较 Table 7 Performance comparison of single model and Stacking ensemble learning model after feature selection

4)解决Q4问题。

将本文模型与文献[39]模型、文献[40]模型以及异构集成学习中的Voting模型进行比较,这些对比模型均采用本文的数据集,以确保可比性。针对文献[39]模型,使用自编码器将原始数据降至与本文特征选择后相同的维度,而对于文献[40]模型以及Voting模型,均使用本文特征选择后的数据,并将Voting模型中的基分类器与本文中的Stacking模型保持一致,即XGB、LGB和RF。从表 8可以看出,文献[39]模型和文献[40]模型的性能指标均低于本文模型,而Voting模型仅在检测LM代码异味时略优于本文模型,由此可见,本文模型具有良好的鲁棒性。

下载CSV 表 8 不同模型的性能比较 Table 8 Performance comparison of different models
4 结束语

本文提出一种混合特征选择和集成学习驱动的代码异味检测方法,其融合由多种特征选择方法得到的特征权重以去除无关特征,同时利用Stacking集成学习模型结合多种单一机器学习模型的优势来提升最终的分类性能。实验结果表明,使用混合特征选择和集成学习方法能够取得较好的代码异味检测结果,即本文所提检测方法具有有效性。代码异味通常都呈类不平衡状态,可能会对检测结果产生一定影响从而降低模型的性能,可利用采样技术来平衡代码异味数据集,因此,下一步将求证该技术在代码异味检测中是否有效,并使用模型可解释性方法探究采样技术对代码异味预测模型性能的影响。此外,本文仅使用了产品度量,加入过程度量后是否能提高分类精度也是今后的一个研究课题。

参考文献
[1]
FOWLER M. Refactoring: improving the design of existing code[M]. [S. l.]: Addison-Wesley Professional, 2018.
[2]
黄华俊, 吴海涛, 高建华, 等. 消除测试代码异味对代码质量的影响分析[J]. 小型微型计算机系统, 2020, 41(11): 2420-2426.
HUANG H J, WU H T, GAO J H, et al. Measuring the impact of test smell removal on software code quality[J]. Journal of Chinese Computer Systems, 2020, 41(11): 2420-2426. (in Chinese) DOI:10.3969/j.issn.1000-1220.2020.11.030
[3]
PALOMBA F, PANICHELLA A, ZAIDMAN A, et al. The scent of a smell: an extensive comparison between textual and structural smells[J]. IEEE Transactions on Software Engineering, 2018, 44(10): 977-1000. DOI:10.1109/TSE.2017.2752171
[4]
章晓芳, 朱灿. 代码坏味对软件演化影响的实证研究[J]. 软件学报, 2019, 30(5): 1422-1437.
ZHANG X F, ZHU C. Empirical study of code smell impact on software evolution[J]. Journal of Software, 2019, 30(5): 1422-1437. (in Chinese)
[5]
ABUHASSAN A, ALSHAYEB M, GHOUTI L. Software smell detection techniques: a systematic literature review[J]. Journal of Software: Evolution and Process, 2021, 33(3): 1-48.
[6]
SOBRINHO E V D P, DE LUCIA A, MAIA M D A. A systematic literature review on bad smells-5 w's: which, when, what, who, where[J]. IEEE Transactions on Software Engineering, 2021, 47(1): 17-66. DOI:10.1109/TSE.2018.2880977
[7]
黄子杰, 陈军华, 高建华. 检测JavaScript类的内聚耦合Code Smell[J]. 软件学报, 2021, 32(8): 2505-2521.
HUANG Z J, CHEN J H, GAO J H. Detecting coupling and cohesion Code Smell of JavaScript classes[J]. Journal of Software, 2021, 32(8): 2505-2521. (in Chinese)
[8]
PECORELLI F, DI NUCCI D, DE ROOVER C, et al. A large empirical assessment of the role of data balancing in machine-learning-based code smell detection[J]. Journal of Systems and Software, 2020, 169: 110693. DOI:10.1016/j.jss.2020.110693
[9]
黄子杰, 陈军华, 高建华. Code Smell视角下分层Web应用失血及充血现象的量化分析[J]. 电子学报, 2020, 48(4): 772-780.
HUANG Z J, CHEN J H, GAO J H. Quantifying anemia and bloodshot of layers in Web applications from the perspective of Code Smell[J]. Acta Electronica Sinica, 2020, 48(4): 772-780. (in Chinese) DOI:10.3969/j.issn.0372-2112.2020.04.019
[10]
LIU H, JIN J H, XU Z F, et al. Deep learning based code smell detection[J]. IEEE Transactions on Software Engineering, 2021, 47(9): 1811-1837.
[11]
ARCELLI FONTANA F, MÄNTYLÄ M V, ZANONI M, et al. Comparing and experimenting machine learning techniques for code smell detection[J]. Empirical Software Engineering, 2016, 21(3): 1143-1191. DOI:10.1007/s10664-015-9378-4
[12]
CARAM F L, DE OLIVEIRA RODRIGUES B R, CAMPANELLI A S, et al. Machine learning techniques for code smells detection: a systematic mapping study[J]. International Journal of Software Engineering and Knowledge Engineering, 2019, 29(2): 285-316. DOI:10.1142/S021819401950013X
[13]
BOUTAIB S, BECHIKH S, PALOMBA F, et al. Code smell detection and identification in imbalanced environ-ments[J]. Expert Systems with Applications, 2021, 166: 114076. DOI:10.1016/j.eswa.2020.114076
[14]
AGNIHOTRI M, CHUG A. Application of machine learning algorithms for code smell prediction using object-oriented software metrics[J]. Journal of Statistics and Management Systems, 2020, 23(7): 1159-1171. DOI:10.1080/09720510.2020.1799576
[15]
GUPTA H, KUMAR L, NETI L B M. An empirical framework for code smell prediction using extreme learning machine[C]//Proceedings of the 9th Annual Information Technology, Electromechanical Engineering and Microelec-tronics Conference. Washington D. C., USA: IEEE Press, 2019: 189-195.
[16]
PECORELLI F, PALOMBA F, KHOMH F, et al. Developer-driven code smell prioritization[C]//Proceedings of the 17th International Conference on Mining Software Repositories. Washington D. C., USA: IEEE Press, 2020: 220-231.
[17]
JAIN S, SAHA A J. Rank-based univariate feature selection methods on machine learning classifiers for code smell detection[J]. Evolutionary Intelligence, 2022, 15(1): 609-638. DOI:10.1007/s12065-020-00536-z
[18]
DI NUCCI D, PALOMBA F, TAMBURRI D A, et al. Detecting code smells using machine learning techniques: are we there yet?[C]//Proceedings of IEEE International Conference on Software Analysis, Evolution and Reengineering. Washington D. C., USA: IEEE Press, 2018: 612-621.
[19]
PALOMBA F, TAMBURRI D A. Predicting the emergence of community smells using socio-technical metrics: a machine-learning approach[J]. Journal of Systems and Software, 2021, 171: 110847. DOI:10.1016/j.jss.2020.110847
[20]
KHOMH F, PENTA M D, GUÉHÉNEUC Y G, et al. An exploratory study of the impact of antipatterns on class change and fault-proneness[J]. Empirical Software Engineering, 2012, 17(3): 243-275. DOI:10.1007/s10664-011-9171-y
[21]
BIGONHA M A S, FERREIRA K, SOUZA P, et al. The usefulness of software metric thresholds for detection of bad smells and fault prediction[J]. Information and Software Technology, 2019, 115: 79-92. DOI:10.1016/j.infsof.2019.08.005
[22]
KAUR S, MAINI R. Analysis of various software metrics used to detect bad smells[J]. The International Journal of Engineering and Science, 2016, 5(6): 14-20.
[23]
PECORELLI F, PALOMBA F, NUCCI D D, et al. Comparing heuristic and machine learning approaches for metric-based code smell detection[C]//Proceedings of the 27th International Conference on Program Comprehension. Washington D. C., USA: IEEE Press, 2019: 93-104.
[24]
DANPHITSANUPHAN P, SUWANTADA T. Code smell detecting tool and code smell-structure bug relationship[C]//Proceedings of Spring Congress on Engineering and Technology. Washington D. C., USA: IEEE Press, 2012: 1-5.
[25]
BOLÓN-CANEDO V, ALONSO-BETANZOS A. Ensembles for feature selection: a review and future trends[J]. Information Fusion, 2019, 52: 1-12. DOI:10.1016/j.inffus.2018.11.008
[26]
ROBNIK-SIKONJA M, KONONENKO I. Theoretical and empirical analysis of ReliefF and RReliefF[J]. Machine Learning, 2003, 53(1/2): 23-69. DOI:10.1023/A:1025667309714
[27]
XU H H, DENG Y. Dependent evidence combination based on shearman coefficient and Pearson coefficient[J]. IEEE Access, 2018, 6: 11634-11640. DOI:10.1109/ACCESS.2017.2783320
[28]
CHEN T Q, GUESTRIN C. XGBoost: a scalable tree Boosting system[C]//Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining. New York, USA: ACM Press, 2016: 785-794.
[29]
李占山, 刘兆赓. 基于XGBoost的特征选择算法[J]. 通信学报, 2019, 40(10): 101-108.
LI Z S, LIU Z G. Feature selection algorithm based on XGBoost[J]. Journal on Communications, 2019, 40(10): 101-108. (in Chinese) DOI:10.11959/j.issn.1000-436x.2019154
[30]
NGUYEN H A T, HA LE T, BUI T D. A Stacking ensemble learning model for mental state recognition towards implementation of brain computer interface[C]//Proceedings of the 6th NAFOSTED Conference on Information and Computer Science. Washington D. C., USA: IEEE Press, 2019: 39-43.
[31]
WOLPERT D H. Stacked generalization[J]. Neural Networks, 1992, 5(2): 241-259. DOI:10.1016/S0893-6080(05)80023-1
[32]
AMORIM L, COSTA E, ANTUNES N, et al. Experience report: evaluating the effectiveness of decision trees for detecting code smells[C]//Proceedings of IEEE International Symposium on Software Reliability Engineering. Washington D. C., USA: IEEE Press, 2015: 261-269.
[33]
FERENC R, TÓTH Z, LADÁNYI G, et al. A public unified bug dataset for Java[C]//Proceedings of the 14th International Conference on Predictive Models and Data Analytics in Software Engineering. Washington D. C., USA: IEEE Press, 2018: 12-21.
[34]
FENG Y, WANG D J, YIN Y Q, et al. An XGBoost-based casualty prediction method for terrorist attacks[J]. Complex & Intelligent Systems, 2020, 6(3): 721-740.
[35]
YANG F, MAO K Z. Robust feature selection for microarray data based on multicriterion fusion[J]. IEEE/ACM Transactions on Computational Biology and Bioinformatics, 2011, 8(4): 1080-1092. DOI:10.1109/TCBB.2010.103
[36]
TANG J J, LIANG J, HAN C Y, et al. Crash injury severity analysis using a two-layer Stacking framework[J]. Accident, Analysis and Prevention, 2019, 122: 226-238.
[37]
MHAWISH M Y, GUPTA M. Predicting code smells and analysis of predictions: using machine learning techniques and software metrics[J]. Journal of Computer Science and Technology, 2020, 35(6): 1428-1445. DOI:10.1007/s11390-020-0323-7
[38]
杨荣新, 孙朝云, 徐磊. 基于Stacking模型融合的光伏发电功率预测[J]. 计算机系统应用, 2020, 29(5): 36-45.
YANG R X, SUN Z Y, XU L. Photovoltaic power prediction based on Stacking model fusion[J]. Computer Systems & Applications, 2020, 29(5): 36-45. (in Chinese)
[39]
HADJ-KACEM M, BOUASSIDA N. A hybrid approach to detect code smells using deep learning[C]//Proceedings of the 13th International Conference on Evaluation of Novel Approaches to Software Engineering. Washington D. C., USA: IEEE Press, 2018: 137-146.
[40]
CHEN H, REN Z L, QIAO L, et al. AdaBoost-based refused bequest code smell detection with synthetic instances[C]//Proceedings of the 7th International Conference on Dependable Systems and Their Applications. Washington D. C., USA: IEEE Press, 2020: 78-89.