深度 | 你的神經網路不work? 這37個原因總有一款適合你!
大數據文摘作品,轉載要求見文末
作者 | Slav Ivanov (企業家/黑客)
編譯 | 朱璇、霍靜、笪潔瓊、崔雲柯
彼時,我手頭的神經網路訓練已持續了12個小時,各項指標顯示運轉良好。沒有一點點防備,就在剛才,突然提示:全部預測為零,一點有用的信息都沒有!
「到底哪裡出問題了?」 ——我自言自語,很是鬱悶。「該如何檢查神經網路模型輸出的信息是否有用(例如,預測所有輸出的平均值,還是看看準確度是不是很糟糕)」?
其實,影響神經網路訓練正常運轉的影響因素很多! 在經歷了多次調試後,我總結出了一些通用的經驗,特此整理成文,希望能夠給和我有一樣困惑的朋友們一點啟發:
目錄
0. 如何使用本指南?(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607#b6fb)
I. 數據集問題(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607#678a)
II. 數據歸一化/擴增問題(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607#86fe)
III. 執行問題(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607#95eb)
IV. 訓練問題(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607#74de)
0. 如何使用本指南?
其實,可能導致錯誤的影響因素有很多, 不過總有一些「出鏡率」比較高。如果出現問題,我通常從下面的列表開始:
1. 從一種可用於此類型數據的已知簡單模型開始試驗(比如用於圖像識別的VGG模型)。 如果可能,使用標準損失。
2. 關閉所有「鈴聲和口哨」(譯者註:即使用最基礎的模型),比如不再使用正則化和數據擴增。
3. 調模型時,請仔細檢查預處理,確保使用和我們訓練原始模型一樣的預處理。
4. 驗證輸入數據是否正確。
5. 從一個非常小的數據集(2-20個樣本)開始,先讓模型過度擬合,再逐漸增加更多的數據。
6. 逐漸添加之前被省略的部分:數據擴增/正則化,自定義損失函數,嘗試更複雜的模型。
如果上述內容還不能解決問題,那接下來,請繼續閱讀,我們之後會還有一份大型影響因素清單,建議逐一驗證。
I. 數據集問題
資料來源: http : //http://dilbert.com/strip/2014-05-07
1. 檢查輸入數據
檢查一下你輸入訓練模型的數據是否正確。之前,曾經好多次我都搞混了圖像的寬度和高度,還有的時候,我手誤輸入一堆多餘的零,還有,曾經發生過多次重複輸入同一批次數據的情況……
總之,記得仔細檢查一開始幾個批次輸入和輸出情況,儘可能保證看起來正常。
2. 隨機輸入驗證
嘗試往訓練項目中輸入一些隨機數據,然後看看模型報錯,和之前的報錯情況是否一致。 如果一致,那肯定是在模型的某個階段出了問題,將數據轉換成了垃圾。 之後,逐層調試,找到出錯的地方就好。
3. 檢查數據載入器
有時候,數據本身可能沒問題,出問題的可能是將數據輸入到網路的代碼。 因此,在任何操作之前,請列印第一層的輸入檢查檢查。
4. 確保輸入連接到輸出
檢查幾個輸入樣品是否有正確的標籤。 同時還要確保輸入樣本與輸出標籤的重新排序方式相同。
5. 輸入與輸出之間的隨機比例問題
如果模型中,輸入輸出之間的非隨機部分,相比隨機部分比例過小,那麼我們可以確定,輸入和輸出無關的可能性比較大。 因為這往往取決於數據的性質,目前,針對這個情況,我還沒找到更簡便的方式來檢測,畢竟這與數據本身的特質息息相關。
6. 數據集中是否有太多噪音?
之前有一次,我打算從食品站點上整理一組圖像數據集,放到我的神經網路模型,結果就碰到了這個問題。裡面很多數據都顯示損壞標籤,才影響到模型結果。建議手動檢查一些輸入樣本,看看它們顯示的標籤。
對於多少噪音才是神經網路訓練的臨界點目前仍有爭議,比如,這篇文章(https://arxiv.org/pdf/1412.6596.pdf) 顯示,在一定條件下,在使用了50%損壞標籤的MNIST數據集中,準確率仍可以達到50%以上。
7. 對數據集重新排序
如果數據集沒有重新排序,並且有特定的順序(按照標籤排序),這可能會對學習產生負面影響。 記得給數據集隨機重新排序,也別忘了將輸入和標籤用同樣的方式重新排序。
8. 減少標籤不平衡
圖像種類B和圖像種類A是1:1000嗎? 如果這樣,我們可能需要平衡損失功能或嘗試其他標籤不平衡數據的應對方法 (http://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/)。
9. 你的訓練數據夠多嗎?
從頭開始訓練一個神經網路,是需要大量數據的。 在圖像分類方面, 有人建議每個類別需要約1000張圖片或更多。(https://stats.stackexchange.com/a/226693/30773)。
10. 確保批次數據不為單一標籤
這可能發生在有序數據集中(即前一萬個樣本擁有同一個標籤)。 通過將數據集重新排序可輕鬆修復這個問題。
11.減少每個批次的容量
這篇文章(https://arxiv.org/abs/1609.04836)指出,擁有非常大的批次可以降低模型的泛化能力。
添加 1.使用標準數據集(例如mnist,cifar10)
感謝@ hengcherkeng提出這一點:
當測試新的網路架構或編寫新的代碼片段時,首先使用標準數據集,而不是自己的數據。 這樣,我們就可以參考前人的數據集總結,這樣做的好處是,不存在標籤噪音、訓練/測試分配差異、數據集難度過大等問題。
II. 數據歸一化/增強
12. 特徵標準化
你有沒有標準化你的輸入數據,它們是否具有零均值和單位標準差?
13. 你是否做了太多的數據擴增?
數據擴增具有正則化效果。 太多的數據擴增,再加上其他形式的正則化(比如weight L2, dropout等等),都可能導致網路擬合不足。
14. 檢查預訓練模型的預處理
如果您使用預先訓練好的模型,請確保您正在使用與該模型訓練時相同的規範化和預處理。 例如,圖像像素是在[0,1]、[-1,1]還是[0,255]的範圍內?
15. 檢查訓練集/驗證集/測試集的預處理
CS231n指出了一個常見的陷阱(http://cs231n.github.io/neural-networks-2/#datapre) :
「......任何預處理統計值(如數據均值)只能在訓練數據上計算,然後應用於驗證/測試數據。 例如,計算平均值並從整個數據集中的每個圖像中減去它,然後將數據分割成訓練集/驗證集/測試集將是一個錯誤。 「
另外,請檢查每個樣品或批次中是否使用了不同的預處理。
III.執行問題
資料來源: https://xkcd.com/1838/
16. 嘗試簡化問題
簡化問題能夠幫助你發現異常。如果目前你的模型輸出了對象的分類和坐標,那就嘗試只輸出對象的分類。
17. 「隨機」尋找正常範圍的損失
源自卓越的cs231n課程:用少量的參數來初始化,不加正則化。比如,如果我們有十個類,「隨機」意思是10%的時候我們會得到正確結果,softmax損失是負對數概率:-ln(0.1) = 2.302。
然後,再試著增加正則化的強度,從而增加損失。
18. 檢查你的損失函數
如果你自己實現了損失函數,那檢查bugs,再加上單位測試。之前,我的損失函數稍微有些偏差,降低了網路的性能。
19. 驗證損失的輸入
如果你正在使用「已有框架」提供的損失函數,那你一定要按照指定方法輸入指定數據。 在PyTorch里,我會弄混NLLLoss和CrossEntropyLoss,前者需要softmax輸入,但後者不需要。
20. 調整損失的權重
如果你的損失是由幾個小的損失函數組成的,確保他們的相關權重是合適的。這也許包括了測試幾種不同的權重組合。
21. 監測其他度量標準
有時候損失並不是最好的測量標準來衡量你的網路是否訓練良好。如果可以,可以使用其他的,比如準確率。
22. 測試每一個自定製網路層
你自己完成了網路里的層嗎?檢查,再檢查,確保這些層運行正確。
23. 檢查「凍結」的網路層或者變數
檢查你是不是無意間限制了可更新層與變數的更新。
24. 增加網路大小
也許你網路的指數級力度不足以描述目標函數。嘗試增加更多的層,或者全鏈接的隱藏單元數。
25. 檢查隱藏維錯誤
如果你的輸入是(k, H, W) = (64, 64, 64),那很容易錯過關於錯誤維度的錯誤。使用奇怪的數字設置輸入維度(比如,對不同的維度使用不同的素數),來檢查它們是怎麼在網路傳播。
26. 進行梯度檢查
如果你自己手動實現了梯度下降法,檢查梯度,以確保你的後向傳播運行良好。
IV.訓練問題
資料來源: http://carlvondrick.com/ihog/
27. 解決一個小的數據集
過擬合一個很小的數據子集,確保它可行。比如,用1到2個例子進行訓練,看看是否你的網路能分類正確。然後再每個類添加更多的例子。
28. 檢查權重的初始化
如果不確定,就使用Xavier或者He來初始化。初始化可能會把你引向一個有問題的最小局部,所以,你可以嘗試不同的初始化,看是否有幫助。
29.改變超參數
也許你使用的超參數集有問題。如果可以,可以嘗試http://scikit-learn.org/stable/modules/grid_search.html。
30.減少正則化
過度的正則化會讓網路擬合不足。嘗試減少過度的正則化,諸如,dropout,batch norm,權重/偏差 L2正則化,等等。在「實用深度學習程序員必讀」這門課中,Jeremy Howard建議先排查擬合不足。這意味著你先使訓練集過擬合,而且只有過擬合。
31. 給你的訓練網路多一點的時間
有時候並不是網路出現了問題,也有可能你太心急了。請在作出有價值的預測之前,給你的網路再多一些的訓練時間。如果這個過程中,如果你觀察到損失在穩定減少,那放輕鬆,給它再多一些的訓練時間吧。
32. 訓練模式與測試模式的轉換
某些框架的網路層,類似batch norm,dropout,它們的效果在訓練和測試模式是不一樣的。請選擇合適的模式,以確保你的網路預測更好。
33. 可視化訓練的過程
- 監控每層的激活函數,權重和更新情況。確保它們的值是對得上的。比如,參數(權重和偏差)的更新值應該是1-e3。
- 考慮諸如Tensorboard和Crayon的可視化庫。你還可以列印出來,檢查權重/偏差/激活函數值。
- 注意查找網路層的激活函數值,均值遠遠大於0的那些。嘗試Batch Norm或者ELUs。
- Deeplearning4j (https://deeplearning4j.org/visualization#usingui)描述了,理想狀態的權重和偏差柱狀圖:
「拿權重來說,柱狀圖應該呈現近似高斯分布的特徵。而偏差,在柱狀圖中應該從0開始,最後也近似高斯分布(LSTM是個例外)。注意觀察那些趨於正負無窮大的參數,以及那些變的特別大的偏差值。有時候會發生在分類的輸出層,如果類的分布很不平衡的話。」
- 檢查一下層更新,它們也應該是高斯分布。
34. 嘗試不同的優化器
優化器的選擇上,要注意,不要選對你的訓練可能造成很大影響的那些。好的優化器可以讓你在最短的時間達到最好的效果。許多描述演算法的論文都有說明相關的優化器,如果沒找到,我一般使用Adam或者帶勢的SGD。
可以查看這篇很好的文章(http://ruder.io/optimizing-gradient-descent/),作者是Sebastian Ruder,裡面你會知道很多關於梯度下降優化器。
35. 逐一檢查那些爆炸性增長/消失不見的梯度
- 檢查層的更新,如果出現很大的值,那可能預示著爆炸性增長的梯度值。梯度剪切會有幫助。檢查層的激活函數值。Deeplearning4j一文中(https://deeplearning4j.org/visualization#usingui),給出了不錯的建議:「激活函數值好的標準偏差範圍大致在0.5 到2.0,如果超出這個範圍過多,則可能會出現激活函數值消失不見、或爆炸性增長的情況。「
36. 增加/減少學習率
學習率過低,可能會導致你的模型收斂的很慢。而學習率過高,也會有一些不良影響————起初損失快速減少,但是最後卻不易找到良好解決辦法。建議改變你的學習率,可以嘗試乘以0.1或10。
37. 解決非數值數
如果訓練RNNs,出現非數值數可能是個需要關注的問題。建議你嘗試下列方式改進這個情況:
- 減少學習率,尤其是在開始的100個回合里有非數值數時候。
- 非數值數來自於除以0,或者0與負數的自然對數。
- Russell Steward也給出了很多參考片方法,來應對非數值數(http://russellsstewart.com/notes/0.html)。
- 嘗試逐層評估你的網路,找出產生非數值數的確切位置。
原文鏈接:https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607
推薦閱讀:
※大數據進階-—— 時光和努力的意義
※自主創新,打造一站式地理雲平台
※大數據是什麼
※AI技術講座精選:機器學習梯度下降演算法(包括其變式演算法)簡介
※【巡洋艦首發】有趣的機器學習 第一章:最簡明入門指南