詳解首個系統性測試現實深度學習系統的白箱框架DeepXplore

吳攀發表於2017-06-19
五月份,來自哥倫比亞大學和理海大學的幾位研究者的論文《DeepXplore: Automated Whitebox Testing of Deep Learning Systems》提出了一種深度學習系統的自動白箱測試方法 DeepXplore,參閱機器之心的報導《學界 | 新研究提出 DeepXplore:首個系統性測試現實深度學習系統的白箱框架》。近日,Yoav Hollander 在一篇部落格文章中對這項研究進行了深度解讀,同時還對「對基於機器學習的系統進行驗證」這一主題進行了更廣泛的探討。機器之心對本文進行了編譯介紹。

論文《DeepXplore: Automated Whitebox Testing of Deep Learning Systems》描述了一種新的且(我認為)相當重要的用於驗證基於機器學習的系統的方法。而且其或多或少打破了機器學習世界和類似 CDV(覆蓋驅動驗證)的、動態驗證的世界之間的界限。

在我閱讀這篇論文時,我一直在對自己說:「恩,很不錯嘛,不過,他們好像還忽略了什麼。」所以我聯絡了一下作者,事實證明他們很清楚這個「什麼」是什麼(而且他們也正計劃在未來的研究中解決其中的一些問題)。我將在這篇文章中引述他們的一些答案。


關於 DeepXplore


這篇論文描述了一種用於驗證基於深度神經網路(DNN)的系統的方法,下面部分來自原論文的摘要:

我們提出了 DeepXplore:這是首個系統性測試真實深度學習系統的白箱框架(whitebox framework)。該框架解決兩個難題:(1)生成能夠激發一個深度學習系統邏輯的不同部分的輸入(input);(2)在不涉及手動操作的情況下,識別深度學習系統的不正確行為。首先,我們引入了神經元覆蓋(neuron coverage)來評估深度學習系統的不同部分(這些部分由用於測試的輸入訓練而成)。然後,利用多個有類似功能的深度學習系統作為交叉引證,因此避免了對錯誤行為的手動檢查。我們表明了可以如何將在實現深度學習演算法高神經元覆蓋率時找到觸發不同行為的輸入的過程表示為一個聯合最佳化問題,然後使用基於梯度的最佳化技術有效地解決。

DeepXplore 有效地在當前最先進的深度學習模型上發現了數千個不同的不正確的極端案例行為(corner-case behaviors,比如自動駕駛汽車撞向護欄、惡意軟體偽裝成好軟體),這些模型是在五個流行的資料集上訓練的,其中包括來自 Udacity 在山景城收集的駕駛資料和 ImageNet 資料。

其中有 4 個主要思想我比較喜歡:

  • 使用了神經元覆蓋(neuron coverage);
  • 透過比較多個相似的 DNN 的輸出來檢查 DNN 的輸出;
  • 自動「輕微推動」執行過程向目標移動,即:(2) 中定義的檢查可以找到不一致的地方,同時 (1) 中定義的覆蓋實現最大化,同時還考慮到了約束條件;
  • 使用了有效的基於梯度的聯合最佳化而做到了 (3)。

但對於這其中的每一個,我都有問題。這不是壞事:實際上這篇論文帶來的很多問題是一個很大的加分——我已經在期待後續的研究了。我的問題主要和 DeepXplore 的「僅有白箱(whitebox-only)」的本質有關(當然,這也是一個優點)。

讓我按順序逐一闡述一下這四個主要思想,討論一下我喜歡它們的理由以及相關的問題:

1. 使用神經元覆蓋

對於一組 DNN 執行,它們的覆蓋指標是「在這些執行過程中有多大比例的神經元(DNN 節點)至少啟用了一次」。其核心思想是,對於一個給定的 DNN 輸入,每個神經元要麼是啟用的(即超過了閾值),要麼就保持為 0。正如原論文說的一樣:

最近的研究已經表明 DNN 中的每個神經元往往需要負責提取其輸入的一個特定的特徵……這個發現直觀地解釋了為什麼神經元覆蓋是一個用於 DNN 測試全面性(testing comprehensiveness)的好指標

注意,這些節點對應的特徵並不一定能夠用我們的語言直觀描述(比如:一個有兩隻眼睛的物體)。但 DNN 訓練的最佳化過程通常確實會使它們對應於一些「可複用的特徵」,即讓 DNN 在許多不同輸入上都有用的東西。

研究者之前也嘗試過自動使神經元活躍,比如在論文《Understanding Neural Networks Through Deep Visualization》為了視覺化神經元的工作,但使用神經元覆蓋(neuron coverage)來進行驗證應該是一個新的好想法。

可能的問題:

但是注意,神經元覆蓋(類似於 軟體驗證中的程式碼覆蓋(code coverage))是真正的實現覆蓋(implementation coverage)。而實現覆蓋就我們所知是不夠的,主要是因為其對因疏忽造成的漏洞沒有助益:如果你接收/傳輸 軟體的模組遺忘(SW module forgot)來實現傳輸,或遺忘有關「接收同時傳輸」的問題,然後你可以實現 100% 的程式碼覆蓋並達到完美,直到有人實際寫出了一個傳輸測試(或使用者自己嘗試傳輸)。

參見覆蓋的多個討論(實現,功能等等):https://blog.foretellix.com/2016/12/23/verification-coverage-and-maximization-the-big-picture/

這對於 DNN 也是一樣:如果你忘記在「靠右行駛」、謹慎轉彎或巴士上塗鴉的人上訓練的駕駛 DNN,那麼你可能會在一個漏洞很多的系統上實現 100% 的覆蓋。

作者回復:

我們完全同意你的觀點。完全的神經元覆蓋(full neuron coverage)(就像程式碼覆蓋)無法保證能找到所有可能的漏洞。話雖如此,我們也在思考擴充套件神經元覆蓋的定義,使之能夠包含不同型別的覆蓋(比如在傳統軟體中就像路徑覆蓋(path coverage)一樣的神經元路徑覆蓋(neuron path coverage))。

我認為擴充套件神經元覆蓋能或多或少帶來一些幫助。假設(這裡簡化了很多)我們的駕駛 DNN 有一個用於檢測「狗在公路上」的神經元和另一個用於檢測「貓在公路上」的神經元。那麼,除了分別單個覆蓋它們,我們還想要覆蓋它們的反例(「沒有狗」)和組合(「有狗有貓」、「有貓且沒狗」)以及序列(「有貓然後有狗」——這就是上面提到的神經路徑覆蓋)。

但是,這只是實現覆蓋,下面可看到更多評論。

透過比較其它實現來檢查 DNN

他們檢查行為的方式是比較多個、或多或少不同的基於 DNN 的實現,來看它們是否吻合。這是 軟體「差分測試(differential testing)」的一種擴充套件,其(對於你們這些來自硬體驗證的人來說)基本上和原來的「透過一個參考模型進行檢查」差不多。

潛在問題:

透過參考模型檢查通常是假設該參考模型是(幾乎)完美的,即是可以被信任的。當然,事實並非如此,所以是有潛在問題的。

比如說,這能找到遺漏的 bug 嗎?只能考慮我們在訓練過程中考慮過的一些 DNN 案例,而不能考慮其它的。但我很懷疑這是否足夠。該論文說道:

如果所有被測試的 DNN 都會犯同樣的錯,那麼 DeepXplore 不能生成對應的測試案例。但是,我們發現這在實際中並不是一個顯著問題,因為大多數 DNN 是獨立構建和訓練的,它們都會犯同樣錯誤的機率比較低。

但這是假設 (a) 你在現實和充滿競爭的市場中能夠獲取許多不同的實現,和 (b) 至少有一位作者(比如 Tsunami)想過這並不一定現實。


作者回復:

這確實是差分測試的一個限制。以一種獨立的方式測試一個模型的一種方法是使用對抗 DNN 測試技術,這種方法目前僅允許實現人眼不可見的輕微擾動。你也許可以擴充套件對抗訓練來使用範圍廣泛的現實約束。比如說,透過改變光的效果。但是,這種方法的主要問題是缺乏資料標籤。我們很難確定一個 DNN 模型是否做出了正確的分類。理論上,任何擾動都可以任意改變影像的真實標籤。

實際上,無需一個「獨立的」檢查事物的方式,這可能是一個相當好的方式。但其 CDV 選項(這確實意味著大量的工作)說需要人類來寫出單獨的/人工的檢查/斷言集。

比如說,如果我們在談論的是 Udacity 駕駛案例,你可以寫一些「不能朝其它汽車行駛」之類的檢查……這些都是機率檢查,所以這是一種微不足道的工作,但做自動駕駛汽車的人可能會做。另外隨便一提,安全問題永遠不是隻靠機器學習就可以的。

這些人也會使用功能覆蓋來增強實現覆蓋,比如「我們是不是走過了一個左轉彎?一次沒有保護的左轉彎?一次沒有汽車和我們同一條道路的左轉彎?一次雨天的左轉彎?」正如我前面提到的那樣。

差分檢查還有另一個潛在的問題:假設其中有比較大的重疊,但其中每個都會考慮一些其它不會考慮的案例。然後執行 DeepXplore 將會將這些案例標記為「不一致(inconsistent)」,然後你必須檢查完它們全部,然後找到其中正確的部分(即:這是我的實現中的 bug 嗎?還是隻是其他人遺忘的一個?)

另外,還經常有「沒有一個正確答案」的情況:汽車可以左轉也可以右轉,或者決策邊界可以有所不同(「我可以啟動了嗎?」)。而當不一致性僅僅意味著「這裡可能有一個錯誤時」,我們可能會需要一個長的、人工的過程。

推動執行檢查錯誤,同時最大化覆蓋並服從約束

這可能是最有意思的部分了。正如他們描述的一樣:

最後,我們表明儘可能生成測試輸入(該輸入需要在最大化深度學習系統的神經元覆蓋的同時揭示出盡可能多的有區別的行為(即多個相似深度學習系統之間的差異))的問題可以如何被形式化成一個聯合最佳化的問題,而且其可以在大規模真實世界深度學習分類器上得到有效的解決。和傳統的程式不同,由深度學習系統所使用的大多數流行的深度神經網路(DNN)所逼近的函式是可微分的。因此,在給出了對應模型的白箱許可權的情況下,這些輸入對應的梯度可以得到準確的計算。

我真的很喜歡這一點:這既在同一個工具中包含了我們所說的覆蓋最大化(coverage maximization)和漏洞尋找(bug-hunting)。他們也嘗試在一些約束條件下做到這一點:比如說,在視覺任務中,他們僅僅使影像更暗或覆蓋影像的小邊角,而在檢測檔案中的惡意軟體時,他們堅持給檔案的結構加一些約束條件。

潛在問題:

這裡有一個大問題,我將其稱為「約束問題(constraint problem)」:因為,可允許的約束不夠靈活,所以,得到的輸入只能成為「用於訓練的輸入,加上一些小改動」。

人們很希望能夠明確靈活的限制(flexible constraint)是什麼,因為這些限制讓簡單的修改和巨大的改動都成為了可能(就像在左邊開車或在公交車上畫畫一樣),同時它們也可以完全避免不現實的改變(比如漂浮在空氣中的汽車)。

這一切可能嗎?聽起來的確很難,但是惡意軟體的例子向我們展示了人們可以在一定程度上自定義約束。

在大部分驗證中我最喜歡的結論是一些 CDV(覆蓋驅動驗證)的變體。因此,我期望為驗證所有系統而創造一種隨機驗證的、基於模型的輸入,這其中包括了基於 DNN 的系統。使用 DeepXplore 的人們只討論獲取現存輸入與將這些輸入進行變異的方法。尋找一些結合的方法應該是很有趣的。

作者回復:

你是對的,我們在影像設定中提出的約束仍然不夠靈活。之所以考慮它們是因為它們可以被梯度有效的引導。實際上,還有很多其它的資料增強技術:對影像而言,我們可以旋轉、翻轉它們,甚至我們可以做一些語義轉換(比如:將 BMW X6 改變成 BMW X1)。然而,我們不能使用梯度來對這些轉換(transformation)進行有效地計算——我們只能隨機用這些約束來轉換這些影像,希望部分轉換可以引發模型間的不同狀態。指明這些約束(它們可被梯度有效引導)的類別、和性質是非常有趣的。……提出資料(如影像)的現實模型/約束本身就是一個困難的問題。在 DeepXplore 裡,我們以現實的輸入作為起點,希望變異的樣本是有效的,因此它們可以出現在現實世界。我們也試著從隨機樣本開始,後來發現 DeepXplore 能夠發現不同誘導(difference-inducing)的輸入,但是它們看起來不是一個不真實的影像。在機器學習的世界裡,一個執行類似任務的熱門方法是使用生成對抗網路(GAN):給定一個隨機向量,它可以學習生成真實的輸入,這些輸入和真正的輸入是不可分辨的(例如,https://github.com/jayleicn/animeGAN)。我們也正在使用這個技術來研究如何生成輸入。

我曾在部落格上寫了關於「用於驗證的 GAN」的文章,我同意 GAN 可以幫助生成某種意義上直接的、真實的驗證輸入。但是我還是懷疑,認為其中的「新穎性」是會受到限制的,所以它還不夠好。

我真正想看到的是有一個 pipeline,在它裡面輸入的生成是從一些強行的、高階描述中生成的。例如,考慮如下(完全是推測)內容:假設我們有一個從文字到影像的神經網路,你告訴它,現在有這樣一種圖文聯絡:「一輛車從左邊過來」,然後它你給出與你描述相關的影像。我描述了(在上面提到的帖子中)人們如何用一種 GAN 和一種 RNN 來處理這類事情的方法,但是很有可能它不是唯一的。

現在你將得到的影像(或影像的序列)輸入 Udacity 的駕駛員 DNN,你會得到一個「必要的轉向角度(required-steering-angle)」輸出。現在,與其(比如說)對圖片新增黑色的干擾,不如對文字輸入進行干擾。而且你也可以將邏輯約束施加給文字。

如果這種方法奏效(很有可能),或許你還可以透過將另一個 DNN(它結合了多個這種文字到影像的 DNN 的輸出)應用於複合場景(「一輛從左邊開來的車、站在右邊的狗、以及剛剛變綠的訊號燈這三者的結合」),從而在輸入中實現更高的複雜度和多樣性。

這個觀點可能不會如其所述那樣有效——我只是試著概述一種更接近「真實 CDV(覆蓋驅動驗證)」的方向。


在 DNN 上進行有效、基於梯度的聯合最佳化

在一篇早先的帖子裡我表示我希望機器學習可以更多地用於對智慧的自動化系統的驗證工作中,參閱:https://blog.foretellix.com/2017/05/25/one-shot-imitation-learning-and-verification/。其中一個理由是:

深度神經網路是基於「可微分」計算的,所以這種屬性讓它更容易根據你的想法來進行操作。關於這一點更多的分析我將在後面的帖子中論述。

現在,「後面的帖子」就在你眼前。我們來看看作者是怎樣解釋他們如何計算導致錯誤(error-causing)的輸入的。

注意到,在高階層面,我們的梯度計算與在訓練一個 DNN 過程中執行的反向傳播運算類似,但是存在一個關鍵的區別,即與我們不同的是,反向傳播運算將輸入值作為一個常數,將權重引數作為一個變數。

換句話說,他們在用在根本上同樣有效的線性代數機器(這種機器是訓練和發展 DNN 去做其它事情的基礎)來找出輸入,這種輸入將形成一個覆蓋點(或一個誤差,或二者都有)。

試想一下在進行常規硬體和軟體驗證時有多麼困難:比如,為了達到一條具體的誤差線,你使用了很多方法,如結合大量手動工作的智慧隨機(smart random),或者是 Concolic 生成(Concolic generation),或是(對足夠小的系統而言)模型檢查——你可以在這篇帖子(https://blog.foretellix.com/2016/09/01/machine-learning-for-coverage-maximization/)的文末找到相關參考文獻。但是對於 DNN 而言,這相對簡單一些。順便提一句,DeepXplore 只能對靜態的、狀態較少的 DNN 進行報告,但是這項技術可被擴充套件來處理如牽涉一個輸入序列的強化學習問題。

我感到這可以用來做很多事情(參見標題名為「Other applications of DNN gradients(深度神經網路梯度的其它應用)」的論文章節)。例如,這裡有個初步、模糊的想法:我曾經寫過有關「可解釋的人工智慧」的文章(https://blog.foretellix.com/2016/08/31/machine-learning-verification-and-explainable-ai/),而且提到了其有助於驗證(以及其它很多事情)的原因。或許,我們可以用像 DeepXplore 的技巧(找到精準的界限和關於這些界限的補充樣本)去描繪一個輸入的本地區域(「如果這個輸入變成了 this,那麼回答就應該變成 that」), 因此,透過這種辦法我們可以讓使用者瞭解 DNN。

其它評論


下面是我在閱讀這篇論文時看到的一些零散的評論:

機器學習系統大概可能無法單獨處理所有的安全問題:

如我在「強化學習與安全性」(https://blog.foretellix.com/2017/03/28/misc-stuff-mobileye-simulations-and-test-tracks/)中提到的一樣,大部分人都假設:僅靠 DNN 是無法顧及到所有安全相關的邊界情況(原因有很多,比如在錯誤的資料上過渡訓練將會讓系統偏離正常狀態;再比如,你希望透過閱讀程式碼來說服自己你的系統符合安全規範)。因此人們需要某種不是 DNN 的「安全 wrapper」(在上面提到的文章中我提到了三種這樣的 wrapper)。

如果我說得沒錯,那麼(假設 DeepXplore 受限於 DNN 系統),DeepXplore 就只能完成工作的一部分,對於它找出的每一個「錯誤」,我們都應該把它交給另一個更大的系統,然後觀察 wrapper 是否可以將工作完成。這一切有可能很容易,但是也不一定。

作者回複道:

你是對的。任何真實世界的自動駕駛汽車都有某種 wrapper 來處理 DNN 可能的決定,而不是直接依賴 DNN 去處理所有的錯誤情況。所以,這個 wrapper 也應該是一個很好的測試目標。

關於對抗性樣本:

我在《用機器學習驗證機器學習?》這篇帖子裡(https://blog.foretellix.com/2016/09/14/using-machine-learning-to-verify-machine-learning/)裡提到了對抗性樣本,我表示:

這篇文章《Transferability in Machine Learning: from Phenomena to Black-Box Attacks using Adversarial Samples》(https://arxiv.org/pdf/1605.07277.pdf)提到了多種機器學習(深度神經網路、支援向量機、決策樹等等)系統中同樣的欺騙性樣本。最後,這篇文章《EXPLAINING AND HARNESSING ADVERSARIAL EXAMPLES》嘗試解釋為何欺騙性樣本應該經常遷移(transfer)到所有線性模型。此外,本文還表示,正確分類的輸入只在輸入空間中形成「thin manifolds」。它們被欺騙性樣本環繞,但是大部分輸入空間都由「無效樣本」組成,這些輸入與訓練關注的內容完全不相關。

如果,在執行同樣任務時,欺騙了一個深度學習實現的對抗性樣本也會傾向去欺騙其它的 DNN 實現,那麼可能那些錯誤的樣本也有能力辦到同樣的事。如果說得沒錯,那麼透過在 K 實現之間進行比較的檢查法就不會起作用,除非 K 非常大。

對此作者回複道:

可遷移性(transferability)真的是非常有趣的觀察(observation)。在我們的實驗裡,我們發現儘管有些輸入狀態是可遷移的,但是大部分不是。實際上,差異測試的目標是找到這種不可遷移的狀態。

同時,我們注意到,如果「無效樣本」的空間實際上非常巨大,那麼我們就需要多少將其切分成這樣:即「雖然不在訓練中進行考慮,但是它要已經包含在裡面」(就像「在左邊開車」);同時我們也要將其切分成這樣:即「不因為好的原因而將其考慮進訓練中」(就像「空間中的車輛,一個在另一個之上飛行一樣」)。這就回到了上面提到的那個非常困難的「約束問題」。

相關文章