高 添,郭 曦
華中農(nóng)業(yè)大學信息學院,湖北武漢430070
軟件在開發(fā)過程中處于動態(tài)演化狀態(tài),對其維護困難且代價較大,因此盡可能準確地預測軟件存在的缺陷一直是軟件研究人員和開發(fā)者的研究熱點之一。軟件缺陷預測過程一般由4部分組成[1]:收集軟件缺陷數(shù)據(jù)、提取度量元、構(gòu)建軟件缺陷預測模型的方法和性能評價。在度量元設計方面,王丹丹等[2]提出用兩種演化度量元來度量已有類的演化,驗證了演化度量元對缺陷預測性能的改進。于巧[3]從代碼包的缺陷率和類的變更程度兩方面提出了兩個演化度量元,并分析了代碼度量元和演化度量元與類別的相關(guān)性,結(jié)果表明演化度量元與類別的相關(guān)性更高。在軟件缺陷預測模型的構(gòu)建方面,經(jīng)典的方法主要有:貝葉斯[4]、決策樹[5]、邏輯回歸[6]、支持向量機[7]、神經(jīng)網(wǎng)絡[8~10]等方法。原子等[11]以代碼(語句級)變更作為預測粒度,采用特征熵差值矩陣分析了軟件演化過程中概念漂移問題的特點,提出一種伴隨概念回顧的動態(tài)窗口學習機制來實現(xiàn)長時間的穩(wěn)定預測。機器學習方法遵循誤差最小化原則,當訓練數(shù)據(jù)不平衡時,其分類會偏向多數(shù)類,導致模型的分類性能較差[12],不能有效發(fā)揮所加入的演化度量元的性能。
針對以上問題,本文用集成學習的方法進行軟件缺陷預測研究[13~17],構(gòu)建了一種面向代碼演化的集成軟件缺陷預測模型,在代碼演化的預測技術(shù)上加入集成學習方法,將機器學習模型形成的弱分類器進行Adaboost集成,通過各種模型迭代產(chǎn)生強分類器,從而提高缺陷預測模型的性能。
軟件缺陷數(shù)據(jù)度量元是與缺陷外在表現(xiàn)有關(guān)系的內(nèi)在屬性(比如復雜度、耦合、繼承等)[1]?,F(xiàn)有的度量主要基于代碼度量元(code metrics,CM),有代碼行數(shù)、McCabe環(huán)路復雜度、Halstead科學度量以及CK度量元等。其中,CK度量元是面向?qū)ο蟪绦蛟O計的度量元,主要從繼承、耦合、內(nèi)聚等角度描述程序的復雜性。由于近年來面向?qū)ο蟪绦蛟O計成為開發(fā)的主流,不同數(shù)據(jù)集包含的特征屬于類級別,因此本文選擇CK度量元作為預測的屬性(表1)。
表1 CK度量元Table 1 CK metrics
演化度量元(evolution metrics,EM)是用來刻畫軟件演化過程的度量元,包括不同版本中類的變化以及代碼變更度量元等。
本文使用類存在缺陷的概率(probability of defective classes,pdc)和發(fā)生變化的代碼度量元比例(percentage of changed code metrics,pccm)兩個演化度量元[3]進行缺陷預測。pdc定義如下
其中,Nd為某個代碼版本中缺陷類的個數(shù),Na為該代碼版本中所有類的個數(shù)。
pccm定義如下
其中,Cc表示與前一個版本相比,當前版本的每個類中發(fā)生變化的代碼度量元;Cm為該版本每個類中所有代碼度量元。演化信息能直觀地反映軟件在不同版本的演化程度。因此,將代碼度量元與演化度量元進行結(jié)合分析,能有效提高軟件預測模型的性能。
選擇使用哪些版本的缺陷數(shù)據(jù)進行預測是面向代碼演化的缺陷預測技術(shù)的重點。常見的方法包括使用所有的歷史版本的缺陷數(shù)據(jù)來預測下一個版本的缺陷(即{V1,V2,…,Vn-1}→Vn)和使用前一個版本的缺陷數(shù)據(jù)來預測下一個版本的缺陷(即Vn-1→Vn)。王丹丹等[2]與Ekanayake等[18]發(fā)現(xiàn)使用時間鄰近的實例比時間相距較遠的實例具有更好的預測性能。于巧[3]使用至少3個版本的數(shù)據(jù),依次提取相鄰兩個版本的共同類與演化度量元從而得到訓練集與測試集。然而該方法對相鄰版本的缺陷率穩(wěn)定程度較為依賴,當相鄰版本缺陷率相對穩(wěn)定時,加入的演化度量元具有較好的預測性能,否則預測性能不如代碼度量元?;谝陨涎芯?,本文使用前一個版本的缺陷數(shù)據(jù)來預測下一個版本的缺陷(即Vn-1→Vn)。
樸素貝葉斯(NB)、決策樹(J48)、邏輯回歸(LR)是最常用的缺陷預測方法。相關(guān)研究[19]表明邏輯回歸與樸素貝葉斯模型是缺陷預測中使用最廣泛的兩種對比標準。Seliya等人[20]發(fā)現(xiàn)J48決策樹方法在缺陷預測中有較好的性能。隨著神經(jīng)網(wǎng)絡的發(fā)展,復雜的網(wǎng)絡模型逐漸應用在缺陷預測方面,由于其具有自學習與自適應性等特點,雖然預測花費的時間較長,但在各項評價指標上均能達到較高水平?;谝陨涎芯?,本文選擇的弱分類器是決策樹(J48)、邏輯回歸(LR)、神經(jīng)網(wǎng)絡(NN)、樸素貝葉斯(NB)。
本文構(gòu)建了一種面向代碼演化的集成軟件缺陷預測模型,在代碼演化的預測技術(shù)上加入集成學習方法,基本框架如圖1所示。首先對不同版本代碼進行預處理,即選擇合適的代碼度量元和演化度量元,提取公共類以及數(shù)據(jù)采樣等。然后使用集成方法迭代增強前一個分類誤差率較小的弱分類器的權(quán)重,減小分類誤差率較大的弱分類器的權(quán)重,再將加權(quán)后的樣本重新訓練,當誤差達到設定的閾值時結(jié)束訓練,將不同分類器按照各自的權(quán)重集成得到最終分類器。
圖1 本文基本框架Fig.1 Basic framework of this paper
常見的集成學習方法包括Bagging,Boosting,Stacking等。Bagging是并行式的集成學習方法,主要思想為使用有放回重采樣法,采樣出T個含有n個訓練集的采樣集后,基于每個采樣集訓練出弱分類器,通過不同的結(jié)合策略獲得強學習器。其主要優(yōu)點是易于并行計算,降低弱分類器方差,改善泛化誤差,但比較依賴弱分類器的穩(wěn)定性。Boosting是串行集成的方法,它是一個迭代的過程,用于自適應地改變訓練樣本的分布,使得弱分類器更關(guān)注易錯分的樣本。其主要優(yōu)點是學習速率快,而且能夠有效地利用弱學習器來構(gòu)建強學習器。Stacking是一種融合各類模型的方法,主要使用基礎(chǔ)模型進行完整的數(shù)據(jù)集訓練,然后使用元模型基于基礎(chǔ)模型的輸出進行訓練,能融合多個模型的優(yōu)點來提升集成模型的性能。Boosting比Bagging更激進,更容易受噪聲影響過擬合,不易并行,Stacking多用于最終綜合多個性能較好的模型,最易于過擬合。通常情況下,Boosting和Bagging考慮同質(zhì)弱分類器,而Stacking考慮的是異質(zhì)弱分類器。
本文采用Boosting中的Adaboost方法,對不同機器學習模型各自進行迭代,不停地調(diào)整權(quán)重讓其更關(guān)注上一輪的錯分元組。主要過程是以m個分類器為核心,學習獲取一個錯誤分類誤差最小的分類器ft(x)以及其組合權(quán)重αt,綜合T次Adaboost過程,遵循權(quán)重值集成所得到最終分類器,實現(xiàn)缺陷預測。
本文中預測模型訓練后最終得到一個分類器,對未來版本的代碼進行缺陷預測,其目標函數(shù)
其中,T為Adaboost過程的次數(shù),ft(x)是第t次Adaboost過程得到的弱分類器,αt是與弱分類器ft(x)對應的權(quán)重值。最終經(jīng)過T次Adaboost后,最后得到基于T個弱分類器按照各自的權(quán)重集成的分類器。
集成學習方法的核心是訓練弱分類器,即T次Adaboost。訓練階段采用多核集成方法[21],即為每個單核函數(shù)訓練得到一個單核分類器,由m個核函數(shù)得到m個單核分類器,然后根據(jù)分類效果從中選出性能最好的作為本次Adaboost過程的弱分類器。其中可以根據(jù)m個分類器的未正確分類的誤差率ρt來進行比較和選擇。記為第j個(1≤j≤m)核函數(shù)的分類器,則其誤差率定義如下:
其中,Dt為訓練樣本集的權(quán)重向量,yi為軟件模塊的標記信息,分類誤差越小表明分類器分類效果越好,從中選擇分類誤差率最小的作為第t次Adaboost過程的弱分類器。弱分類器ft(x)的權(quán)重αt與未正確分類誤差率ρt關(guān)系為:
在上一節(jié)得到了第t次Adaboost過程完成后的弱分類器ft(x)及它的權(quán)重值αt,在進行t+1次Adaboost過程之前,需要更新訓練集的權(quán)重向量Dt+1,目的是更多地關(guān)注有缺陷樣本。在更新訓練樣本集的權(quán)重向量時,可以采用如下策略:
如果訓練樣本為有缺陷樣本,即yi=1,則
如果訓練樣本為無缺陷樣本,即yi=-1,則
上述策略綜合了模塊有無缺陷屬性和第t次Adaboost過程的分類結(jié)果。正確或者錯誤分類有缺陷樣本時,權(quán)重分別是不變或增加,這樣使下一次Adaboost過程中關(guān)注有缺陷樣本,尤其是上一次分類中錯誤的元組。正確或者錯誤分類無缺陷樣本時,權(quán)重分別是減少或不變,為了減少正確分類無缺陷樣本的權(quán)重,從而更關(guān)注有缺陷樣本的分類情況,降低誤報率。
本文旨在通過實驗回答以下3個問題:
問題1:不同機器學習模型集成前后的預測性能如何?
問題2:演化度量元對預測性能的影響如何?
問題3:不同集成方法對預測性能的影響如何?
針對以上問題,本節(jié)將在PROMISE上對不同機器學習的集成模型預測性能進行驗證。本文選擇了4種常用的分類預測模型決策樹(J48)、邏輯回歸(LR)、神經(jīng)網(wǎng)絡(NN)、樸素貝葉斯(NB)進行實驗。不同機器學習模型在不同數(shù)據(jù)集以及集成方法上表現(xiàn)差異較大,因此本文選擇的模型與集成方法在其他數(shù)據(jù)集不一定是最好的。本文側(cè)重點在于針對演化項目的預測技術(shù)進行集成后的改進,其中選擇的預測模型與演化度量元是為了驗證集成后的性能,期望找到更優(yōu)的集成方法。
為驗證本文構(gòu)建模型的有效性,選取PROMISE軟件數(shù)據(jù)集中的5種,均為缺陷預測中常用的開源數(shù)據(jù)集,基本信息如表2所示。其中每個項目至少包含3個版本和20個代碼特征和標注,均使用Java語言開發(fā),其缺陷預測的粒度為類,缺陷率為缺陷模塊數(shù)占所有模塊數(shù)的比率。
表2 實驗數(shù)據(jù)集Table 2 Experimental data set
預處理能有效提高缺陷預測性能。因此對以上數(shù)據(jù)集提取公共類,進行數(shù)據(jù)采樣等操作。
1)提取公共類
版本演化過程中,可能發(fā)生新增類、移除類等產(chǎn)生類的變化,導致相鄰版本之間的演化沒有可比性,因此需要提取兩者的共同類,再提取相關(guān)代碼變更等演化數(shù)據(jù)。
2)抽樣方法
由于缺陷分布通常符合2-8規(guī)律,即80%的缺陷分布在20%的模塊中,反映了類的不平衡性。因此需要對訓練數(shù)據(jù)進行重采樣以降低其影響。實驗表明[22],欠抽樣能有效提高缺陷預測模型的性能。在初始訓練集時本文使用欠抽樣方法,即有放回地隨機抽取與缺陷模塊數(shù)量相同的模塊,將其作為訓練集。
3)度量元選取
不同度量元之間存在一定的相關(guān)性,例如rfc與wmc均可以表示類中所涉及的方法數(shù),具有較強的相關(guān)性。為了減小度量元之間的相關(guān)性帶來的影響,因此需要對代碼度量元以及演化度量元進行篩選。CFS(correlation-based feature selection)屬性選擇算法[23]能評估每個特征的獨立預測能力以及與其他特征的相關(guān)性,挑選出與缺陷具有較高相關(guān)性但是相互之間相關(guān)性較低的特征屬性,并結(jié)合最佳優(yōu)先搜索算法(Best-First Search)選取最優(yōu)的特征子集。表3即為使用CFS選擇出的度量元,例如在數(shù)據(jù)集Ant-1.3中選擇ce、moa和pccm3個度量元來預測Ant-1.4版本中的缺陷。從表3中可看出選取次數(shù)較多的度量元為rfc、lcom3、ce、pdc和pccm,表明以上度量元與缺陷的關(guān)聯(lián)較強。
表3 不同數(shù)據(jù)集的度量元選擇Table 3 Metric selection of differ ent data sets
軟件缺陷預測是對軟件模塊是否存在缺陷進行預測,本質(zhì)是一個二分類問題,所以采用常見的評價指標:查準率(P),召回率(R),F(xiàn)1和AUC。查準率是預測為有缺陷的模塊數(shù)量中實際有缺陷模塊數(shù)量所占的比例
召回率是實際有缺陷的模塊數(shù)量中預測為有缺陷模塊數(shù)量所占的比例
以上兩式中TP、FP和FN的定義如表4。F1是一個綜合評價指標,是對召回率和查準率之間的權(quán)衡,具體公式如下
AUC范圍在[0,1],一般情況下數(shù)值越大,表明該缺陷預測模型性能越好。
預測結(jié)果用混淆矩陣表示,如表4。
表4 混淆矩陣Table 4 Confusion matrix
3.4.1 不同機器學習模型集成前后的預測性能分析
表5中數(shù)據(jù)集表示使用前一個版本的缺陷數(shù)據(jù)來預測下一個版本缺陷(即Vn-1→Vn),J48、LR、NN和NB分別為基于單一分類器的實驗。在數(shù)據(jù)集方面,可以看到Jedit數(shù)據(jù)集比Ant數(shù)據(jù)集預測結(jié)果均值高,可能是由于Jedit數(shù)據(jù)集缺陷率較高,以及選擇的度量元可能與缺陷的聯(lián)系更緊密,所以更容易預測出缺陷。
在精確率方面,LR模型占有優(yōu)勢;在召回率和F1上,NN占有很大的優(yōu)勢,這可能是由于神經(jīng)網(wǎng)絡在預測方面相較于其他機器學習模型更靈活,能構(gòu)建多層模型來優(yōu)化結(jié)果。J48模型此時的綜合指標一般。
表6為4種機器學習模型集成前后結(jié)果對比,其中J48*、LR*、NN*、NB*分別表示Adaboost模型基于各弱分類器的集成,J48、LR、NN、NB均為基于單一分類器的實驗,每個弱分類器迭代20次。從表6可以看出,4種模型集成后比集成前各評價指標都提升了,其中J48*的提升幅度較大,AUC提升率達51.7%,各項評價指標均是最高的。但J48*模型在集成之前(表5),與其他模型相比表現(xiàn)并不突出,這是因為其弱分類器容易將存在缺陷的模塊錯分為無缺陷模塊,而Adaboost集成對權(quán)重進行了加強訓練,J48*在AUC指標上比LR*、NN*、NB*平均高出7.7%、4.6%、8.0%。
表5 4種機器學習模型的部分預測結(jié)果Table 5 Partial prediction results of four machine learning models
表6 4種機器學習算法集成前后對比Table 6 Comparison of four machine lear ning algorithms before and after integration
因此可以認為,本文提出的集成模型在一定程度上提高了各項評價指標,比單一的機器學習模型有一定的優(yōu)勢。
3.4.2 演化度量元對預測性能的影響分析
為驗證演化度量元(EM)對預測模型性能的影響,設計兩組實驗進行對比,一組僅用代碼度量元(CM),另一組使用代碼度量元與演化度量元(CM+EM),選擇AUC進行對比,實驗結(jié)果如表7所示。
從表7可以看出,J48*和NB*加入了EM后,絕大多數(shù)情況下AUC要優(yōu)于未加入的。在數(shù)據(jù)集Jedit-4.2→Jedit-4.3上,加入了EM后的AUC不如未加入的高,這是因為Jedit-4.2和Jedit-4.3缺陷率分別分13.1%、2.2%,導致Jedit-4.2→Jedit-4.3版本間缺陷率變化較明顯,加入pdc度量元不能有效使用前一個版本中類的缺陷率來度量當前版本中類存在缺陷的概率。Jedit-4.2→Jedit-4.3版本間發(fā)生變化的代碼度量元比例較大而缺陷率減少,因此加入的pccm度量元會產(chǎn)生一些誤報,所以4種模型在該版本演化過程中CM+EM性能不如CM。
表7 演化度量元對4種預測模型AUC的影響Table 7 The influence of evolution metric on the AUC of four prediction models
因此可以認為,預測時加入演化度量元能在一定程度上提高模型性能。針對代碼演化較穩(wěn)定的版本,即沒有較多新增類與刪除類,該情況下加入演化度量元預測性能提升明顯。針對代碼演化不穩(wěn)定的版本,可僅利用代碼度量元進行缺陷預測,此時預測效率更高。
3.4.3 不同集成方法對預測性能影響
本小節(jié)用集成學習方法Bagging和Stacking與本文選擇的Adaboost方法比較。從上面的結(jié)果來看,J48*的性能相比其他3種總體上好些,因此,Adaboost選擇基于J48進行20次Adaboost過程后的模型。Bagging方法中NN模型是集成后效率最高的,因此Bagging選擇基于NN進行20次Bagging過程后的模型。由于Stacking方法是由兩種不同的基礎(chǔ)分類器構(gòu)成,我們對比不同組合模型發(fā)現(xiàn)J48+NN比J48+NB性能略微高出一些,但NN模型花費時間較多,因此Stacking方法選擇J48+NB模型。表8為這3種集成學習方法的F1和AUC結(jié)果。
表8 3種集成學習方法的F1和AUCTable 8 The AUC and F1 of three ensemble learning methods
從表8中可以看出雖然不同集成方法之間的F1和AUC值之間性能差距較小,在1%以內(nèi),但Adaboost在多數(shù)情況下還是比其他方法高一點,這可能是Adaboost方法與J48作為基分類器的契合度更高,能有效改善J48在錯分缺陷模塊的情況,提高召回率從而達到提升整體的模型性能。
3.4.4 與其他方法對比
本文在演化項目上進行預測,因此選擇文獻[2]與文獻[3]的方法進行對比。文獻[2]使用代碼度量元、演化模式相關(guān)度量元和代碼變更度量元等數(shù)據(jù),選擇NB、J48、隨機森林(RF)和二元邏輯回歸(BLR)等預測方法進行分析。文獻[3]在代碼度量元中加入演化度量元(pdc,pccm),選擇KNN、LR、NB等方法進行預測。本文在文獻[2]基礎(chǔ)上構(gòu)建集成模型進行預測,由3.4.3節(jié)實驗可知J48*性能最好,因此表9中僅列出J48*與文獻[2,3]比較結(jié)果。
從表9可以看出,本文集成后的模型的F1和AUC大于其他兩種預測方法,這是因為本文模型通過了多輪的訓練并調(diào)整分類器權(quán)重,而在精確率或召回率等方面不同方法均有優(yōu)勢,這一方面是由于基分類器不同性能不同,另一方面是因為代碼演化穩(wěn)定性不同。代碼過于穩(wěn)定,可能產(chǎn)生過擬合。
表9 與其他文獻預測方法性能對比Table 9 Performance comparison with other literature prediction methods
各文獻選擇的模型不一致,因此根據(jù)不同情況選擇對應的模型會更有效。本文方法在面向演化項目的缺陷預測技術(shù)上進行集成模型測試,總體性能有一定提升,然而在部分數(shù)據(jù)集以及模型上提升不明顯,因此需要針對不同情況選擇合適的方法。
本節(jié)從以下三個方面來分析影響實驗結(jié)果的因素:
1)構(gòu)建因素,在構(gòu)建方面本文選取的模型為J48、LR、NB、NN,每個模型均有優(yōu)勢,因此集成方法采用的模型均不同。Adaboost對LR與NB的提升并不大,這是由于其弱分類器的效果較差或者精度與召回率相差較大從而導致模型整體性能不佳,而Stacking能將LR或者NB的一些優(yōu)點發(fā)揮出來,通過基礎(chǔ)模型或者元模型來彌補其缺點。Bagging由于其并行的優(yōu)勢選擇NN模型。因此不同模型對預測性能影響較大,而針對其他機器學習模型的性能還需進一步的研究。
2)內(nèi)部因素,模型中不同參數(shù)可能對實驗結(jié)果產(chǎn)生一定影響。Adaboost次數(shù)、閾值設定、權(quán)重所占比例以及權(quán)重向量策略對模型的分類有直接影響。例如Adaboost次數(shù)為20,比次數(shù)為10的模型性能有較大提升,而30次與20次的性能差異不明顯,因此最終選擇Adaboost次數(shù)為20。當設定的誤差率閾值較大時,則很容易達到閾值從而過早地結(jié)束訓練階段,當設定的誤差率閾值較小時,訓練階段過長從而導致過擬合。
3)外部因素,數(shù)據(jù)集的質(zhì)量、代碼度量元選取、代碼版本的演化等都會影響實驗的結(jié)果。本文選取的PROMISE數(shù)據(jù)集均是缺陷演化中的典型數(shù)據(jù)集,且至少含有3個演化版本。Ant-1.4→Ant-1.5和Jedit-4.2→Jedit-4.3版本間缺陷率變化較明顯,通過上一個版本有缺陷模塊與演化度量元預測下一個版本的代碼缺陷存在許多誤報,影響模型的性能。在Ant-1.5、Ant-1.6、Ant-1.7 3個版本間,演化過程中各個包中共同類的缺陷比較相似,所以預測時能有效找出缺陷。在代碼度量元方面,不同版本數(shù)據(jù)集選取的度量元均不一樣,例如Ant-1.4中僅選取輸入3個度量元來進行下版本的缺陷預測,而在Ant-1.6中選取了包含以上3個度量元在內(nèi)的10個度量元,所以選取合適的度量元對預測模型的性能也有較大影響。
本文針對面向代碼演化項目中機器學習模型對預測模型性能的影響問題進行了研究,以代碼演化為切入點,基于4種機器學習模型構(gòu)建各自的集成模型進行缺陷預測。首先對不同版本的代碼進行預處理,選出合適的代碼度量元及演化度量元作為模型的輸入,再將J48、LR、NB、NN模型通過Adaboost集成構(gòu)建缺陷預測模型,最后在PROMISE中的5種實驗數(shù)據(jù)集上進行實驗并與其他集成方法和面向演化項目的缺陷預測技術(shù)進行對比,得出如下結(jié)論:
1)4種不同弱分類器中基于Adaboost集成后的模型比對應的單一弱分類器性能提升幅度最大;
2)預測時加入演化度量元能有效提高模型的性能,但受數(shù)據(jù)集的影響較大,代碼演化越穩(wěn)定,則性能提升越明顯;
3)相較于文獻[2,3]中的方法,本文所用的Adaboost基于J48模型集成在F1和AUC上有一定優(yōu)勢。
本文方法在整體性能上優(yōu)于其他面向演化項目的預測技術(shù)。在后續(xù)的研究工作中,針對更多的基分類器或者不同基分類器之間進行組合,以覆蓋更多的集成方法進行預測。