范貴生,刁旭煬,虞慧群,陳麗瓊
(1.華東理工大學 計算機科學與工程系,上海 200237; 2.上海市計算機軟件評測重點實驗室,上海 201112;3.上海應用技術大學 計算機科學與信息工程系,上海 201418)
軟件缺陷產生于軟件開發過程中開發人員的錯誤編碼,含有缺陷的編碼在軟件運行過程中可能會產生意料之外的結果或行為,從而帶來不必要的企業經濟損失。在軟件項目開發的生命周期中,發現缺陷的時間越晚,帶來的風險和修復代價就越高。因此,在軟件部署上線之前必須進行軟件測試和代碼審查。然而目前保障軟件質量的常規方法往往不能及時檢查出缺陷,并且無法在有限的資源內對所有程序模塊進行審核。為了及時幫助開發和測試人員定位軟件中存在的缺陷,軟件缺陷預測成為當前軟件工程數據挖掘[1]領域的重點研究方向。軟件缺陷預測[2-3]是指挖掘軟件倉庫的歷史數據信息,如代碼復雜度、類型、變更記錄等,可設計缺陷相關的度量元并構建分類器來預測軟件中潛在的缺陷。
目前,大部分研究工作關注的是同一項目內的軟件缺陷預測[4](Within-Project Defect Prediction,WPDP),即利用項目內的歷史數據對新版本進行建模預測。但在實際的軟件開發過程中,對于新啟動的項目而言,通常沒有足夠多的訓練數據來建模訓練,而重新對新項目中的缺陷數據集進行標注,需要耗費大量的人力與物力資源。因此,一些研究人員開始關注跨項目軟件缺陷預測[4-5](Cross-Project Defect Prediction,CPDP),即利用其他項目(源項目)的歷史數據建立缺陷預測模型,然后對當前項目(目標項目)進行缺陷預測。然而,由于源項目和目標項目之間的數據分布存在較大差異,會導致直接利用源項目中的數據進行建模不能達到較好的預測性能,因此縮小源項目和目標項目數據集之間分布的差異性是跨項目軟件缺陷預測領域中的關鍵問題。此外,人工標注項目數據集的過程中容易產生噪聲數據,這將導致后續實例遷移的偏差。
針對實例存在噪聲和數據分布差異性的問題,本文從實例過濾和實例遷移的角度出發,提出一種兩階段跨項目缺陷預測方法CLNI-KMM。在實例過濾階段,借助CLNI[6]算法對訓練數據集中的每一個實例選取其附近的k個鄰居,計算與該實例標簽相反的鄰居占所有鄰居的比例,如果有一定數量的鄰居具有相反的標簽,則該實例被視為噪聲并被過濾。在實例遷移階段,借助KMM[7]算法,利用源項目和目標項目中的數據計算源項目所有實例的訓練權重,對與目標項目實例分布相近的實例賦予較高的權重。在此基礎上,利用目標項目集中已有的少量有標注數據,結合帶有權重的源項目訓練數據建立缺陷預測模型。
跨項目軟件缺陷預測采用其他項目(即源項目)的訓練數據集進行模型的建模,然后對當前目標項目進行缺陷預測。為解決不同數據源之間的分布差異性問題,遷移學習的相關方法被應用到了跨項目軟件缺陷預測領域中。TCA[8]是基于特征的經典遷移學習方法,采用TCA來從源項目中提取與目標項目相關的特征,從而減少源于和目標域的距離。在基于實例遷移方法中,NNfilter[9]過濾與目標項目集中的實例不夠接近的源項目中的實例,只保留每個目標項目實例中最接近的k個源項目實例鄰居。文獻[10]提出一種遷移樸素貝葉斯(TNB)的方法,首先通過調整源項目中的實例權重,削弱不相關實例的影響,然后將帶有權重的訓練實例放入樸素貝葉斯模型中進行訓練。文獻[11]提出了基于Box-Cox轉換的集成跨項目軟件缺陷預測方法。文獻[12]利用 Box-Cox、Log和Rank轉換對源項目進行多重變換,最終得到最接近于目標項目的訓練實例集。文獻[13]提出了一種基于度量元相似度的多源異構缺陷預測方法。研究表明,利用目標項目中少量的有標記數據能提升跨項目軟件缺陷預測模型的性能。
然而,無論是基于特征遷移的TCA、基于實例過濾的NNfilter,還是基于實例權重調整的TNB、基于特征變換的Box-Cox或相似度計算的多源異構,都要對源項目中的實例進行篩選、權重調整或特征變換。因此,實例標注的準確性會對后序的源項目實例遷移和缺陷模型的構建產生重大的影響。然而在挖掘軟件歷史倉庫時,對軟件程序模塊進行類型標注時可能產生噪聲,這些噪聲的存在會影響到實例遷移的效果。而上述研究工作并沒有對可能產生噪聲數據的源項目進行去噪處理,從而影響了跨項目缺陷預測模型的性能。
針對實例的噪聲和分布差異性問題,本文從實例過濾和實例遷移的角度出發,利用源項目的訓練數據集和目標項目中的少部分標注數據集建立缺陷預測模型,提出一種兩階段跨項目軟件缺陷預測方法CLNI-KMM。
如圖1所示,CLNI-KMM方法包含2個階段:實例過濾和實例遷移階段。在實例過濾階段,為去除源項目集中的噪聲數據,CLNI-KMM方法首先對源項目集中的每一個實例,選取最靠近它的k個鄰居。當這k個鄰居中與該實例標簽相反的個數達到一定數量時,則該實例被判定為噪聲數據,過濾所有的噪聲數據,最后得到去除噪聲后的源項目集。在實例遷移階段,為降低源項目集和目標項目集之間分布的差異性,采用KMM算法計算源項目實例與目標項目實例之間的相似度,為每個實例分配相應的訓練權重,提高與目標項目集相似的實例權重,降低與目標項目集差異大的實例權重,再結合目標項目集中少量的有標簽數據,建立缺陷預測模型,對新項目中的程序模塊進行缺陷預測。

圖1 CLNI-KMM軟件缺陷預測流程Fig.1 Procedure of software defect prediction of CLNI-KMM
人工采集標注的源項目數據集通常會因為標記錯誤導致后期預測模型的性能下降。如果能在建模之前找出這些噪聲并將其從實例中過濾,那么過濾后的數據將更有利于分類器建立準確的預測模型。根據文獻[6]研究可知,CLNI算法在不同的噪聲比例下都表現出了良好性能,使得預測模型的準確度得到提升。因此,本文采用了一種有效的錯誤標簽檢測方法CLNI來去除噪聲數據。對于每一個實例,選取距離該實例最近的k個鄰居。當有一定數量的鄰居和該實例的缺陷標注類型相反時,則認為該實例大概率是噪聲數據。
算法1CLNI實例過濾

輸出源項目中的噪聲實例集合A
初始化列表A,閾值δ、ε,鄰居個數k
1.For each iteration j:
7.End

θ=n/k*100%
9.If θ≥δ:
11.End
12.End
13.If |A)j∩Aj-1|/|Aj|≥ε:break
14.End
15.return Aj

在實例遷移階段,本文采用KMM實例遷移算法,目的是調整源項目中訓練樣本的權重,降低與目標項目分布差異較大的實例對缺陷預測模型的影響。與其他的實例遷移算法不同,KMM是一種非參數方法,不需要估計不同類別的概率分布。此外,該方法只要使用源項目和目標項目的實例集合就能求解出樣本的訓練權重,不需要使用類標簽信息。
通常,源項目和目標項目之間的分布差異性較大,因此,根據源項目的聯合概率分布Prs(x,y)和目標項目的聯合概率分布Prt(x,y)無法推斷出很好的估計量。因此,KMM假設源項目和目標項目的2個條件概率分布是相同的,即Prs(y|x))=Prt(y|x))。基于上述假設,以及Pr(x,y)=Pr(y|x))Pr(x),可以得出Prs(x,y)和Prt(x,y)只受Prs(x)和Prt(x)影響。因此,降低Prs(x,y)和Prt(x,y)的分布差異性可以轉化為降低Prs(x)和Prt(x)的邊緣分布的差異。

(1)

式(1)是一個有約束的二次規劃問題,可以被轉化為以下形式:
(2)

為評估CLNI-KMM方法,本文采集了15個Java開源項目作為實驗數據集,項目的靜態度量元特征和其對應代碼文件的缺陷標注數據集來源于Promise公開數據庫(https://github.com/klainfo/DefectData)。表1展示了這些項目的具體信息,包括項目名稱、項目版本、代碼文件數和缺陷率。此外,本實驗選取的20個靜態度量元特征都是由文獻[21]針對面向對象程序語言設計提取的,包括代碼行數、子類個數、公共方法的個數、樹的繼承深度以及相關代碼復雜度特征等。

表1 Java項目數據集信息Table 1 Dataset information of Java project
本實驗中,采用cvxopt,Scikit-learn(0.19.2)和Python3.6來構建缺陷預測模型。實驗運行環境是Ubuntu16.04服務器,配有3.60 GHz的因特爾i7處理器和8 GB內存。表1中的一些項目(jedit,elearn)的缺陷率很低,而有一些項目(log4j,xalan)則擁有很高的缺陷率,這表明Promise數據集存在類不平衡問題。為解決此問題,本文使用過采樣技術SMOTE[22]來合成少數類,從而使得兩類達到平衡。
本文采用2種評測指標,即F1值和準確率來評價缺陷預測模型的性能,其中F1值用來度量預測模型的穩定性,而準確率用來度量預測模型精確度。F1值是綜合考慮了查準率和召回率的度量方法。本文用c代表無缺陷的程序文件,用b代表有缺陷的程序文件。然后,定義以下3種情況:1)b→b代表將有缺陷的文件預測為有缺陷的;2)b→c表示將有缺陷的文件預測為無缺陷的;3)c→b則是將無缺陷的文件預測為有缺陷的。N代表了每種情況下的數量,比如Nb→b表示第一種情況的數量。最后定義軟件缺陷預測中的查準率、召回率、F1值和準確率,如式(3)~式(6)所示。
查準率:標記為有缺陷的文件被正確預測的數量在所有被預測為有缺陷的文件中的占比。
(3)
召回率:標記為有缺陷的文件被正確預測的數量在所有標記為有缺陷文件中的占比。
(4)
F1值:查準率和召回率的調和平均數。
(5)
Acc值:預測正確的文件數在總文件數中的占比。
(6)
此外,使用Friedman[23-25]檢驗來分析評價指標在統計上的顯著性。Friedman檢驗服從自由度為k-1的卡方分布,其原假設為多個方法間的效果不存在顯著的差異。如果發現檢驗結果的p值足夠的小(小于0.05),則認為原假設并不成立,即各個方法之間存在顯著性差異。進一步,采用Nemenyi[26]的后置檢驗來比較CLNI-KMM方法和其他經典的跨項目缺陷預測方法之間的差異。

為檢驗CLNI-KMM方法與其他3種經典CPDP方法之間的差異性,本文采用Friedman檢驗方法對各個方法的Acc值進行分析。由于共有5種方法,因此自由度k=4。如表2所示,檢驗結果的p值為8.77×10-8(遠小于0.05),反映了CLNI-KMM和其他經典CPDP方法之間的差異性。

表2 CLNI-KMM與4種CPDP方法之間的Friedman檢驗結果Table 2 Friedman test results of CLNI-KMM and four CPDP methods
表3展示了CLNI-KMM和其他4種CPDP方法之間的Nemenyi后置檢驗結果。實驗結果表明,CLNI-KMM方法與其他經典CPDP方法之間的顯著性差異主要體現在TCA和NNFilter中。

表3 CLNI-KMM與4種CPDP方法之間的Nemenyi檢驗結果Table 3 Nemenyi test results of CLNI-KMM and four CPDP methods
表4和表5分別列出了不同方法之間的Acc和F1值對比結果,其中粗數據表示最佳值。所有其他方法都與CLNI-KMM方法一樣,在訓練集中加入來自目標項目中的少量(5%)有標簽數據。

表4 CLNI-KMM與CPDP之間的Acc值比較Table 4 Comparison of Acc between CLNI-KMM and CPDP

表5 CLNI-KMM與CPDP之間的F1值比較Table 5 Comparison of F1 value between CLNI-KMM and CPDP
相較于TNB方法,CLNI-KMM方法在Acc和F1值的W/T/L上分別贏了11次和10次,這表明CLNI-KMM在模型在穩定性和預測準確性上都占有較大的優勢。相較于經典的TCA方法,CLNI-KMM方法在Acc的W/T/L上全部占優,而在F1值的W/T/L比較中與TCA持平。該結果表明CLNI-KMM的模型穩定性與TCA方法接近,而在模型的準確率上有較大的提升。從外,在Acc和F1值的W/T/L比較中,CLNI-KMM都比NNfilter方法表現得更為出色,分別贏了15次和11次,這都反映出了CLNI-KMM模型的優越預測性能。最后,根據Acc和F1-值的平均值來看,CLNI-KMM也比TNB、TCA以及NNfilter在Acc和F1值上分別提升了1.0,28.7,21.3和3.3,0.7,10.4個百分點。
基于上述分析,相較于經典的CPDP方法,CLNI-KMM通過同時考慮實例過濾和實例遷移,在使用CLNI算法過濾源項目噪聲的基礎之上,再運用KMM算法對實例進行遷移,提升了軟件缺陷預測模型的準確率和穩定性,達到更好的預測性能。
從外部有效性和內部有效性2個角度對本文方法進行有效性分析。外部有效性反映的是實驗研究得到的結論是否具有普遍性,本文采用Apache下開源的Java項目數據集,所有關于項目程序模塊的靜態度量元數據集能從Promise公開數據庫中獲得,因此,可以保證研究結論具有一定的代表性。內部有效性則反映實驗結果的正確性,本文編寫的代碼主要是基于Python的cvxopt模塊和Scikit-learn機器學習包,因此,可以最大程度上保證模型構建的正確性。在評估指標上,本文從模型的準確性和穩定性出發,采用Acc和F1值分別進行衡量,保證了評價指標的可靠性。
本文以跨項目軟件缺陷預測為研究背景,提出一種跨項目軟件缺陷預測方法CLNI-KMM,其中包含實例過濾和實例遷移2個階段。對源項目進行噪聲實例的過濾,保證源項目實例集的可靠性,并在實例遷移過程中為源項目的實例分配訓練權重,減少與目標項目不相關實例的負面影響。在此基礎上,結合目標項目集中少量的有標簽數據集建立缺陷預測模型,對新項目中的程序文件進行缺陷預測。基于實際項目數據集的實驗結果驗證了本文方法的有效性。后續將嘗試在實例遷移完成后,去除權重過低的實例,并驗證此步驟是否會提升預測性能,同時將利用更多實際項目的數據集進一步驗證本文方法的普適性。