轉自:http://www.infoq.com/cn/articles/37-reasons-why-your-neural-network-is-not-working
神經網絡已經持續訓練了 12 個小時。它看起來很好:梯度在變化,損失也在下降。但是預測結果出來了:全部都是零值,全部都是背景,什么也檢測不到。我質問我的計算機:“我做錯了什么?”,它卻無法回答。
如果你的模型正在輸出垃圾(比如預測所有輸出的平均值,或者它的精確度真的很低),那么你從哪里開始檢查呢?
無法訓練神經網絡的原因有很多。在經歷了許多次調試之后,我發現有一些檢查是經常做的。這張列表匯總了我的經驗以及最好的想法,希望對讀者也有所幫助。
〇. 使用指南
許多事情都可能出錯。但其中有些事情相比於其他方面更容易出問題。在出現問題時,我通常會做以下幾件事情。
- 從已知的用於該數據類型的簡單模型入手(例如VGG用於圖像處理)。盡可能使用標准誤差。
- 去掉所有的花哨的預處理程序,例如正則化和數據增強。
- 微調模型,仔細檢查預處理,應該和原始模型的訓練設置保持一致。
- 驗證輸入數據的正確性。
- 從較小的數據集開始(2-20個樣本)。在小數據集上過擬合之后再增加數據量。
- 慢慢加入之前忽略的項:增強或正則化、自定義損失函數,以及嘗試更多的復雜模型。
如果上面的步驟還不能解決,可以開始一項一項的按以下列表進行檢查。
Ⅰ. 數據集問題
1. 檢查你的輸入數據
檢查饋送到網絡的輸入數據是否正確。例如,我不止一次混淆了圖像的寬度和高度。有時,我錯誤地讓輸入數據全部為零,或者一遍遍地使用同一批數據。所以要打印或顯示一些批次的輸入和目標輸出,並確保它們是正確的。
2. 嘗試隨機輸入
嘗試向網絡傳入隨機數而不是真實數據,看看錯誤的產生方式是否相同。如果是,說明在某些時候你的網絡把數據轉化為了垃圾。試着逐層調試,並查看出錯的地方。
3. 檢查數據加載器
你的數據也許很好,但是把輸入數據讀取到網絡的代碼可能有問題,所以我們應該在進行其他操作之前打印出第一層的輸入並進行檢查。
4. 確保輸入與輸出相關聯
檢查少許輸入樣本是否有正確的標簽,確保打亂輸入樣本同樣也要打亂輸出標簽。
5. 輸入與輸出之間的關系是否太隨機
相較於隨機的部分(可以認為股票價格也是這種情況),輸入與輸出之間的非隨機部分也許占得比重太小。也就是說輸入與輸出的關聯度太低。沒有統一的方法來檢測它,因為這取決於數據的性質。
6. 數據集中是否有太多的噪聲
我曾經遇到過這種情況,當我從一個食品網站抓取一個圖像數據集時,錯誤標簽太多以至於網絡無法學習。手動檢查一些輸入樣本並查看標簽是否大致正確。例如這篇 文章 ,由於在MNIST數據集中使用了50%損壞的標簽,只得到了50%的准確率。
7. 打亂數據集
如果你的數據集沒有被隨機打亂,並且有特定的序列(按標簽排序),這可能給學習帶來不利影響。打亂數據集可以避免這一問題。要確保輸入和標簽都被重新排列。
8. 減少類別失衡
是不是對於一張類別 B 的圖像,有 1000 張類別 A 圖像?如果是這種情況,那么你也許需要平衡損失函數或者嘗試 其他解決類別失衡的方法 。
9. 你有足夠的訓練實例嗎?
如果你從頭開始訓練一個網絡(不是調試),你很可能需要大量數據。 對於圖像分類,每個類別需要 1000 張圖像甚至更多。
10. 確保一批數據不是單一標簽
這可能發生在排好順序的數據集中(即前 10000 個樣本屬於同一個分類)。可通過打亂數據集輕松修復這個問題。
11. 縮減訓練批次大小
這篇文章 指出巨大的批次會降低模型的泛化能力。
補充. 使用標准數據集(例如MNIST,cifar10)
測試新的網絡結構,或者寫了一段新代碼時,首先要使用標准數據集,而不是你自己的數據。這是因為在這些數據集上已經有了許多參考結果,他們被證明是“可解的”。不會出現標簽噪音、訓練/測試分布差距、數據集太難等問題。
Ⅱ. 數據歸一化/增強
12. 歸一化特征
你的輸入已經歸一化到零均值和單位方差了嗎?
13. 你是否應用了過量的數據增強?
數據增強有正則化效果。過量的數據增強,加上其它形式的正則化(權重 L2,dropout操作,等等)可能會導致網絡欠擬合。
14. 檢查預訓練模型的預處理過程
如果你正在使用一個已經預訓練過的模型,確保你現在正在使用的歸一化和預處理與之前訓練模型的設置相同。例如,一個圖像的像素是在 [0, 1],[-1, 1] 或 [0, 255] 的范圍內嗎?
15. 檢查訓練、驗證、測試集的預處理
CS231n 指出了一個常見的 陷阱 :“任何預處理數據(例如數據均值)必須只在訓練數據上進行計算,然后再應用到驗證、測試數據中。例如,計算均值,然后在整個數據集的每個圖像中都減去它,再把數據分發進訓練、驗證、測試集中,這是一個典型的錯誤。”
此外,要在每一個樣本或批次(batch)中檢查是否存在不同的預處理。
Ⅲ. 實現問題
16. 試着解決某一問題的更簡單的版本
這將會有助於找到問題的根源究竟在哪里。例如,如果目標輸出是一個物體類別和坐標,那就試着把預測結果僅限制在物體類別當中。
17. “碰巧”尋找正確的損失
還是來源於 CS231n 的技巧:用小參數進行初始化,不使用正則化。例如,如果我們有 10 個類別,“碰巧”就意味着我們將會在 10% 的時間里得到正確類別,Softmax 損失是正確類別的負log概率: -ln(0.1) = 2.302。然后,試着增加正則化的強度,這樣應該會增加損失。
18. 檢查你的損失函數
如果你實現的是你自己的損失函數,那么就要檢查錯誤,並且添加單元測試。通常情況下,損失可能會有些不正確,並且略微損害網絡的性能表現。
19. 核實損失輸入
如果你正在使用的是框架提供的損失函數,那么要確保你傳遞給它的東西是它所期望的。例如,在PyTorch中,我會混淆 NLLLoss 和 CrossEntropyLoss,因為一個需要 softmax 輸入,而另一個不需要。
20. 調整損失權重
如果你的損失由幾個更小的損失函數組成,那么確保它們每一個的相應幅值都是正確的。這可能會涉及到測試損失權重的不同組合。
21. 監控其它指標
有時損失並不是衡量你的網絡是否被正確訓練的最佳預測器。如果可以的話,使用其它指標來幫助你,例如精度。
22. 測試任意的自定義層
你自己在網絡中實現過任意層嗎?檢查並且復核以確保它們的運行符合你的預期。
23. 檢查“冷凍”層或變量
檢查你是否無意中阻止了一些層或變量的梯度更新,這些層或變量本來應該是可以學習的。
24. 擴大網絡規模
可能你網絡的表現力不足以捕捉目標函數。試着加入更多的層,或在全連層中增加更多的隱藏單元。
25. 檢查隱維度誤差
如果你的輸入看上去像(k,H,W)= (64, 64, 64),那么很容易錯過與錯誤維度相關的誤差。給輸入維度使用一些“奇怪”的數值(例如,每一個維度使用不同的質數),並且檢查它們是如何通過網絡傳播的。
26. 探索梯度檢查
如果你手動實現了梯度下降,梯度檢查會確保你的反向傳播能像預期一樣工作。
Ⅳ. 訓練問題
27. 一個真正小的數據集
過擬合數據的一個小子集,並確保它能正常工作。例如,僅使用 1個 或 2 個實例訓練,並查看你的網絡是否能夠區分它們。然后再訓練每個分類的更多實例。
28. 檢查權重初始化
如果不確定,請使用 Xavier 或 He 初始化。同樣,初始化也許會給你帶來壞的局部最小值,因此嘗試不同的初始化,看看是否有效。
29. 改變你的超參數
或許你正在使用一個很糟糕的超參數集。如果可行,嘗試一下 網格搜索 。
30. 減少正則化
太多的正則化會導致網絡嚴重地欠擬合。減少正則化,比如 dropout、批歸一、權重/偏差 L2 正則化等。在課程 《編程人員的深度學習實戰》 中, Jeremy Howard建議首先解決欠擬合問題。這意味着你充分地過擬合訓練數據,並且只在那時處理過擬合。
31. 給它一些時間
也許你的網絡需要更多的時間來訓練,在它能做出有意義的預測之前。如果你的損失在穩步下降,那就再多訓練一會兒。
32. 從訓練模式轉換為測試模式
一些框架有批歸一化層、Dropout層,而其他的層在訓練和測試時表現並不同。轉換到適當的模式有助於網絡更好地預測。
33. 可視化訓練
- 監督每層的激活值、權重和更新。確保它們的大小匹配。例如,參數更新的大小幅度(權重和偏差) 應該是 1-e3 。
- 考慮可視化庫,例如 Tensorboard 和 Crayon 。緊要時你也可以打印權重、偏差或激活值。
- 尋找平均值遠大於 0 的層激活。嘗試批歸一化層或者ELU單元。
- Deeplearning4j
指出了權重和偏差柱狀圖的期望值應該是什么樣的:
對於權重,一段時間之后這些柱狀圖應該有一個近似高斯的(正態)分布。對於偏差,這些柱狀圖通常會從 0 開始,並經常以近似高斯(LSTM是例外情況)結束。留意那些向正無窮或負無窮發散的參數。留意那些變得很大的偏差。這有可能發生在分類網絡的輸出層,如果類別的分布不均勻。
- 檢查層更新,它們應該呈高斯分布。
34. 嘗試不同的優化器
優化器的選擇不應當妨礙網絡的訓練,除非你選擇了特別糟糕的超參數。但是,選擇一個合適的優化器非常有助於在最短的時間內獲得最多的訓練結果。描述算法的論文應該指定了優化器,如果沒有,我傾向於選擇Adam或者帶有動量的朴素SGD。
關於梯度下降的優化器可以參考Sebastian Ruder的 博文 。
35. 梯度爆炸、梯度消失
- 檢查隱藏層的更新情況,過大的值說明可能出現了梯度爆炸。這時,梯度截斷(Gradient clipping)可能會有所幫助。
- 檢查隱藏層的激活值。 Deeplearning4j 中有一個很好的指導方針:“一個好的激活值標准差大約在 0.5 到 2.0 之間。明顯超過這一范圍可能就代表着激活值消失或爆炸。”
36. 增加、減少學習速率
低學習速率將會導致你的模型收斂很慢。高學習速率將會在開始階段減少你的損失,但是可能會導致你很難找到一個好的解決方案。
試着把你當前的學習速率乘以 0.1 或 10然后進行循環。
37. 克服NaN
據我所知,在訓練 RNNs 時得到 NaN(Non-a-Number,非數)是一個很大的問題。一些解決它的方法:
- 減小學習速率,尤其是如果你在前 100 次迭代中就得到了NaN。
- NaNs 的出現可能是由於用零作了除數,或用零或負數作了自然對數。
- Russell Stewart 在 《如何處理NaN》 中分享了很多心得。
- 嘗試逐層評估你的網絡,這樣就會看見NaN到底出現在了哪里。
關於作者:Slav Ivanov是保加利亞索菲亞的企業家和ML實踐者。 博客主頁 。
查看英文原文: 37 Reasons why your Neural Network is not working
感謝薛命燈對本文的審校。
給InfoQ中文站投稿或者參與內容翻譯工作,請郵件至editors@cn.infoq.com。也歡迎大家通過新浪微博(@InfoQ,@丁曉昀),微信(微信號: InfoQChina )關注我們。
