神經(jīng)網(wǎng)絡(luò)調(diào)試手冊:從數(shù)據(jù)集與神經(jīng)網(wǎng)絡(luò)說起
近日,hackernoon 上出現(xiàn)了一篇題為《How to debug neural networks. Manual.》的文章,從數(shù)據(jù)集與神經(jīng)網(wǎng)絡(luò)兩個方面分享了作者 Andrey Nikishaev 在調(diào)試神經(jīng)網(wǎng)絡(luò)方面的實踐心得。
調(diào)試神經(jīng)網(wǎng)絡(luò)是一項艱難的工作,專家也不例外。面對數(shù)百萬的參數(shù),任何一個小變動都可能使你前功盡棄。沒有調(diào)試和可視化,所有你的行動就像拋硬幣,而且更糟糕的是還浪費時間。下面是我搜集的實踐匯總,希望有助于你提早發(fā)現(xiàn)問題。
一、數(shù)據(jù)集問題
1. 嘗試使用小數(shù)據(jù)集過擬合你的模型
一般來說神經(jīng)網(wǎng)絡(luò)應(yīng)該在數(shù)百次迭代中過擬合你的數(shù)據(jù)。如果你的損失值不下降,那問題存在于更深層次。
2. 使用迭代邏輯解決問題
嘗試構(gòu)建最簡單的網(wǎng)絡(luò)解決你的主要問題,接著一步一步擴展到全局問題。比如,你正在創(chuàng)建風(fēng)格遷移網(wǎng)絡(luò),首先在一張圖像上訓(xùn)練你的腳本遷移風(fēng)格。如果奏效,再接著創(chuàng)建用于任何圖像的風(fēng)格遷移模型。
3. 使用具有扭曲的平衡數(shù)據(jù)集
比如訓(xùn)練分類數(shù)據(jù)的網(wǎng)絡(luò),你的訓(xùn)練數(shù)據(jù)應(yīng)該對每一分類具有相同數(shù)量的輸入。其他情況下則存在分類過擬合的可能性。神經(jīng)網(wǎng)絡(luò)對于所有的扭曲并非恒定不變,因此需要你對它們進行專門訓(xùn)練。制造輸入扭曲將會提升網(wǎng)絡(luò)準(zhǔn)確度。
4. 網(wǎng)絡(luò)容量 vs 數(shù)據(jù)集大小
你的數(shù)據(jù)集應(yīng)足夠大,以便網(wǎng)絡(luò)用來學(xué)習(xí)。如果你的數(shù)據(jù)集小,而網(wǎng)絡(luò)很大,那么它會停止學(xué)習(xí)(某些情況下也會為大量的不同輸入輸出相同結(jié)果)。如果你有大數(shù)據(jù),而網(wǎng)絡(luò)很小,那么你將會看到損失值的跳躍,因為網(wǎng)絡(luò)容量無法存儲如此多的信息。
5. 使用均值中心化(mean centering)
這將會從你的網(wǎng)絡(luò)中移除噪音數(shù)據(jù),提升訓(xùn)練性能,同時某些情況下有助于解決 NaN 問題。但是記住,如果你有時序數(shù)據(jù),那么你應(yīng)該使用批而不是全局中心化。
二、神經(jīng)網(wǎng)絡(luò)問題
1. 首先嘗試較簡單的模型
我在很多案例中看到人們首先嘗試一些標(biāo)準(zhǔn)的大型網(wǎng)絡(luò),比如 ResNet-50、VGG19 等,但是接著發(fā)現(xiàn)他們的問題通過僅有若干層的網(wǎng)絡(luò)也能解決。因此如果你沒有標(biāo)準(zhǔn)問題,首先從小網(wǎng)絡(luò)開始吧。你添加的數(shù)據(jù)越多,模型就越難訓(xùn)練,因此從小網(wǎng)絡(luò)開始會更省時。你也應(yīng)該記住,大網(wǎng)絡(luò)需要更大的內(nèi)存與更多的操作。
2. 可視化是必須的
如果你正使用 TensorFlow,一定要從 TensorBoard 開始。如果沒有,嘗試為你的框架尋找一些可視化工具,或者自己動手編寫。這將對于你發(fā)現(xiàn)訓(xùn)練早期階段的問題非常有幫助。你必須可視化的事情有:損失值、權(quán)重直方圖、變量和梯度。如果你正在做計算機視覺,那要一直可視化過濾器從而理解網(wǎng)絡(luò)實際上看到了什么。
3. 權(quán)重初始化
如果你錯誤設(shè)置權(quán)重,由于零梯度,或者所有神經(jīng)元的類似更新等,你的網(wǎng)絡(luò)將變得無法訓(xùn)練。同樣你也應(yīng)該記住權(quán)重與學(xué)習(xí)率是成對的,因此高學(xué)習(xí)率和大權(quán)重可以導(dǎo)致 NaN 問題。
對于一些網(wǎng)絡(luò)使用 1e-2–1e-3 左右的高斯分布初始化軟件已經(jīng)足夠。
對于深度網(wǎng)絡(luò)這毫無用處,因為你的權(quán)重彼此相乘了很多次,將會產(chǎn)生幾乎消除反向傳播上的梯度的非常小的數(shù)值。多虧了 Ioffe 和 Szegedy,現(xiàn)在我們有了批歸一化,緩解了令人頭疼的大量問題。
4. 使用標(biāo)準(zhǔn)網(wǎng)絡(luò)解決標(biāo)準(zhǔn)問題
存在大量的預(yù)訓(xùn)練模型,你可以正確使用它們。在一些情況中是這樣,或者你可以使用調(diào)整技術(shù)節(jié)約訓(xùn)練時間。主要的想法是絕大多數(shù)網(wǎng)絡(luò)容量對于不同問題是相同的。比如,如果我們討論計算機視覺,它將會包含對于所有圖像一樣的線、點、角,并且你不需要再訓(xùn)練它們。
5. 把衰減用于學(xué)習(xí)率
這幾乎每次都會給你一個提升。TensorFlow 中有大量的不同衰減調(diào)度器
(https://www.tensorflow.org/versions/r0.12/api_docs/python/train/decaying_the_learning_rate)。
6. 使用網(wǎng)格搜索、隨機搜索或配置文件調(diào)整超參數(shù)
不要試圖手動調(diào)整所有參數(shù),這很耗時,效率低下。我經(jīng)常使用全局配置調(diào)整所有參數(shù),并在運行完檢查結(jié)果后看看在哪個方向上應(yīng)該進一步調(diào)查。如果這個方法沒有幫助,你可以試一下隨機搜索或網(wǎng)格搜索。
7. 激活函數(shù)
(1) 梯度消失問題
一些激活函數(shù),比如 Sigmoid 和 Tanh 正在遭受飽和問題。在其極限時,它們的導(dǎo)數(shù)接近于零,這將會消除梯度和學(xué)習(xí)過程。因此檢查不同的函數(shù)比較好。現(xiàn)在標(biāo)準(zhǔn)的激活函數(shù)是 ReLU。同樣這一問題也出現(xiàn)在一個非常深度或者循環(huán)的網(wǎng)絡(luò)中,比如你有 150 層,所有的激活值是 0.9,那么 0.9¹⁵⁰ = 0,000000137。但是正如上文所說,批歸一化將有助于解決這一問題,殘差層也是。
(2) 不是零均值的激活值
比如 Sigmoid、ReLU 函數(shù)就不是零均值的。這意味著訓(xùn)練期間所有你的梯度將全部是正或負(fù),并會引發(fā)學(xué)習(xí)問題。這就是為什么我們使用零均值的輸入數(shù)據(jù)。
(3) Dead ReLUs
標(biāo)準(zhǔn)的 ReLU 函數(shù)也不完美。對于負(fù)數(shù) ReLU 給出零的問題意味著它們將不會被激活,因此你的神經(jīng)元的某些部分將會死掉并永不再用。這之所以能發(fā)生是因為高學(xué)習(xí)率和錯誤的權(quán)重初始化。如果參數(shù)調(diào)整沒有幫助,那么你可以試一下 Leaky ReLU、PReLU、ELU 或 Maxout,它們沒有這一問題。
(4) 梯度爆炸
這一問題與梯度消失相同,除卻每一步梯度變的越來越大。一個主要的解決辦法是使用梯度剪裁,為梯度設(shè)置基本的硬限制。
8. 深度網(wǎng)絡(luò)的精確度降級
從一些點上真正深化網(wǎng)絡(luò)的問題開始表現(xiàn)為一個壞手機,因此增加更多層降低了網(wǎng)絡(luò)精確度。解決辦法是使用殘差層把輸入的一些部分傳遞到所有層。
原文:https://hackernoon.com/how-to-debug-neural-networks-manual-dc2a200f10f2
【本文是51CTO專欄機構(gòu)“機器之心”的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】