作者:Slav Ivanov
編譯:ronghuaiyang
大家都遇到過這種情況,訓練的時候沒什麼問題,測試的時候就不對勁了,想找問題,感覺無處入手,那麼今天,給你37個建議,看看再說吧。
這個網絡在過去12個小時中一直在進行訓練。一切看起來都很好:梯度在流動,損失在降低。但是接下來的預測結果是:所有都是0,所有都是背景,沒有檢測到任何東西。「我做錯了什麼?」—我問我的電腦,電腦沒睬我。
你從哪裡開始檢查你的模型是否正在輸出垃圾(例如預測所有輸出的平均值,或者它的準確性非常差)?
由於一些原因,網絡可能不會進行訓練。在許多調試的過程中,我經常發現自己在執行相同的檢查。我把我的經驗和最好的想法整理在這個方便的列表里。我希望它們對你也有用。
很多事情都可能出錯。但其中一些更有可能出現問題。我通常以這張簡短的清單作為緊急第一反應:
如果上面的步驟沒有什麼用,那麼就從下面的列表開始,逐一驗證。
1. 檢查你的輸入數據
檢查你正在向網絡提供的輸入數據是否有意義。例如,我不止一次地搞混了圖像的寬度和高度。有時,我會不小心把輸入全部搞成了0。或者我會反覆的使用相同batch。因此,列印/顯示兩個batch的輸入和目標輸出,並確保它們是正確的。
2. 嘗試隨機的輸入
嘗試傳遞隨機數而不是實際數據,看看錯誤的現象是否相同。如果是的話,這是一個確定的信號,表明你的網絡在某個時候正在把數據變成垃圾。試著一層一層地調試看看哪裡出錯了。
3. 檢查你的數據加載
你的數據可能沒有問題,但是將輸入傳遞到網絡的代碼可能會有問題。在任何操作之前列印第一層的輸入並檢查它。
4. 確保輸入連接到了輸出
檢查一些輸入樣本的標籤是否正確。還要確保對輸入樣本的變換對輸出標籤的作用是相同的。
5. 輸入和輸出之間的關係是不是太隨機了?
也許輸入和輸出之間關係的非隨機部分與隨機部分相比太小了(有人可能會說股票價格是這樣的)。也就是說,輸入與輸出的關係並不充分。由於這取決於數據的性質,因此沒有一種通用的方法來檢測這一點。
6. 數據集中是否有太多的噪聲?
有一次,當我從一個食品網站上抓取圖像數據集時,這種情況發生在我身上。有太多不好的標籤,網絡無法學習。手動檢查一些輸入樣本,看看標籤是不是正確。
噪聲的截止點有待討論,因為本文在使用50%損壞標籤的MNIST上獲得了超過50%的準確性。
7. 打亂數據集
如果你的數據集沒有被打亂,並且有一個特定的順序(按標籤排序),這可能會對學習產生負面的影響。打亂你的數據集,以避免這種情況。確保你在進行打亂的時候,是把輸入和標籤一起打亂的。
8. 減少類別的不均衡
每一個類別B的圖像就有1000個類別A的圖像?你可能需要平衡損失函數或嘗試其他類別不平衡的方法。
9. 你有足夠的訓練樣本嗎?
如果你正在從頭開始訓練一個網絡,你可能需要大量的數據。對於圖像分類,人們說每個類需要1000個或更多的圖像。
10. 確保你的batch里不只包含同一個標籤
這可能發生在排過序的數據集中(即前10k個樣本包含相同的類)。通過打亂數據集很容易修復。
11. 減少batch size
這篇文章指出大的batch size會降低模型的泛化能力。
附加1. 使用標準的數據集(如mnist, cifar10 )
在測試新網絡架構或編寫新代碼時,首先使用標準數據集,而不是你自己的數據。這是因為這些數據集有很多參考結果,而且它們被證明是「可解的」。不會出現標籤噪聲、訓練/測試分布差異、數據集難度過大等問題。
12. 特徵標準化
你是否標準化了你的輸入使其均值和單位方差為零?
13. 你是不是用了太多的數據增強?
增強具有規律性的效果。太多的這些與其他形式的正則化(權值的L2,dropout等等)結合在一起會導致網絡欠擬合。
14. 檢查你的預訓練模型的預處理
如果你使用的是預訓練模型,請確保你使用的歸一化和預處理與訓練時的模型相同。例如,圖像像素應該在[0,1]、[- 1,1]還是[0,255]範圍內?
15. 檢查訓練/驗證/測試集的預處理
CS231n指出了一個常見的陷阱:
「……任何預處理統計數據(例如數據平均值)必須僅對訓練數據進行計算,然後應用於驗證/測試數據。」例如,計算平均值並從整個數據集中的每幅圖像中減去它,然後將數據分割為train/val/test分割是錯誤的。"
同時,檢查每個樣本或batch的預處理的不同之處。
16.嘗試解決這個問題的更簡單的版本的問題
這將有助於找到問題所在。例如,如果目標輸出是物體的類別和坐標,請嘗試只預測物體的類別。
17.看看「隨機」時候的正確的損失
再次來自優秀的CS231n:使用小參數進行初始化,沒有正則化。例如,如果我們有10個類,在隨機的情況下意味著我們將有10%的時候會得到正確的類,Softmax損失是正確類的機率的負對數,因此:-ln(0.1) = 2.302.
在此之後,試著增加正則化強度,這會增加損失。
18. 檢查你的損失函數
如果你實現了自己的loss函數,那麼檢查它的bug並添加單元測試。通常,我自己寫的損失可能是不正確的,並以一種微妙的方式損害了網絡的性能。
19. 驗證損失的輸入
如果你使用的是框架提供的loss函數,請確保你傳遞給它的是它所期望的。例如,在PyTorch中,我會混淆NLLLoss和CrossEntropyLoss,因為前者需要softmax輸入,而後者不需要。
20. 調整損失的權重
如果你的損失由幾個較小的損失函數組成,請確保它們相對於每個損失函數的大小是正確的。這可能涉及測試不同的損失權重組合。
21. 使用其他的度量方法進行監控
有時候,損失並不能很好地預測你的網絡是否訓練的好。如果可以,使用其他指標,如準確性。
22. 測試所有的自定義的層
你自己實現了網絡中的一些層嗎?反覆檢查以確保它們按照預期工作。
23. 檢查「凍結」的層和變量
檢查你是否無意中禁用了一些層/變量的梯度的更新。
24. 增加網絡的大小
也許你的網絡的表達能力不足以得到目標函數。嘗試在全連接的層中添加更多的層或更多的隱藏單元。
25. 檢查隱藏維度的錯誤
如果你的輸入看起來像(k, H, W) =(64, 64, 64)那麼很容易忽略與錯誤維度相關的錯誤。對輸入維度使用奇怪的數字(例如,每個維度使用不同的素數),並檢查它們如何在網絡中傳播。
26. 梯度檢查
如果你手動實現梯度下降,檢查梯度,確保你的反向傳播工作正常。
27. 處理小數據集
過擬合數據的一個子集,並確保它能工作。例如,用一兩個樣本來訓練,看看你的網絡是否能學會區分它們。再繼續使用每個類的更多樣本。
28. 檢查權值初始化
如果不確定的話,使用Xavier或He初始化。另外,初始化可能會導致錯誤的局部最小值,所以嘗試不同的初始化,看看是否有幫助。
29. 改變你的超參數
也許你使用了一組特別糟糕的超參數。如果可行,嘗試網格搜索。
30. 減少正則化
過多的正則化會導致網絡嚴重欠擬合。減少正規化,如dropout、、權重/偏置L2正規化等。在優秀的「Practical Deep Learning for coders」課程中,Jeremy Howard建議首先擺脫欠擬合。這意味著你需要對訓練數據進行充分的過擬合,然後再解決過擬合問題。
31. 多給點時間
也許你的網絡需要更多的時間來訓練,才能開始做出有意義的預測。如果你的損失在穩步減少,那就讓它繼續訓練吧。
32. 從訓練模式切換到測試模式
有些框架具有Batch Norm、drop等層,在訓練和測試期間的行為有所不同。切換到適當的模式可能有助於你的網絡進行正確的預測。
33. 訓練可視化
對於權值,這些直方圖在一段時間後應該有一個近似的高斯分布。對於偏置,這些直方圖通常從0開始,通常以近似高斯分布結束(LSTM是一個例外)。注意那些發散到+/-∞的參數。留意那些變得很大的偏置。如果類的分布非常不平衡,這種情況有時會發生在分類的輸出層。
34. 嘗試不同的優化器
你選擇的優化器不應該會導致你的網絡不訓練,除非你選擇了特別糟糕的超參數。然而,對於一個任務,適當的優化器可以幫助在最短的時間內獲得最多的訓練。你正在使用的算法的論文中應該會指定優化器。如果不是,我傾向於使用Adam或使用動量的SGD。
查看Sebastian Ruder的excellent post了解更多關於梯度下降優化器的信息。
35. 梯度爆炸/消失
36. 增大/降低學習率
較低的學習率會導致模型非常緩慢地收斂。
高學習率將在開始時迅速減少損失,但可能很難找到一個好的解決方案。
把你當前的學習速度乘以0.1或10。
37. 克服NaNs
在訓練RNN時,獲得NaN (Non-a-Number)是一個更大的問題。一些解決方法:
英文原文:https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607
更多文章,請關注微信公眾號:AI公園