乾貨 | 模型表現不好怎麼辦?37條妙計助你扭轉局勢

 2017-08-02 15:32:00.0

雷鋒網(公衆號:雷鋒網) AI 科技評論按:讀論文,看別人的模型的時候彷彿一切都順利成章,可是等到自己訓練模型的時候,麻煩一個接一個…… 雷鋒網 AI 科技評論找到了一篇國外大神 Slav Ivanov 寫的絕招文編譯如下,給大家介紹37個好辦法!

你的神經網絡已經跑了12個小時訓練,看上去一切都很完美:梯度運轉良好,損失也在降低。但是做預測的時候卻一團糟:所有都是0,什麼也監測不到。「我哪一步做錯了呢?」你迷茫地問你的電腦,而電腦卻笑而不語。

如果你的模型輸出來的都是辣雞——例如你想預測所有輸出的平均值,或者模型的精度很低——該從哪兒開始檢查?

可能出錯的地方多了去了。經過很多次的調試,我常常做此類檢查。我根據自己的經驗以及很多好的想法,寫了以下這個指引。希望對你們也有用。

目錄

0、如何使用本指引

一、數據庫問題

二、數據歸一化/增強問題

三、執行問題

四、訓練問題

 

0. 如何使用本指引

很多問題可能會出錯。不過有一些問題相對容易解決。通常我先從這個急救列表開始:

1. 先從一個簡單的模型入手,找一個對此類數據證明可行的模型,例如針對圖像就用VGG。如果可能的話就選一個標準的損失函數。

2. 把花哨的小玩意都卸了,例如歸一化和數據增強。

3. 微調模型的時候,仔細檢查數據預處理,因爲它必須跟原始模型的訓練數據一致。

4. 確認輸入數據正確。

5. 從一個很小的數據庫入手(2-20個樣本)。用這個調試好了,再慢慢增加更多數據。

6. 慢慢把省略的每一個部件都加回來:增強、歸一化、定製的損失函數、更復雜的模型。

如果以上的步驟不管用,再根據下面這個更長的列表來一項項確認。

一、數據庫問題 乾貨 | 模型表現不好怎麼辦?37條妙計助你扭轉局勢

- 老闆:你給我的數據對嗎?

- 程序猿:這麼多年來我給你的數據都是錯的。怎麼今天想到找茬了。

- 老闆:你說啥?

程序猿:我說數據完全準確。

1. 檢查輸入數據

檢查你輸入網絡的數據是否正確。舉個例子,我好幾次把圖像的長和寬搞混了。有時候,我一不小心全部輸入的都是0。有時候,我把同一個批次的數據用了一遍又一遍。所以,打印顯示你想要的輸入和輸出,確保數據正確。

2. 試試隨機輸入

試試輸入隨機數據而非真實數據,看看是不是會得到一樣的錯誤。如果是的話,那你的網絡肯定是某一個點出錯了,可以試試一層層、一個指令一個指令地調試,看看是哪個點出了錯。

3. 檢查數據導入

可能你的數據是對的,但是用來導入數據到網絡的代碼可能有問題。在任何動作之前,把第一層的數據打印出來看看。

4. 確保輸入和輸出相連

檢查一下是不是輸入樣本都有正確的標籤。再把輸入數據打亂,看看輸出標籤是不是也會打亂。

5. 輸入和輸出之間的關係是不是太隨機

可能輸入和輸出之間的非隨機部分,與隨機部分相比太少了,例如股票就是這樣。換句話說,輸入和輸出之間的關聯不夠。對於這一點沒有萬全的辦法,因爲這得看數據的情況。

6. 數據庫中的噪音是否過多

我發生過這樣的錯誤,把一個食物網站的圖像弄壞了。錯誤的標籤太多,網絡沒法進行學習。手動檢查一些輸入樣本,看看標籤有沒有問題。

業界沒有統一的分水線,一篇論文曾在50%標籤錯誤的情況下,實現了高於50%的精度。

7. 打亂數據庫

如果數據庫沒有打亂,而是用標籤進行了排序,有可能會影響到網絡的學習。打亂數據庫的順序,防止這個問題。確保輸入和標籤一起打亂。

8. 減少類偏斜問題

A類圖像是不是比B類多出了一千倍?那你得平衡你的損失函數,或者嘗試其他類偏斜問題的解決方法。

9. 你有足夠的訓練例子嗎?

如果你從零訓練一個神經網絡,也就是說,沒有經過調試,你可能需要很多的數據。對於數據分類問題,很多人說每一類都需要一千個、甚至更多的圖像。

10. 確保一個批次的數據裏不包含單一標籤

在經過排序的數據庫中可能出現這個問題,例如,一萬個樣本包含同一個類別。這個很好解決,只要打亂排序就好了。

11. 減少mini-batch大小

一篇論文指出,一個非常大的mini-batch會減少模型泛化的能力。

增補1:使用標準數據庫(例如mnist和cifar10)

感謝 @hengcherkeng 網友的貼士:

測試新的神經網絡架構或者寫新代碼的時候,首先使用標準數據庫,而非你自己的數據。這是因爲這些數據庫有很多參考結果,都是可以解決的。這樣就防止了以下的問題:標籤噪音、訓練/測試分佈差別、數據庫比較困難等等。

二、數據歸一化/增強

12、把特徵歸一化

你把輸入歸一化了爲平均值爲0且方差爲1了嗎?

13、數據增強是否過度

增強帶有歸一化的效果。過度增強會帶來其他形式的歸一化(weight L2、Dropout 等等),可能導致網絡調試不足。

14、檢查預訓練模型的預調試

如果你使用的是預訓練模型,訓練的時候一定要使用跟模型相同的歸一化和預處理。例如,圖像像素應該在哪個範圍內,[0,1]、[-1,1]還是[0,255]?

15、檢查訓練/驗證/測試數據庫

CS231n 指出了一個常見漏洞:

「...任何預處理數據,例如數據平均值,都必須只在訓練數據中計算,然後應用到驗證/測試數據上。舉個例子,計算平均數,然後從數據庫的每一個圖像中減掉平均值,再將數據庫分割爲訓練/驗證/測試數據,這樣就錯了。」

另外,還需要在每一個樣本或者批次中檢查不同的預處理。

三、執行問題

乾貨 | 模型表現不好怎麼辦?37條妙計助你扭轉局勢

- 這一大坨就是你的機器學習系統。

- 把數據輸入這一大坨線性代數,然後等着答案吐出來。

- 如果答案錯了怎麼辦?

- 那就把這一大坨攪和攪和,直到答案對了爲止。 

16. 把大問題變成小問題

這有助於定位問題出在哪兒。舉個例子,如果目標輸出是一個目標類別或者座標,可以將預測僅限於目標類別。

17. 「隨機」尋找正確的損失

還是來自於傑出的 CS231n:以小參數開始,不用歸一化。例如,如果我們有10個類別,隨機意味着我們只有十分之一的時候能獲得正確類別,而且 Softmax 損失是正確類別的負對數概率:-ln(0.1) = 2.302。

然後,試試增加歸一化的強度,應該能增加損失函數。

18. 查一查你的損失函數

如果你執行自己的損失函數,檢查一下有沒有問題,增加單元測試。我的損失函數經常有些細小的錯誤,導致神經網絡的運行出現細微的偏差。

19. 確認損失輸入

如果你使用自己框架下的損失函數,一定要注意,輸入給它的數據得符合其預期。例如,在 PyTorch 裏我會混淆 NLLLoss 和 CrossEntropyLoss,這就犯了錯,因爲前者需要 softmax 輸入,而後者則不需要。

20. 調整損失權重

如果你的損失函數由若干個較小的損失函數構成,它們之間的相對大小必須正確。這可能需要測試不同損失權重的組合。

21. 監測其他度量

有時候,損失函數沒法最好地預測神經網絡的訓練是否良好。如果可以的話,使用精度等其他度量。

22. 測試任何定製層

神經網絡裏,你有沒有自己執行任何的層?重複檢查,確保它們運行正常。

23. 檢查「凍結」層或者變量

檢查一下是否不經意間,你解除了一些層或者變量的梯度更新,沒能及時獲得信息。

24. 增加網絡大小

可能你的神經網絡的表達力太小,不能描述目標函數。試試在完全聯接的層中,增加更多的層或者隱藏單元。

25. 檢查隱藏維度錯誤

如果你的輸入類似(k, H, W) = (64, 64, 64),很容易忽視跟錯誤維度有關的漏洞。在輸入維度使用特別的數字(例如在每一個維度都使用質數),檢查它們如何在網絡中傳播。

26. 嘗試梯度檢查

如果你手動執行梯度下降,梯度檢查能確保反向傳播運行正常。

四、訓練問題

乾貨 | 模型表現不好怎麼辦?37條妙計助你扭轉局勢

圖像中可以識別出來一輛汽車。

27. 用很小很小的數據庫

用一個很小的數據庫子集用於調試,確保運行正常。例如,只用一兩個例子進行訓練,看你的神經網絡能否學會區分這些例子。然後再在每一個類型增加例子。

28. 檢查權重初始化

如果不確定的話,初始化就用 Xavier 或者 He。另外,初始化有可能導致一個錯誤的區域最小值,所以要嘗試幾個不同的初始化方法,看看有沒有用。

29. 改變超參數

可能你用的超參數組有問題。如果可能的話,試試網格搜索。

30. 減少歸一化

過度歸一化可能讓網絡無法調試。減少一些歸一化,例如 dropout、批次常規、weight / bias L2 歸一化,等等。Jeremy Howard 在其傑出的課程「程序員深度學習實操」中,建議首先排除欠擬合。這意味着你必須充足地優化訓練數據,然後再去處理過度優化的問題。

31. 交給時間

可能你的神經網絡需要更多時間來訓練,才能做出有意義的預測。如果你的損失在穩健降低,那就再讓它多訓練一段時間。

32. 從訓練模式轉化爲測試模式

一些帶有 Batch Norm、Dropout 等其他層的框架,在訓練和測試的時候表現不同。轉換到合適的模式有助於神經網絡有效地預測。

33. 將訓練視覺化

- 監測每一層的初始化、權重和更新。確保它們的強度互相匹配。例如,參數更新的強度應該爲1-e3。

- 考慮 Tensorboard 和 Crayon 等視覺化庫。簡單來說,你還可以打印輸出權重、偏壓或者初始化。

- 注意層初始化的平均值有沒有大大超過0. 可以試試 Batch Norm 或者 ELU。

- 對於權重和偏壓的柱狀圖,網友 Deeplearning4j 這樣說道:

「關於權重,柱狀圖一段時間以後應該大致是一個高斯(正態)分佈。關於偏壓,柱狀圖基本上是從0開始,通常最後也會接近高斯分佈(長短期記憶網絡則是一個例外)。要留心趨近於正/負無窮的參數。要留心變得非常大的偏壓。如果類別分佈非常不平衡,這有時候就會發生在分類中的輸出層。」

- 檢查層更新,它們應該是高斯分佈。

34. 試試不同的優化器

你選的優化器應該不會妨礙神經網絡的訓練,除非你選的超參數特別有問題。但是,適合某一任務的優化器有助於在最短的時間內完成最多的訓練。看看介紹算法的論文,裏面應該說名該使用什麼優化器。如果沒有說的話,我傾向於使用 Adam 或者就用帶有 momentum 的 SGD。

35. 梯度消失與梯度爆炸

- 檢查層更新,因爲很大的值意味着梯度爆炸。梯度剪裁可能有用。

- 檢查層初始化。網友 Deeplearning4j 提供了很好的指引:「對於初始化,好的標準方差是在0.5到2.0的範圍內。如果遠遠超出了這個範圍,可能就是消失或者爆炸初始化。」

36. 增加或減少學習率

如果學習率低,模型的收斂會非常地慢。

如果學習率高,開始的損失會很快減少,但是可能很難找到一個滿意的答案。

可以拿你現在的學習率做一些小改動試試,乘以0.1或乘以10。

37. 消除NaN

訓練循環神經網絡時,如果看到NaN就問題大了。解決辦法包括:

- 減少學習率,尤其是如果前一百次迭代就出現NaN的話。

- 如果計算中包含除以0、求0或負數的自然對數,就會出現NaN。

- 一層層地檢查神經網絡,看看NaN是從哪兒出來的。

如果各位讀者還有什麼好辦法,歡迎在留言區分享,大家以開源共享的精神幫更多的人解決更多的問題。

via Slavv Blog,雷鋒網 AI 科技評論編譯

文章來源:雷鋒網