[譯] 除錯神經網路的清單

雲水木石發表於2019-03-26

訓練深度學習模型是非常耗時的工作,沒有什麼比花費了好幾天訓練而最終結果效果不佳更讓人沮喪的了。因此翻譯了這篇文章: Checklist for debugging neural networks,希望能給你一點啟發,儘早發現模型中的問題。原文地址:towardsdatascience.com/checklist-f… ,略有刪減。點選閱讀原文可以跳轉到該文章,需要翻牆哦!

眾所周知,機器學習程式碼很難除錯。就連簡單的前饋神經網路,您也經常需要圍繞網路架構、權重值初始化和網路優化做出決策 - 所有這些都可能導致機器學習程式碼中隱藏BUG。

正如Chase Roberts在一篇精彩的關於“如何單元測試機器學習程式碼”的文章中寫道,他的挫折源於常見的陷阱:

  1. 程式碼永遠不會崩潰、引發異常,甚至變慢。
  2. 網路持續訓練,損失仍在不斷減少。
  3. 幾個小時後會收斂,但結果卻很糟糕。

那麼該怎麼辦呢?

[譯] 除錯神經網路的清單

本文將提供一個框架來幫助您除錯神經網路:

  1. 簡單處開始
  2. 確認你的模型損失(loss)
  3. 檢查中間輸出和連線
  4. 診斷引數
  5. 跟蹤你的工作

您可以隨意跳到特定部分或順序閱讀下面的內容!請注意:我們不涉及資料預處理或特定模型演算法選擇。這些主題有很多很好的線上資源(例如,閱讀“選擇合適的機器學習演算法”)。

1.簡單處開始

具有正則化和學習速率排程器的複雜架構的神經網路將比簡單網路更難除錯。這個第一點可能有些投機取巧,因為它與除錯您已經建立的網路沒有關係,但它仍值得重點推薦!

從簡單開始:

  • 首先構建一個更簡單的模型
  • 在單個資料點上訓練模型

構建一個更簡單的模型

作為起點,構建一個具有單個隱藏層的小型網路,並驗證一切正常,然後逐漸新增模型複雜性,同時檢查模型結構的每個方面(層、引數等)是否有效。

在單個資料點上訓練模型

作為一種快速檢查,您可以使用一組或兩組訓練資料點來確認模型是否會產生過擬合。神經網路應立即過擬合,訓練精度為100%,驗證準確度與您隨機猜測的模型相當。如果模型不能在那些資料點上過擬合,那麼要麼資料集太小,要麼有錯誤。

即使您已經確認模型可以工作,也請嘗試在正式訓練之前進行一個(或幾個)epoch的訓練。

2.確認你的模型損失

模型的損失是評估模型效能的主要方式,而模型在評估過程中設定重要的引數,因此您需要確保:

  • 損失適合於當前任務(使用分類交叉熵損失進行多分類問題或使用焦點損失來解決類別不平衡問題)
  • 損失函式都以正確的比例因子進行度量。如果您在網路中使用多種型別的損失,例如MSE、對抗式、L1、特性丟失,那麼請確保所有損失都以相同的比例正確縮放。

注意初始損失也很重要。如果您的模型是通過隨機猜測開始的,請檢查初始損失是否接近您的預期損失。在Stanford CS231n課程中,Andrej Karpathy建議如下:

出於效能考慮尋找正確的損失。使用小引數初始化時,請確保獲得預期的損失。最好先只檢查資料損失(因此將正則化強度設定為零)。例如,對於具有Softmax分類器的CIFAR-10,我們預期初始損失為2.302,因為我們期望每個類別的擴散概率為0.1(因為有10個類別),而Softmax損失是正確的類別的負的對數概率,所以:-ln(0.1) = 2.302。

對於二分類例子而言,您只需對每個類別執行類似的計算。假設你的資料是20%的0類別和80%的1類別。預期的初始損失將達到 -0.2ln(0.5)-0.8ln(0.5) = 0.693147。如果您的初始損失遠大於1,則可能表明神經網路的權重未平衡(即初始化得較差)或您的資料未正則化。

3.檢查中間輸出和連線

為了除錯神經網路,理解神經網路內部的動態以及各個中間層所起的作用以及層的連線方式通常很有用。您可能遇到以下錯誤:

  • 梯度更新的算式不正確
  • 未應用權重更新
  • 消失或爆炸的梯度

如果您的梯度值是零,這可能意味著優化器中的學習率太小,或者你遇到了上述的錯誤#1:不正確的梯度更新算式。

除了檢視梯度更新的絕對值之外,還要確保監視每個層的啟用幅度、權重和更新。例如,引數更新的幅度(權重和偏差)應為1-e3。

存在一種稱為“死亡ReLU”或“消失梯度問題”的現象,其中ReLU神經元在學習其權重的大負偏差項後將輸出零。那些神經元永遠不會再在任何資料點上啟用。

您可以使用梯度檢查,通過使用數值方法逼近梯度來檢查這些錯誤。如果它接近計算的梯度,則反向傳播實現是正確的。要實現梯度檢查,請在此處此處檢視CS231中的這些優秀資源以及Andrew Ng關於該主題的相關課程

Faizan Shaikh撰寫了關於視覺化神經網路的三種主要方法:

  • 初步方法 - 向我們展示訓練模型的整體結構的簡單方法。這些方法包括列印出神經網路的各個層的形狀或過濾器以及每層中的引數。
  • 基於啟用的方法 - 在這些方法中,我們破譯單個神經元或一組神經元的啟用,以直觀的瞭解他們正在做什麼。
  • 基於梯度的方法 - 這些方法傾向於在訓練模型時計算前向和後向梯度。

有許多有用的工具可用於視覺化各個層的啟用和連線,例如ConXTensorboard

[譯] 除錯神經網路的清單

使用ConX進行的動態渲染視覺化示例

使用影象資料? Erik Rippel發表了一篇精彩的文章“使用Keras和Cats視覺化部分卷積神經網路”。

4.診斷引數

神經網路具有大量彼此相互作用的引數,使得優化變得困難。請注意,這是一個積極研究的領域,所以下面的建議只是起點。

  • 批量大小(技術上稱為mini-batch) - 您希望批量大到足以準確估計誤差梯度,但小到足以使mini-batch隨機梯度下降(SGD)可以正則化網路。小的批量大小將會使得學習過程快速收斂,但可能會以增加噪聲為代價,並可能導致優化困難。論文“On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima”解釋了為什麼會這樣:

在實踐中已經觀察到,當使用較大批次時,通過泛化的能力衡量的模型的質量會降低。我們研究了大批量體系中這種泛化下降的原因,並提供了支援大批量方法傾向於收斂到訓練和測試函式的區域性最小化的觀點的資料證據 - 眾所周知,區域性的最小值導致較差的泛化。相比之下,小批量方法始終如一地收斂到平面最小化,我們的實驗支援一種普遍看法,這是由於梯度估計中的固有噪聲。

  • 學習率 - 學習率太低會導致收斂緩慢或陷入區域性最小值的風險,而學習率太大會導致優化發散,因為存在跳過損失函式更深、但更窄部分的風險。可以考慮進行學習速率排程,在訓練過程時降低學習速率。CS231n課程有很多關於實現退火學習率的不同技術

機器學習框架,如Keras、Tensorflow、PyTorch、MXNet現在都有關於使用學習速率排程器/遞減的文件或示例:

Keras - keras.io/callbacks/#…

Tensorflow - www.tensorflow.org/api_docs/py…

PyTorch - pytorch.org/docs/stable…

MXNet - mxnet.incubator.apache.org/versions/ma…

  • 梯度裁剪 - 這將在反向傳播期間用最大值或最大範數剪下引數的梯度。這用於解決您在上述錯誤#3中可能遇到的任何梯度爆炸。

  • 批量標準化 - 批量標準化用於標準化每層的輸入,以對抗內部協變數移位問題。如果您同時使用Dropout和批量標準化,請務必閱讀下面關於Dropout的觀點。

來自Dishank Bansal的文章“Pitfalls of Batch Norm in TensorFlow and Sanity Checks for Training Networks”是批處理標準化常見錯誤的重要參考資源。

  • 隨機梯度下降(SGD) - 有幾種SGD使用動量、自適應學習率和Nesterov更新,但在訓練表現和泛化方面都沒有明顯的優勢(參見Sebastian Ruder的優秀文章'梯度下降優化演算法概述'和這個有趣的實驗'SGD > Adam?')。推薦的開始選擇Adam或普通的帶Nesterov動量的SGD。

  • 正則化 - 正則化對於構建泛化模型至關重要,因為它增加了對模型複雜性或極端引數值的懲罰。它顯著降低了模型的方差,但沒有明顯增加其偏差。如CS231n課程中所講的:

通常情況是,損失函式是資料損失和正則化損失的總和(例如,權重上的L2懲罰)。需要注意的一個危險是正則化損失可能會壓倒資料損失,在這種情況下,梯度將主要來自正則化(通常具有更簡單的梯度表示式)。這可以掩蓋資料損失梯度的錯誤實現。

要對此進行稽核,您應該關閉正則化並獨立檢查資料損失梯度。

  • Dropout - Dropout是另一種正則化網路以防止過度擬合的技術。在訓練時,通過僅以某個概率p(超引數)保留神經元的啟用來實現Dropout,否則將其設定為零。結果,網路必須在每個訓練批次中使用不同的引數子集,這減少了特定引數的變化,防止某些引數占主導地位。

這裡重要的注意事項是:如果您同時使用Dropout和批量規範化(batch norm),請謹慎處理這些操作的順序,甚至謹慎一起使用它們。這仍然是一個活躍的研究領域,但您可以看到最新的討論:

來自Stackoverflow使用者MiloMinderBinder:“Dropout意味著完全阻止來自某些神經元的資訊,以確保神經元不會共同適應。因此,批量規範化必須在Dropout之後,否則您將通過規範化統計傳遞資訊。“

來自arXiv:通過方差轉換理解Dropout和批量標準化之間的不統一(Xiang Li,Shuo Chen,Xiaolin Hu,Jian Yang) - “從理論上講,我們發現網路從訓練狀態轉移到測試時,Dropout會改變特定神經元的方差。但是,BN將在測試階段保持其整個學習過程累積的統計方差。該方差的不一致性(我們將該方案命名為“方差偏移”)導致推理中不穩定的數值行為,當在BN之前應用Dropout時,最終導致更多錯誤的預測。

5.跟蹤你的工作

在您忘記所使用的學習率或類別權重之前,很容易忽略記錄實驗的重要性。通過更好的跟蹤,您可以輕鬆檢視和重現以前的實驗,以減少重複工作(也就是遇到相同的錯誤)。

但是,手動記錄資訊可能很難做到,也很難擴大到多次實驗。Comet.ml這樣的工具可以幫助自動跟蹤資料集、程式碼更改、實驗歷史和產品模型(這包括模型的關鍵資訊,如超引數、模型效能指標和環境詳細資訊)。

您的神經網路對資料、引數甚至包版本的微小變化都非常敏感 - 導致模型效能下降,並可能累積。跟蹤您的工作是開始標準化環境和建模工作流程的第一步。

[譯] 除錯神經網路的清單

快速回顧

我們希望這篇文章能為除錯神經網路提供堅實的起點。總結其關鍵點,您應該:

  • 從簡單開始 - 首先構建一個更簡單的模型,然後通過對幾個資料點的訓練進行測試
  • 確認模型損失 - 檢查您是否使用了正確的損失並檢查初始損失
  • 檢查中間輸出和連線 - 使用梯度檢查和視覺化來檢查圖層是否正確連線,以及梯度是否按預期更新
  • 診斷引數 - 從SGD到學習率,確定正確的組合(或找出錯誤的組合)?
  • 跟蹤您的工作 - 作為基準,跟蹤您的實驗過程和關鍵建模工件

image

相關文章