Odena A , Goodfellow I . TensorFuzz: Debugging Neural Networks with Coverage-Guided Fuzzing[J]. arXiv, 2018.
摘要神經網路是很難去解釋與除錯的。本文介紹了神經網路的測試技術,它能夠發現在一些特有輸入時出現的錯誤。特別的是,我們開發了神經網路的覆蓋導向模糊的方法(CGF)。在 CGF 中,輸入的隨機突變被一個覆蓋度引導到滿足使用者的指定約束的目標。本文還描述了近似最近鄰搜尋演算法(ANN)如何為神經網路提供這種覆蓋度量。我們接下來將這些方法與基於屬性的測試技術(PBT)結合起來。在 PBT 中,一個斷言函式應該滿足其功能,然後系統自動生成並執行這些功能測試。我們還將這個系統應用與實際的目標,包括(但不限於)在現在流行的 GitHub 儲存庫中顯示損壞的丟失的功能,然後改善 TensorFlow 的效能。最後,我們釋出了一個名為 TensroFuzz 的開源庫,它描述並實現了上述技術。
1 介紹問題來源:神經網路的除錯十分困難。例如,對於 Reluplex,它透過將 ReLU 網路的描述分析為分段的線性函式,使用矩陣乘法操作理論模型來工作,但在實踐中,由於浮點的存在,計算機上的矩陣乘法並不是線性的,機器學習演算法利用這一特性來執行顯著的非線性計算,這是存在矛盾的。也導致有關它們即便是相對簡單的問題,神經網路的實現結果都很有可能偏離理論模型。同時,它的計算成本太高,並且無法按實際使用的模型的尺寸進行放縮。
本文從傳統的軟體測試技術——覆蓋導向模糊入手,來測試神經網路。並且,本文將這項技術與基於屬性的測試結合起來,將最後產生的系統用於測試各種各樣的神經網路測試問題。具體的說,本文做出了一下貢獻:
•
首先,本文介紹了神經網路的覆蓋導向模糊的概念,並描述了近似最近鄰搜尋演算法是如何以一個一般的方法來檢測覆蓋率的。
•
其次,本文描述瞭如何將基於屬性的測試技術將覆蓋導向模糊技術結合到一個完整的系統當中,對於這個系統,它在我們想要測試的各種程式的神經網路當中,表現的開箱即用的效能相當好。
•
第三,本文開源了一個名為 TensorFuzz 的軟禁庫來實現這些想法。
•
最後,本文證明了 TensorFuzz 在神經網路的訓練當中發現的數值錯誤和它們的量子化版本的分歧,並將暴露出的丟失功能在 GitHub 上釋出,還對 TensorFlow 進行效能改進。
2 相關工作1.
Pei 等人以一個直線單元(ReLUs)作為啟用函式的神經網路為基礎引入了神經元覆蓋的度量。
2.
Ma 等人以兩種方式概括了神經元網路。
3.
Sun 等人引入了一組由修改條件/決策覆蓋率激發的度量標準。
4.
Tian 等人將神經元覆蓋率指標應用於深度神經網路。(自動駕駛汽車的一部分)
5.
Wicker 等人使用影象特定操作對影象分類器進行黑河測試。
6.
Sun 等人認為神經元覆蓋度量太容易滿足,因此自身重新定義指標改善神經元的覆蓋。
3 TensorFuzz 概述作者從 fuzzers 的基本屬性的測試概念中獲得靈感,實現了 TensorFuzz——一個更適用於神經網路測試的工具。它透過計算圖的“啟用度”來度量它的覆蓋率。
其中核心的工作部件為模糊器,它主要負責影象的模糊化過程。其中,模糊化過程的整體結構非常類似於計算機程式的覆蓋制導模糊器的結構。主要區別在於,TensorFuzz 是與 TensorFlow 圖形互動,而不是與檢測到的任意計算機程式互動,並且,TensorFuzz 還可以向 TensorFlow 圖形饋送輸入並從中獲取輸出。
與傳統的 CGF 不同,TensorFuzz 不僅僅是輸入大的位元組陣列,TensorFuzz 輸入限制為在某種意義上是有效的神經網路輸入。如果輸入是影象,則 TensorFuzz 將輸入限制為具有正確的大小和形狀,並且與所考慮的資料集的輸入畫素處於相同的間隔內。如果輸入是字元序列,TensorFuzz 只允許從訓練集中提取的詞彙中的字元。
對於給定的種子語料庫,模糊化按如下方式進行:在指示停止之前,模糊器根據我們的需要將輸入選擇器的某個元件從輸入語料庫中選擇出來。給定輸入後,賦值器元件將對該輸入執行某種修改。修改可以像翻轉影象中輸入畫素的符號一樣簡單,也可以被限制為遵循對語料庫元素隨時間進行的某種約束。最後,突變的輸入可以饋送到神經網路。
在 TensorFuzz 中,從神經網路中可以提取出兩個資訊:
1.
覆蓋的陣列集合,計算實際覆蓋率
2.
元資料陣列集合,目標函式計算出來的結果
一旦覆蓋率計算出來,如果產生了新覆蓋,則把變異後的輸入加入到輸入集合中;如果滿足了目標函式,則把輸入加入到測試用例中。
圖一:模糊過程:表示資料流動 演算法虛擬碼
4 TensorFuzz 的詳細資訊輸入選擇器:在任何給定的時間,模糊器必須從現有的語料庫中選擇要突變的輸入資料。最優你選擇是依賴於問題本身的輸入,傳統的 CGFs 依賴於各種啟發式的方法來做出決定,這對於我們要測試的成像來說,進行統一的隨機選擇當然很好,但是它的缺點就是有時它會很慢。
突變器:一旦輸入選擇器選擇了語料庫中要突變的元素,這個突變就必須要被應用。在 TensorFuzz 中,本文實現了對浮點數的任意密集向量和專門用於對影象輸入的突變進行突變作用的突變函式——因為深度神經網路的一個常見用例是在影象分類當中的。對於影象輸入,本文實現了兩種不同型別的突變:
1.
在輸入中新增使用者可配置方差的白噪聲。
2.
新增限制突變原始和原始原始之間差異的白噪聲。
目標函式:一般情況下,TensrFuzz 會帶著目標執行模糊器。因為我們會想要神經網路達到某種特定的狀態,這種狀態可能在我們看來是錯誤的。目標函式用於評估該處理過程是否達到了某種狀態,在 CGF 中,目標是要找到導致程式奔潰的輸入。由於我們對 PBT 進行分析,我們允許任意使用者定義的目標。當變化的輸入被輸入到計算圖當中,覆蓋率陣列和原資料陣列都作為輸出返回。目標函式應用於元資料陣列,並標記能夠滿足目標的輸入。透過這種方式,目標函式將對要測試的屬性進行斷言,而模糊器的作用就是來發現對該屬性的入侵。
覆蓋分析器:覆蓋分析器負責從 TensorFlow 執行時讀取陣列,並將他們轉換成表示覆蓋率的 Python 物件,並檢查覆蓋率是否為新的。對於覆蓋器,我們希望它的速度快,並且希望它對於所有的覆蓋面都有一定的限制。希望快是因為這樣能夠幫助快速找到不當行為。希望對覆蓋面有限制是因為如果每個新的輸入產生覆蓋範圍的話,那麼我們只是在初始語料庫元素上執行隨機突變,並不能有效的獲取新的覆蓋面。對於這些問題,常用的方法是蠻力發,即讀出整個啟用向量,並將星的啟用向量視為新的覆蓋。然而,本文提出的更好的方法是檢測有關啟用向量是否接近之前觀察到的那個。而實現這個目標的方法是使用近似最近鄰搜尋演算法(ANN)。我們只需要知道是否存在一個具備影響條件的鄰居,這意味著我們不需要儲存所以的語料庫元素。現今已有一些方法(一些特殊的資料結構,如 Bloom 過濾器)可以精確的支援這種鄰進查詢,並且這種方法由於元素的儲存方式的原因,不用特別擔心元素儲存空間的瓶頸。但是本文表示現在還沒有找到一個可用的開源實現,所以這一步可以作為未來研究的方向。
5 實驗結果在訓練好的神經網路中,TensorFuzz 可以有效的發現數組誤差。 作者用了一些不安全的 32 位浮點數資料陣列訓練了一個 MNIST 分類器。他們將所有權值和啟用截斷為 16 位。然後透過比較 32 位模型和 16 位模型在 MNIST 測試機上的預測,得到了兩者沒有分歧的結論。
此外,作者還對訓練好的 MNIST 分類器使用 TensorFlow 截斷,截斷為 16 位浮點數。其中,原始圖和截斷圖對 MNIST 測試集的所有 10000 個元素都做出了相同的預測,但是 fuzzer 能夠在試探模糊的測試影象的 70%左右半徑為 0.4 的圓球內發生分歧。
6 結論本文介紹了神經網路的覆蓋導向模糊方法,並描述瞭如何在這種情況下建立一個有用的覆蓋檢查器。並且,本文已經找到了陣列錯誤,以及神經網路與其量化版本之間的分歧,並且在 GitHub 上顯示了該損壞的丟失函式,最後還對 TensorFlow 的效能進行了改進,證明了 TensorFlow 的實用價值。作者還發布了一個開源庫,以便其他研究人員可以在此基礎上進行開發,從業者也可以使用它來測試他們的機器學習的程式碼。