當前位置:
首頁 > 最新 > AI賦能DevOps:基於TensorFlow的端到端軟體缺陷預測

AI賦能DevOps:基於TensorFlow的端到端軟體缺陷預測

1. 什麼是軟體缺陷預測?

軟體缺陷預測(software bug/defect prediction),致力於根據源代碼(source code)的靜態特徵來自動地預測某個軟體模塊是否有缺陷,從而幫助我們識別軟體系統中有質量風險的部分。

據統計,在軟體系統中,通常來說,大部分的缺陷是由小部分的模塊造成的。通過軟體缺陷預測,可以及時甄別此類模塊,有助於更好地分配軟體測試資源和提高軟體測試效率。另外,在甄別的基礎之上,通過重新設計和實現系統中的高風險模塊,可以促使系統得到進一步完善。

隨著敏捷和DevOps的深入實踐,軟體工程的自動化程度越來越高。AI技術的快速普及,則為軟體工程從自動化向智能化演進提供了機遇。軟體缺陷預測,是有潛力在軟體工程領域落地的AI應用之一。

那麼,如何進行軟體缺陷預測呢?答案是使用機器學習技術。本質上,軟體缺陷預測是一個二元分類(binary classification)問題。有許多的機器學習演算法可以用於解決這類問題。例如邏輯回歸、樸素貝葉斯、KNN、K-means、決策樹、支持向量機、隨機森林、神經網路等。

為了進行軟體缺陷預測,我們既可以基於數學原理從頭開始實現這些演算法,也可以調取第三方庫來使用這些演算法。在本文中,我們採用另一種端到端的、自頂向下的方法。

2. 什麼是自頂向下的方法?

自頂向下(Top-down)的機器學習方法是由Jason Brownlee博士在https://machinelearningmastery.com/machine-learning-mastery-method/中提出的。傳統的機器學習方法是自底向上(down-top)的:先學習數學和理論,然後掌握演算法的實現方式,最後著手用演算法解決實際問題。

自頂向下的方法則反其道而行之:首先選擇流程(Process)和工具(Tool),然後在數據集上練習使用流程和工具,最後展示機器學習的結果。

自頂向下的方法目的性很強,關注的是如何以最短路徑獲得機器學習的收益,而不是過早陷入機器學習的演算法細節和數學原理。在這種方法論中,作者還提出了一種使用機器學習技術解決複雜實際問題的標準化的、端到端(end-to-end)的流程模板

這個模板的內容是:

定義問題(Problem)

準備數據

選擇、訓練、評價、改進演算法

展示結果(Results)

這裡,我們採用上述方法和流程,並使用開源工具TensorFlow,來解決我們面臨的軟體缺陷預測問題。

3. 什麼是TensorFlow?

TensoFlow是由Google Brain團隊開發的、基於數據流圖進行數值計算的開源機器學習框架。這個框架具有強大的功能和廣泛的適用性。一個經常為人稱道的優點是,其分散式執行引擎抽象了硬體的異構性,使得基於TensorFlow的機器學習程序既能部署在移動和邊緣計算設備上,也能部署在大規模的計算機集群上。

無論在學術界,還是在工業界,這幾年來TensorFlow都獲得了極大的關注,其流行程度和影響力與日俱增。今年的TensorFlow全球開發者峰會最近剛剛召開。峰會上發布了一些激動人心的TensorFlow最新功能,例如面向Javascript和Web應用的TensorFlow.js等。想了解更多的朋友,可以在這裡觀看峰會上的精彩視頻:https://www.tensorflow.org/dev-summit/。

4. 準備數據集

數據集是機器學習中非常重要的內容,其相當程度上決定了機器學習結果的好壞。我們使用的數據集來自於著名的美國NASA。作為航空航天領域的頂尖機構,NASA對軟體質量的要求是非常苛刻的。

NASA提供了一個面向學術界開放的軟體缺陷數據集倉庫。這個倉庫中有一些數據集,每個數據集是對NASA某個軟體項目的統計。具體來說,每個數據集包含一系列的樣本(記錄)。每條記錄表示的是軟體項目中某個軟體模塊的一些靜態特徵(feature),以及這個模塊是否有缺陷的標籤(label)。

這裡的靜態特徵是對模塊源代碼進行靜態分析和綜合的結果。具體來說,他們從軟體模塊的源代碼中提取了以下幾類特徵:

McCabe特徵集:這類特徵是以軟體工程專家T.J. McCabe的名字命名的。其核心思想是具有複雜路徑的代碼更傾向於有缺陷。在獲取McCabe特徵之前,首先需要構造代碼模塊的「流圖」(flowgraph)。在這個「流圖」的基礎上,可以衍生出一系列的特徵,反映軟體模塊的Cyclomatic複雜度、Essential複雜度和Design複雜度等。

Halstead特徵集:這類特徵以另一位軟體工程專家M.H. Halstead的名字命名。其核心思想是可讀性差的代碼更傾向於有缺陷。那麼,如何衡量代碼的可讀性呢?Halstead採用的辦法是統計代碼中的若干概念(例如操作數、唯一操作符等)的數量。

?

其他特徵集:除了上述兩種類型,還有其他一些常見的特徵也被提取,例如代碼的行數、注釋的行數、空白的行數等。

我們以這個數據集倉庫中的KC2數據集為例(下圖是數據量的一部分展示)。(http://promise.site.uottawa.ca/SERepository/datasets)。

這份數據集來自於NASA的一個C++項目,共有522個樣本。每個樣本由3個McCabe特徵,12個Halstead特徵,6個其他特徵,一共21個特徵和1個標記(用於表述樣本模塊是否有缺陷,0代表沒有缺陷,1代碼有缺陷)組成。在522個樣本中,沒有缺陷的樣本有415個,佔比79%;有缺陷的樣本有107個,佔比21%。

5. 使用TensorFlow進行軟體缺陷預測

TensorFlow為不同需求的開發者提供不同級別的機器學習介面(API)。估計器(estimator)是其高級別的介面。估計器為我們屏蔽了TensorFlow的底層細節,使我們以更快的速度完成機器學習程序的編程。

在這裡,我們使用估計器來編寫軟體缺陷預測的機器學習程序。那麼,估計器是什麼呢?估計器將機器學習中經常性的操作,例如訓練、評價、預測等進行了實現和封裝。我們只需要直接調用這些方法(輔以若干入參)就可以完成構造流圖、初始化變數、開始執行、處理異常等大量具體工作。

使用估計器進行開發有兩種選擇。一種是直接使用TensorFlow內置的估計器,另一種是定義和實現自己的估計器。我們採用前一種方法。

在TensorFlow中,使用估計器開發機器學習程序的一般過程如下:

創建一個或者多個輸入函數(Input Function)。

定義模型的特徵列(Feature Column)。

用特徵列和超參數(Hyper-parameter)等作為入參,實例化估計器,得到估計器對象(object)。

用輸入函數作為入參,調用估計器對象的若干方法(訓練、評價、預測等),完成機器學習工作。

5.1 創建一個或者多個輸入函數

要想調用估計器對象的方法,通常需要傳入數據集作為參數。在TensorFlow中,數據集是以「輸入函數」的形式作為參數傳入的。那麼,輸入函數是什麼樣的函數呢?

這個函數最主要的特點就是:其返回值是一個類型為tf.data.Dataset的對象(這種形式的數據集是估計器所期望的)。具體地說,這個對象是一個包含兩個元素的元組。其中第一個元素是特徵,第二個元素是標籤。特徵是一個Python字典。在這個字典中,每個key是特徵的名字,每個value是由該特徵的所有取值構成的數組。標籤則是一個由其所有取值構成的數組。

那麼,如何從原始的數據集構造出這樣的一個對象呢?TensorFlow提供了多種方法。這裡,我們使用tf.data.Dataset的API來實現這個目標。在我們的場景中,由於原始數據集是一個類似於CSV格式的文本文件,因此我們採用TensorFlow中的tf.data.TextLineDataset類從文件中讀取樣本,並且使用其map方法對樣本進行逐行處理,然後依次使用shuffle方法對數據集進行打亂、使用repeat方法對數據集進行重複化、使用batch方法將重複後的數據集進行分批。

這樣,我們就得到了一個經過處理的數據集(形式上是一個輸入函數)。之後,我們將使用這種數據集進行若干機器學習操作。

5.2 定義特徵列

特徵列用以描述模型應該如何使用來自上述特徵字典中的輸入數據。在實例化估計器模型時,我們需要傳入特徵列參數。在我們的場景中,一共有21個特徵。觀察數據集可知,每個特徵的取值都是數字的。因此,我們可以把每個特徵表示成一個32位的浮點數。在TensorFlow中,對應的類型是tf.feature_column.numeric_column(dtype=tf.float32)。構造特徵列的代碼如下:

5.3 實例化估計器

為了實例化估計器,我們需要做兩件事情:(1) 選擇估計器, (2) 確定實例化估計器需要的入參。

前面提到,TensorFlow中有一些內置的估計器。軟體缺陷分類本質上是一個二元分類問題。針對此類問題,有多個內置估計器可供選擇。這裡,我們使用TensorFlow中的深度神經網路(DNN)分類器,即tf.estimator.DNNClassifier(由tf.estimator派生而來)

確定了估計器類型,那麼我們需要傳入哪些參數來實例化這個估計器呢?這裡,有若干必選和可選的參數需要傳入。比如feature_columns參數是必填的特徵列,hidden_units參數是必填的神經網路隱含層的結構,n_classes參數是可選的分類的類型數量(默認是2),optimizer參數是可選的用於模型訓練的優化器(一個tf.Optimizer實例,默認是Adagrad優化器)等。

以下是構造估計器的代碼。注意到,構造估計器時不需要傳輸數據集。

5.4 訓練模型

在5.3中,我們得到了一個估計器對象。要訓練模型,我們只需要調用估計器對象的train方法即可。當然,重點仍然是傳入適當的參數。這裡,我們傳入5.1中構造的輸入函數(代表用於訓練的數據集),並且傳入1000作為訓練的迭代次數。

5.5 評價模型

在完成模型訓練之後,我們可以使用evaluate方法對得到的模型進行評價。

在train不同的是,這裡我們不需要傳入迭代次數,即只需要得到一次性估計的結果。另外,用於評價的數據集和用於訓練的數據集是獨立的,即用於評價的數據集不會參與到模型的訓練過程中,這可以確保模型的獨立性。具體來說,我們需要構造一個用於評價模型的數據集(輸入函數,eval_input_fn)。

倘若對評價結果不滿意,我們可以嘗試對模型進行各種各樣的改進。例如更換分類器的神經網路結構、激活函數、損耗函數等,調整學習速度、迭代次數、batch大小等超參數,甚至可以基於TensorFlow低級別API構造自己的估計器。這裡有大量的改進工作可以去做。

6. 總結

在本文,我們採用一種自頂向下的方法、並基於Google的TensorFlow框架,探討了軟體缺陷預測這一軟體工程實際問題的機器學習解決方案。必須承認的是,無論對問題的分析,還是對方案的設計,本文都是非常粗淺的。

我們注意到,AI在消費者領域已經有了非常廣泛的應用,但是在程序員身處的軟體工程領域,其應用仍然處於早期階段,有許多方向值得探索。感興趣的朋友可以關注這一領域的發展,本公眾號也會持續關注相關動向。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 自動化測試顧問 的精彩文章:

TAG:自動化測試顧問 |