一文总结调参技巧
調參數是深度學習工作中,必不可少的一步。
“得參數者,得天下“
那么,調參的方法常見的有哪些?小編為您總結一番~
01尋找合適的學習率(learning rate)
學習率是一個非常非常重要的超參數在面對不同規模、不同batch-size、不同優化方式、不同數據集時,學習率的最合適的值都是不確定的,所以,我們無法光憑經驗來準確地確定學習率的值。策略:在訓練中不斷尋找最合適當前狀態的學習率。下圖利用fastai中的lr_find()函數尋找合適的學習率,根據下方的學習率-損失曲線得到此時合適的學習率為1e-2。
推薦一篇fastai首席設計師「Sylvain Gugger」的一篇博客:How Do You Find A Good Learning Rate[1]以及相關的論文Cyclical Learning Rates for Training Neural Networks[2]。
02learning-rate與batch-size的關系
一般來說,越大的batch-size使用越大的學習率。越大的batch-size意味著我們學習的時候,收斂方向的confidence越大。小的batch-size則顯得比較雜亂,毫無規律性,并且相比大批次,批次小的情況下無法照顧到更多的情況,則需要小的學習率來保證不至于出錯。如下圖損失Loss與學習率Lr的關系:
在顯存足夠的條件下,最好采用較大的batch-size進行訓練,找到合適的學習率后,可以加快收斂速度。另外,較大的batch-size可以避免batch normalization出現的一些小問題,參考如下Pytorch庫Issue
03權重初始化
權重初始化的適用并不頻繁。大都適用的是預訓練模型。但是對于沒有預訓練模型的領域,需要自己初始化權重,或者在模型中去初始化神經網絡最后那幾個全連接層的權重。常用的權重初始化算法是「kaiming_normal」或者「xavier_normal」。
相關論文:
Delving deep into rectifiers: Surpassing human-level performance on ImageNet classificationUnderstanding the difficulty of training deep feedforward neural networksXavier初始化論文He初始化論文
不初始化可能會減慢收斂速度,影響收斂效果。
總結幾種初始化方法:uniform均勻分布初始化:
Xavier初始法,適用于普通激活函數(tanh, sigmoid):
He初始化,適用于ReLU:
normal高斯分布初始化, 其中stdev為高斯分布的標準差,均值設為0:
Xavier初始法,適用于普通激活函數 (tanh,sigmoid):
svd初始化:對RNN有比較好的效果。參考論文:https://arxiv.org/abs/1312.6120[8]
04Dropout
Dropout是指在深度學習網絡的訓練過程中,對于神經網絡單元,按照一定的概率將其暫時從網絡中丟棄。對于隨機梯度下降來說,由于是隨機丟棄,故而每一個mini-batch都在訓練不同的網絡。Dropout一般適合于全連接層部分,而卷積層由于其參數并不是很多,所以不需要dropout,加上的話對模型的泛化能力并沒有太大的影響。
05數據集處理
主要有「數據篩選」 以及 「數據增強」fastai中的圖像增強技術為什么相對比較好[9]
06難例挖掘 hard-negative-mining
分析模型難以預測正確的樣本,給出針對性方法。
07多模型融合
Ensemble是論文刷結果的終極核武器,深度學習中一般有以下幾種方式
同樣的參數,不同的初始化方式不同的參數,通過cross-validation,選取最好的幾組同樣的參數,模型訓練的不同階段,即不同迭代次數的模型。不同的模型,進行線性融合. 例如RNN和傳統模型.提高模型性能和魯棒性大法:probs融合 和 投票法。
假設這里有model 1, model 2, model 3,可以這樣融合:
1. model1 probs + model2 probs + model3 probs ==> final label
2. model1 label , model2 label , model3 label ==> voting ==> final label
3. model1_1 probs + ... + model1_n probs ==> mode1 label, model2 label與model3獲取的label方式與1相同 ==> voting ==> final label
第三個方式的啟發來源于,如果一個model的隨機種子沒有固定,多次預測得到的結果可能不同。
以上方式的效果要根據label個數,數據集規模等特征具體問題具體分析,表現可能不同,方式無非是probs融合和投票法的單獨使用or結合。
08差分學習率與遷移學習
遷移學習,一種很常見的深度學習技巧,利用很多預訓練的經典模型直接去訓練我們自己的任務。雖然說領域不同,但是在學習權重的廣度方面,兩個任務之間還是有聯系的。
由上圖,用「model A」訓練好的模型權重訓練我們自己的模型權重(「Model B」),其中,modelA可能是ImageNet的預訓練權重,而ModelB則是我們自己想要用來識別貓和狗的預訓練權重。
神經網絡(如下圖)一般分為三個部分,輸入層,隱含層和輸出層,隨著層數的增加,神經網絡學習到的特征越抽象。
因此,下圖中的卷積層和全連接層的學習率也應該設置的不一樣,一般來說,卷積層設置的學習率應該更低一些,而全連接層的學習率可以適當提高。
差分學習率:在不同的層設置不同的學習率,可以提高神經網絡的訓練效果,具體的介紹可以查看下方的連接。
余弦退火(cosine annealing)和熱重啟的隨機梯度下降「余弦」就是類似于余弦函數的曲線,「退火」就是下降,「余弦退火」就是學習率類似余弦函數慢慢下降。「熱重啟」就是在學習的過程中,「學習率」慢慢下降然后突然再「回彈」(重啟)然后繼續慢慢下降。兩個結合起來就是下方的學習率變化圖
相關論文SGDR: Stochastic Gradient Descent with Warm Restarts
09嘗試過擬合一個小數據集
這是一個經典的小trick了,但是很多人并不這樣做,可以嘗試一下。關閉正則化/隨機失活/數據擴充,使用訓練集的一小部分,讓神經網絡訓練幾個周期。確保可以實現零損失,如果沒有,那么很可能什么地方出錯了。
10多尺度訓練
多尺度訓練是一種「直接有效」的方法,通過輸入不同尺度的圖像數據集,因為神經網絡卷積池化的特殊性,讓神經網絡充分地學習不同分辨率下圖像的特征,可以提高機器學習的性能。處理過擬合效應,在圖像數據集不是特別充足的情況下,可以先訓練小尺寸圖像,然后增大尺寸并再次訓練相同模型,這樣的思想在Yolo-v2的論文中也提到過:
多尺度訓練并不是適合所有的深度學習應用,多尺度訓練可以算是特殊的數據增強方法,在圖像大小做了調整。
11Cross Validation 交叉驗證
在李航的統計學方法中說到,交叉驗證往往是對實際應用中「數據不充足」而采用的,基本目的就是重復使用數據。
交叉驗證只針對訓練集和驗證集。交叉驗證是Kaggle比賽中特別推崇的一種技巧,我們經常使用的是5-折(5-fold)交叉驗證,將訓練集分成5份,隨機挑一份做驗證集其余為訓練集,循環5次,這種比較常見計算量也不是很大。還有一種叫做leave-one-out cross validation
留一交叉驗證,這種交叉驗證就是n-折交叉,n表示數據集的容量,(適合數據量比較小的情況)
12優化算法
按理說不同的優化算法適合于不同的任務,不過我們大多數采用的優化算法還是是adam和SGD+monmentum。Adam 可以解決 loss 降不下去的情況,但是Adam和L2正則結合會產生的復雜效果。adam的相比SGD,收斂快,但泛化能力差,更優結果似乎需要精調SGD。adam,adadelta等, 在小數據上,我這里實驗的效果不如sgd, sgd收斂速度會慢一些,但是最終收斂后的結果,一般都比較好。如果使用sgd的話,可以選擇從1.0或者0.1的學習率開始,隔一段時間,在驗證集上檢查一下,如果cost沒有下降,就對學習率減半. 我看過很多論文都這么搞,我自己實驗的結果也很好. 當然,也可以先用ada系列先跑,最后快收斂的時候,更換成sgd繼續訓練.同樣也會有提升.據說adadelta一般在分類問題上效果比較好,adam在生成問題上效果比較好。adam收斂雖快但是得到的解往往沒有sgd+momentum得到的解更好,如果不考慮時間成本的話還是用sgd吧。
adam是不需要特別調lr,sgd要多花點時間調lr和initial weights。
13數據預處理方式
zero-center ,常用.
PCA whitening,較少應用。
14訓練技巧
梯度歸一化,即算出來的梯度除以minibatch sizeclip c(梯度裁剪): 限制最大梯度,其實是value = sqrt(w1^2+w2^2….),如果value超過了閾值,就算一個衰減系系數,讓value的值等于閾值: 5,10,15dropout對小數據防止過擬合有很好的效果,值一般設為0.5小數據上dropout+sgd在我的大部分實驗中,效果提升都非常明顯.因此可能的話,建議一定要嘗試一下。dropout的位置比較有講究, 對于RNN,建議放到輸入->RNN與RNN->輸出的位置.關于RNN如何用dropout,可以參考這篇論文:http://arxiv.org/abs/1409.2329[15]除了gate之類的地方,需要把輸出限制成0-1之外,盡量不要用sigmoid,可以用tanh或者relu之類的激活函數.sigmoid函數在-4到4的區間里,才有較大的梯度。之外的區間,梯度接近0,很容易造成梯度消失問題。輸入0均值,sigmoid函數的輸出不是0均值的。rnn的dim和embdding size,一般從128上下開始調整. batch size,一般從128左右開始調整. batch size合適最重要,并不是越大越好.word2vec初始化,在小數據上,不僅可以有效提高收斂速度,也可以可以提高結果.盡量對數據做shuffleLSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的結果,來自這篇論文(:http://jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)實驗設成1.0,可以提高收斂速度.實際使用中,不同的任務,可能需要嘗試不同的值.Batch Normalization據說可以提升效果,(參考論文:Accelerating Deep Network Training by Reducing Internal Covariate Shift)如果你的模型包含全連接層(MLP),并且輸入和輸出大小一樣,可以考慮將MLP替換成Highway Network,我嘗試對結果有一點提升,建議作為最后提升模型的手段,原理很簡單,就是給輸出加了一個gate來控制信息的流動,(詳細介紹請參考論文: http://arxiv.org/abs/1505.00387[17])來自@張馨宇的技巧:一輪加正則,一輪不加正則,反復進行。在數據集很大的情況下,一上來就跑全量數據。建議先用 1/100、1/10 的數據跑一跑,對模型性能和訓練時間有個底,外推一下全量數據到底需要跑多久。在沒有足夠的信心前不做大規模實驗。subword 總是會很穩定地漲點,只管用就對了。GPU 上報錯時盡量放在 CPU 上重跑,錯誤信息更友好。例如 GPU 報 "ERROR:tensorflow:Model diverged with loss = NaN" 其實很有可能是輸入 ID 超出了 softmax 詞表的范圍。在確定初始學習率的時候,從一個很小的值(例如 1e-7)開始,然后每一步指數增大學習率(例如擴大1.05 倍)進行訓練。訓練幾百步應該能觀察到損失函數隨訓練步數呈對勾形,選擇損失下降最快那一段的學習率即可。補充一個rnn trick,仍然是不考慮時間成本的情況下,batch size=1是一個很不錯的regularizer, 起碼在某些task上,這也有可能是很多人無法復現alex graves實驗結果的原因之一,因為他總是把batch size設成1。注意實驗的可復現性和一致性,注意養成良好的實驗記錄習慣 ==> 不然如何分析出實驗結論。超參上,learning rate 最重要,推薦了解 cosine learning rate 和 cyclic learning rate,其次是 batchsize 和 weight decay。當你的模型還不錯的時候,可以試著做數據增廣和改損失函數錦上添花了。參考
關于訓練神經網路的諸多技巧Tricks\(完全總結版\)[18]你有哪些deep learning(rnn、cnn)調參的經驗?[19]Bag of Tricks for Image Classification with Convolutional Neural Networks[20]trick 合集 1Must Know Tips/Tricks in Deep Neural Networks[21]trick 合集 233條神經網絡訓練秘技[22]trick 合集 326秒單GPU訓練CIFAR10[23]工程實踐Batch Normalization[24],雖然玄學,但是養活了很多煉丹師
總結
- 上一篇: 深度学习之表面缺陷识别
- 下一篇: Mask R-CNN为什么“家喻户晓”