作者:Cecelia Shao
編譯:ronghuaiyang
這篇文章提供了可以采取的切實可行的步驟來識別和修復機器學習模型的訓練、泛化和優化問題。
眾所周知,調試機器學習代碼非常困難。即使對于簡單的前饋神經網絡也是這樣,你經常會在網絡體系結構做出一些決定,重初始化和網絡優化——所有這些會都導致在你的機器學習代碼中出現bug。
正如Chase Roberts在一篇關于“How to unit test machine learning code”的優秀文章中所寫的,他遇到的麻煩來自于常見的陷阱:
那么我們該怎么做呢?
本文將提供一個框架來幫助你調試神經網絡:
請隨意跳轉到特定的部分或通讀下面的內容!請注意:我們不包括數據預處理或特定的模型算法選擇。對于這些主題,網上有很多很好的資源。
1. 從最簡單的開始
一個具有復雜結構和正則化以及學習率調度程序的神經網絡將比一個簡單的網絡更難調試。我們在第一點上有點欺騙性,因為它與調試你已經構建的網絡沒有什么關系,但是它仍然是一個重要的建議!
從最簡單的開始:
首先,構建一個更簡單的模型
首先,構建一個只有一個隱藏層的小型網絡,并驗證一切正常。然后逐步增加模型的復雜性,同時檢查模型結構的每個方面(附加層、參數等),然后再繼續。
在單個數據點上訓練模型
作為一個快速的完整性檢查,你可以使用一兩個訓練數據點來確認你的模型是否能夠過擬合。神經網絡應該立即過擬合,訓練精度為100%,驗證精度與你的模型隨機猜測相匹配。如果你的模型不能對這些數據點進行過擬合,那么要么是它太小,要么就是存在bug。
即使你已經驗證了模型是有效的,在繼續之前也可以嘗試訓練一個(或幾個)epochs。
2. 確認你的損失
你的模型的損失是評估你的模型性能的主要方法,也是模型評估的重要參數,所以你要確保:
注意,你最初的損失也很重要。如果模型一開始就隨機猜測,檢查初始損失是否接近預期損失。在Stanford CS231n coursework中,Andrej Karpathy提出了以下建議:
在隨機表現上尋找正確的損失。確保在初始化小參數時得到預期的損失。最好先單獨檢查數據的loss(將正則化強度設置為零)。例如,對于使用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神經元在學習了一個表示權重的大的負偏置項后,會輸出一個零。這些神經元再也不會在任何數據點上被激活。
你可以使用梯度檢查來檢查這些錯誤,通過使用數值方法來近似梯度。如果它接近計算的梯度,則正確地實現了反向傳播。
Faizan Shaikh描述了可視化神經網絡的三種主要方法:
有許多有用的工具可以可視化單個層的激活和連接,比如ConX和Tensorboard。
使用ConX生成的動態呈現可視化示例
4. 參數診斷
神經網絡有大量的參數相互作用,使得優化變得困難。請注意,這是一個活躍的研究領域,所以下面的建議只是簡單的出發點。
在實踐中已經觀察到,當使用一個較大的batch size時,模型的質量會下降,這可以通過它的泛化能力來衡量。我們研究了在大批量情況下泛化下降的原因,并給出了支持large-batch方法趨向于收斂于訓練和測試函數的sharp的極小值這一觀點的數值證據——眾所周知,sharp的極小值導致較差的泛化。相比之下,小batch size的方法始終收斂于平坦的最小值,我們的實驗支持一個普遍的觀點,即這是由于梯度估計中的固有噪聲造成的。
本文來自Dishank Bansal的”TensorFlow中batch norm的陷阱和訓練網絡的健康檢查“,里面包括了很多使用batch norm的常見錯誤。
通常情況下,損失函數是數據損失和正則化損失的總和(例如L2對權重的懲罰)。需要注意的一個危險是正則化損失可能會超過數據損失,在這種情況下,梯度將主要來自正則化項(它通常有一個簡單得多的梯度表達式)。這可能會掩蓋數據損失的梯度的不正確實現。
為了檢查這個問題,應該關閉正則化并獨立檢查數據損失的梯度。
來自Stackoverflow的用戶MiloMinderBinder:Dropout是為了完全阻斷某些神經元的信息,以確保神經元不相互適應。因此,batch norm必須在dropout之后進行,否則你將通過標準化統計之后的數據傳遞信息。”
來自arXiv:Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift — 從理論上講,我們發現,當我們將網絡狀態從訓練狀態轉移到測試狀態時,Dropout會改變特定神經單元的方差。但是BN在測試階段會保持其統計方差,這是在整個學習過程中積累的。當在BN之前的使用Dropout時,該方差的不一致性(我們將此方案命名為“方差漂移”)導致不穩定的推斷數值行為,最終導致更多的錯誤預測。
5. 跟蹤你的網絡
你很容易忽視記錄實驗的重要性,直到你忘記你使用的學習率或分類權重。通過更好的跟蹤,你可以輕松地回顧和重現以前的實驗,以減少重復的工作(也就是說,遇到相同的錯誤)。
然而,手工記錄信息對于多個實驗來說是很困難的。工具如 Comet.ml可以幫助自動跟蹤數據集、代碼更改、實驗歷史和生產模型(這包括關于模型的關鍵信息,如超參數、模型性能指標和環境細節)。
你的神經網絡對數據、參數甚至版本中的細微變化都非常敏感,這會導致模型性能的下降。跟蹤你的工作是開始標準化你的環境和建模工作流的第一步。
快速回顧
我們希望這篇文章為調試神經網絡提供了一個堅實的起點。要總結要點,你應該:
英文原文:https://towardsdatascience.com/checklist-for-debugging-neural-networks-d8b2a9434f21