[譯] 調試神經網絡的清單

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

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

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

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

那麼該怎麼辦呢?

image

本文將提供一個框架來幫助您調試神經網絡:

  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

image

使用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 - https://keras.io/callbacks/#learningratescheduler

Tensorflow - https://www.tensorflow.org/api_docs/python/tf/train/exponential_decay

PyTorch - https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html

MXNet - https://mxnet.incubator.apache.org/versions/master/tutorials/gluon/learning_rate_schedules.html

  • 梯度裁剪 - 這將在反向傳播期間用最大值或最大範數剪切參數的梯度。這用於解決您在上述錯誤#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這樣的工具可以幫助自動跟蹤數據集、代碼更改、實驗歷史和產品模型(這包括模型的關鍵信息,如超參數、模型性能指標和環境詳細信息)。

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

image

快速回顧

我們希望這篇文章能爲調試神經網絡提供堅實的起點。總結其關鍵點,您應該:

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

image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章