深度學習訓練的小技巧,調參經驗(轉)


經常會被問到你用深度學習訓練模型時怎么樣改善你的結果呢?然后每次都懵逼了,一是自己懂的不多,二是實驗的不多,三是記性不行忘記了。所以寫這篇博客,記錄下別人以及自己的一些經驗。

Ilya Sutskever(Hinton的學生)講述了有關深度學習的見解及實用建議:

 

獲取數據:確保要有高質量的輸入/輸出數據集,這個數據集要足夠大、具有代表性以及擁有相對清楚的標簽。缺乏數據集是很難成功的。

預處理:將數據進行集中是非常重要的,也就是要使數據均值為0,從而使每個維度的每次變動為1。有時,當輸入的維度隨量級排序變化時,最好使用那個維度的log(1+x)。基本上,重要的是要找到一個0值的可信編碼以及自然分界的維度。這樣做可使學習工作得更好。情況就是這樣的,因為權值是通過公式來更新的:wij中的變化 \propto xidL/dyj(w表示從層x到層y的權值,L是損失函數)。如果x的均值很大(例如100),那么權值的更新將會非常大,並且是相互關聯的,這使得學習變得低劣而緩慢。保持0均值和較小的方差是成功的關鍵因素。

批處理:在如今的計算機上每次只執行一個訓練樣本是很低效的。反之如果進行的是128個例子的批處理,效率將大幅提高,因為其輸出量是非常可觀的。事實上使用數量級為1的批處理效果不錯,這不僅可獲得性能的提升同時可降低過度擬合;不過這有可能會被大型批處理超越。但不要使用過大的批處理,因為有可能導致低效和過多過度擬合。所以我的建議是:根據硬件配置選取適合的批處理規模,量力而為會更加高效。

梯度歸一化:根據批處理的大小來拆分梯度。這是一個好主意,因為如果對批處理進行倍增(或倍減),無需改變學習率(無論如何,不要太多)。

學習率計划:從一個正常大小的學習率(LR)開始,朝着終點不斷縮小。

1LR的典型取值是0.1,令人驚訝的是,對於大量的神經網絡問題來說,0.1是學習率的一個很好的值。通常學習率傾向於更小而非更大。
使用一個驗證集——一個不進行訓練的訓練集子集,來決定何時降低學習率以及何時停止訓練(例如當驗證集的錯誤開始增多的時候)。
學習率計划的實踐建議:若發現驗證集遭遇瓶頸,不妨將LR除以2(或5),然后繼續。最終,LR將會變得非常小,這也到了停止訓練的時候了。這樣做可以確保在驗證性能受到損害的時候,你不會擬合(或過度擬合)訓練數據。降低LR是很重要的,通過驗證集來控制LR是個正確的做法。

但最重要的是要關注學習率。一些研究人員(比如Alex Krizhevsky)使用的方法是,監視更新范數和權值范數之間的比率。比率取值大約為10¯³。如果取值過小,那么學習會變得非常慢;如果取值過大,那么學習將會非常不穩定甚至失敗。

權值初始化。關注權值在學習開始時的隨機初始化。

如果想偷懶,不妨試試0.02*randn(num_params)。這個范圍的值在許多不同的問題上工作得很好。當然,更小(或更大)的值也值得一試。
如果它工作得不好(例如是一個非常規的和/或非常深的神經網絡架構),那么需要使用init_scale/sqrt(layer_width)*randn來初始化每個權值矩陣。在這種情況下,init_scale應該設置為0.1或者1,或者類似的值。
對於深度且循環的網絡,隨機初始化是極其重要的。如果沒有處理好,那么它看起來就像沒有學習到任何東西。我們知道,一旦條件都設置好了,神經網絡就會學習。
一個有趣的故事:多年來,研究人員相信SGD不能訓練來自隨機初始化的深度神經網絡。每次嘗試都以失敗告終。令人尷尬的是,他們沒有成功是因為使用“小的隨機權值”來進行初始化,雖然小數值的做法在淺度網絡上工作得非常好,但在深度網絡上的表現一點也不好。當網絡很深時,許多權值矩陣之間會進行乘積,所以不好的結果會被放大。
但如果是淺度網絡,SGD可以幫助我們解決該問題。

所以關注初始化是很有必要的。嘗試多種不同的初始化,努力就會得到回報。如果網絡完全不工作(即沒法實施),繼續改進隨機初始化是正確的選擇。

如果正在訓練RNN或者LSTM,要對梯度(記得梯度已除以批量大小)范數使用一個硬約束。像15或者5這樣的約束在我個人的實驗中工作得很好。請將梯度除以批處理大小,再檢查一下它的范數是否超過15(或5)。如果超過了,將它縮小到15(或5)。這個小竅門在RNN和LSTM的訓練中發揮着巨大作用,不這樣做的話,爆炸性的梯度將會導致學習失敗,最后不得不使用像1e-6這樣微小而無用的學習率。

數值梯度檢查:如果沒有使用過Theano或者Torch,梯度實現只能親力親為了。在實現梯度的時候很容易出錯,所以使用數值梯度檢查是至關重要的。這樣做會讓你對自己的代碼充滿信心。調整超級參數(比如學習率和初始化)是非常有價值的,因此好刀要用在刀刃上。

如果正在使用LSTM同時想在具有大范圍依賴的問題上訓練它們,那么應該將LSTM遺忘關口的偏差初始化為較大的值。默認狀態下,遺忘關口是S型的全部輸入,當權值很小時,遺忘關口會被設置為0.5,這只能對部分問題有效。這是對LSTM初始化的一個警示。

數據增加(Data augmentation):使用算法來增加訓練實例數量是個有創意的做法。如果是圖像,那么應該轉換和旋轉它們;如果是音頻,應該將清晰的部分和所有類型的雜音進行混合處理。數據添加是一門藝術(除非是在處理圖像),這需要一定的常識。

dropout:dropout提供了一個簡單的方法來提升性能。記得要調整退出率,而在測試時不要忘記關閉dropout,然后對權值求乘積(也就是1-dropout率)。當然,要確保將網絡訓練得更久一點。不同於普通訓練,在進入深入訓練之后,驗證錯誤通常會有所增加。dropout網絡會隨着時間推移而工作得越來越好,所以耐心是關鍵。

綜合(Ensembling)。訓練10個神經網絡,然后對其預測數據進行平均。該做法雖然簡單,但能獲得更直接、更可觀的性能提升。有人可能會困惑,為什么平均會這么有效?不妨用一個例子來說明:假如兩個分類器的錯誤率為70%,如果其中一個的正確率保持較高,那么平均后的預測會更接近正確結果。這對於可信網絡的效果會更加明顯,當網絡可信時結果是對的,不可信時結果是錯的。

(下面幾點是上面的簡化版)

 

1:准備數據:務必保證有大量、高質量並且帶有干凈標簽的數據,沒有如此的數據,學習是不可能的
2:預處理:這個不多說,就是0均值和1方差化
3:minibatch:建議值128,1最好,但是效率不高,但是千萬不要用過大的數值,否則很容易過擬合
4:梯度歸一化:其實就是計算出來梯度之后,要除以minibatch的數量。這個不多解釋
5:下面主要集中說下學習率
5.1:總的來說是用一個一般的學習率開始,然后逐漸的減小它
5.2:一個建議值是0.1,適用於很多NN的問題,一般傾向於小一點。
5.3:一個對於調度學習率的建議:如果在驗證集上性能不再增加就讓學習率除以2或者5,然后繼續,學習率會一直變得很小,到最后就可以停止訓練了。
5.4:很多人用的一個設計學習率的原則就是監測一個比率(每次更新梯度的norm除以當前weight的norm),如果這個比率在10-3附近,如果小於這個值,學習會很慢,如果大於這個值,那么學習很不穩定,由此會帶來失敗。
6:使用驗證集,可以知道什么時候開始降低學習率,和什么時候停止訓練。
7:關於對weight初始化的選擇的一些建議:
7.1:如果你很懶,直接用0.02*randn(num_params)來初始化,當然別的值你也可以去嘗試
7.2:如果上面那個不太好使,那么久依次初始化每一個weight矩陣用init_scale / sqrt(layer_width) * randn,init_scale可以被設置為0.1或者1
7.3:初始化參數對結果的影響至關重要,要引起重視。
7.4:在深度網絡中,隨機初始化權重,使用SGD的話一般處理的都不好,這是因為初始化的權重太小了。這種情況下對於淺層網絡有效,但是當足夠深的時候就不行了,因為weight更新的時候,是靠很多weight相乘的,越乘越小,有點類似梯度消失的意思(這句話是我加的)
8:如果訓練RNN或者LSTM,務必保證gradient的norm被約束在15或者5(前提還是要先歸一化gradient),這一點在RNN和LSTM中很重要。
9:檢查下梯度,如果是你自己計算的梯度。
10:如果使用LSTM來解決長時依賴的問題,記得初始化bias的時候要大一點
12:盡可能想辦法多的擴增訓練數據,如果使用的是圖像數據,不妨對圖像做一點扭轉啊之類的,來擴充數據訓練集合。
13:使用dropout
14:評價最終結果的時候,多做幾次,然后平均一下他們的結果。
 
 
原文地址:https://blog.csdn.net/yanhx1204/article/details/79625382


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM