你有哪些deep learning(rnn、cnn)調參的經驗?


訓練技巧對深度學習來說是非常重要的,作為一門實驗性質很強的科學,同樣的網路結構使用不同的訓練方法訓練,結果可能會有很大的差異。這裡我總結了近一年來的煉丹心得,分享給大家,也歡迎大家補充指正。

參數初始化。

下面幾種方式,隨便選一個,結果基本都差不多。但是一定要做。否則可能會減慢收斂速度,影響收斂結果,甚至造成Nan等一系列問題。

下面的n_in為網路的輸入大小,n_out為網路的輸出大小,n為n_in或(n_in+n_out)*0.5

Xavier初始法論文:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

He初始化論文:https://arxiv.org/abs/1502.01852

  • uniform均勻分布初始化:
    w = np.random.uniform(low=-scale, high=scale, size=[n_in,n_out])
    • Xavier初始法,適用於普通激活函數(tanh,sigmoid):scale = np.sqrt(3/n)
    • He初始化,適用於ReLU:scale = np.sqrt(6/n)
  • normal高斯分布初始化:
    w = np.random.randn(n_in,n_out) * stdev # stdev為高斯分布的標準差,均值設為0
    • Xavier初始法,適用於普通激活函數 (tanh,sigmoid):stdev = np.sqrt(n)
    • He初始化,適用於ReLU:stdev = np.sqrt(2/n)
  • svd初始化:對RNN有比較好的效果。參考論文:https://arxiv.org/abs/1312.6120

數據預處理方式

  • zero-center ,這個挺常用的.
    X -= np.mean(X, axis = 0) # zero-center
    X /= np.std(X, axis = 0) # normalize
  • PCA whitening,這個用的比較少.

訓練技巧

  • 要做梯度歸一化,即算出來的梯度除以minibatch size
  • clip c(梯度裁剪): 限制最大梯度,其實是value = sqrt(w1^2+w2^2….),如果value超過了閾值,就算一個衰減系係數,讓value的值等於閾值: 5,10,15
  • dropout對小數據防止過擬合有很好的效果,值一般設為0.5,小數據上dropout+sgd在我的大部分實驗中,效果提升都非常明顯.因此可能的話,建議一定要嘗試一下。 dropout的位置比較有講究, 對於RNN,建議放到輸入-&>RNN與RNN-&>輸出的位置.關於RNN如何用dropout,可以參考這篇論文:http://arxiv.org/abs/1409.2329
  • adam,adadelta等,在小數據上,我這裡實驗的效果不如sgd, sgd收斂速度會慢一些,但是最終收斂後的結果,一般都比較好。如果使用sgd的話,可以選擇從1.0或者0.1的學習率開始,隔一段時間,在驗證集上檢查一下,如果cost沒有下降,就對學習率減半. 我看過很多論文都這麼搞,我自己實驗的結果也很好. 當然,也可以先用ada系列先跑,最後快收斂的時候,更換成sgd繼續訓練.同樣也會有提升.據說adadelta一般在分類問題上效果比較好,adam在生成問題上效果比較好。
  • 除了gate之類的地方,需要把輸出限制成0-1之外,盡量不要用sigmoid,可以用tanh或者relu之類的激活函數.1. sigmoid函數在-4到4的區間里,才有較大的梯度。之外的區間,梯度接近0,很容易造成梯度消失問題。2. 輸入0均值,sigmoid函數的輸出不是0均值的。
  • rnn的dim和embdding size,一般從128上下開始調整. batch size,一般從128左右開始調整.batch size合適最重要,並不是越大越好.
  • word2vec初始化,在小數據上,不僅可以有效提高收斂速度,也可以可以提高結果.
  • 盡量對數據做shuffle
  • LSTM 的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
  • 來自@張馨宇的技巧:一輪加正則,一輪不加正則,反覆進行。

Ensemble

Ensemble是論文刷結果的終極核武器,深度學習中一般有以下幾種方式

  • 同樣的參數,不同的初始化方式
  • 不同的參數,通過cross-validation,選取最好的幾組
  • 同樣的參數,模型訓練的不同階段,即不同迭代次數的模型。
  • 不同的模型,進行線性融合. 例如RNN和傳統模型.

更多深度學習技巧,請參見我的專欄:煉丹實驗室 - 知乎專欄


其實我發現現在深度學習越來越成熟,調參工作比以前少了很多,絕大多數情況自己設計的參數都不如教程和框架的默認參數好,不過有一些技巧我一直都在用的

(1)relu+bn。這套好基友組合是萬精油,可以滿足95%的情況,除非有些特殊情況會用identity,比如回歸問題,比如resnet的shortcut支路,sigmoid什麼的都快從我世界裡消失了

(2)dropout 。分類問題用dropout ,只需要最後一層softmax 前用基本就可以了,能夠防止過擬合,可能對accuracy提高不大,但是dropout 前面的那層如果是之後要使用的feature的話,性能會大大提升

(3)數據的shuffle 和augmentation 。這個沒啥好說的,aug也不是瞎加,比如行人識別一般就不會加上下翻轉的,因為不會碰到頭朝下的異型種

(4)降學習率。隨著網路訓練的進行,學習率要逐漸降下來,如果你有tensorboard,你有可能發現,在學習率下降的一瞬間,網路會有個巨大的性能提升,同樣的fine-tuning也要根據模型的性能設置合適的學習率,比如一個訓練的已經非常好的模型你上來就1e-3的學習率,那之前就白訓練了,就是說網路性能越好,學習率要越小

(5)tensorboard。以前不怎麼用,用了之後發現太有幫助,幫助你監視網路的狀態,來調整網路參數

(6)隨時存檔模型,要有validation 。這就跟打遊戲一樣存檔,把每個epoch和其對應的validation 結果存下來,可以分析出開始overfitting的時間點,方便下次載入fine-tuning

(7)網路層數,參數量什麼的都不是大問題,在性能不丟的情況下,減到最小

(8)batchsize通常影響沒那麼大,塞滿卡就行,除了特殊的演算法需要batch大一點

(9)輸入減不減mean歸一化在有了bn之後已經不那麼重要了

上面那些都是大家所知道的常識,也是外行人覺得深度學習一直在做的就是這些很low的東西,其實網路設計上博大精深,這也遠超過我的水平範疇,只說一些很簡單的

(1)卷積核的分解。從最初的5×5分解為兩個3×3,到後來的3×3分解為1×3和3×1,再到resnet的1×1,3×3,1×1,再xception的3×3 channel-wise conv+1×1,網路的計算量越來越小,層數越來越多,性能越來越好,這些都是設計網路時可以借鑒的

(2)不同尺寸的feature maps的concat,只用一層的feature map一把梭可能不如concat好,pspnet就是這種思想,這個思想很常用

(3)resnet的shortcut確實會很有用,重點在於shortcut支路一定要是identity,主路是什麼conv都無所謂,這是我親耳聽resnet作者所述

(4)針對於metric learning,對feature加個classification 的約束通常可以提高性能加快收斂

手機碼字,想到再加


補充一點,adam收斂雖快但是得到的解往往沒有sgd+momentum得到的解更好,如果不考慮時間成本的話還是用sgd吧。
再補充一個rnn trick,仍然是不考慮時間成本的情況下,batch size=1是一個很不錯的regularizer, 起碼在某些task上,這也有可能是很多人無法復現alex graves實驗結果的原因之一,因為他總是把batch size設成1。。。


有兩個東西:
1、Hinton老爺子的公開課,說了很多;
2、一本書,《Neural Networks:Tricks of the Trade》


沒做過CNN,RNN,調過連續值DNN,以下經驗僅限於CTR
1.樣本要足夠隨機
2.樣本要做歸一化
3.激活函數要視樣本輸入選擇
4.minibatch很重要,幾百到幾千是比較合適的(很大數據量的情況下)
5.learning rate很重要,可以直接用adagrad or adadelta,省去一些麻煩,然後把衝量調到0.9以上
6.權重初始化,可用高斯分布乘上一個很小的數


少年,助你一臂之力
Must Know Tips/Tricks in Deep Neural Networks (by


小白一枚,在這裡總結一下我在試驗中觀察到的現象(必然有理解錯誤的地方):
1. Adam收斂速度的確要快一些,可是結果總是不如其他優化演算法,如果很看重結果不在乎速度還是用其他的試試。
2. Dropout的放置位置以及大小非常重要,求大神能分享經驗.....
3. Relu並不是一定比Tanh好,如果不太懂的話,用的不合適,可能會導致梯度消失?(不知道是不是網路結構問題,為什麼一用relu梯度一會兒就變成Nan)
4. pretrain 的 Embedding在訓練中不調優泛化能力要更好一些,調優的話參數會增加好多啊。
另:心得體會
1. 深度學習真是一門實驗科學,很多地方解釋不了為什麼好,為什麼不好。
2.如果你機器配置很不到位,也沒有人帶你,畢業設計千萬別選深度學習,天天愁,好坑啊。
未完待續..........


寫代碼這件事情居然變得像老中醫看病一樣需要摸索調參真是讓人難過


燒香拜佛開光(微笑)


最近在看 Karpathy 的 cs231n, 還沒看完, 不過過程中總結了一下他提到的一些技巧:

關於參數:

  • 通常情況下, 更新參數的方法默認用 Adam 效果就很好
  • 如果可以載入全部數據 (full batch updates), 可以使用 L-BFGS

Model Ensembles:

  • 訓練多個模型, 在測試時將結果平均起來, 大約可以得到 2% 提升.
  • 訓練單個模型時, 平均不同時期的 checkpoints 的結果, 也可以有提升.
  • 測試時可以將測試的參數和訓練的參數組合起來:

while True:
data_batch = ...
loss = network.forward(data_batch)
dx = network.backward()
x += - learning_rate * dx
x_test = 0.995 * x_test + 0.005 * x # use for test set


分享幾個常用的trick:
1.增加每個step的輪數
2.early stop
3.用小一些的學習率warmup
4.回退到更大的學習率
5.nesterov momentum sgd
6.搜索初始學習率


基於網格搜索,用坐標下降法調參。然而這個方法太容易收斂到局部最優,所以容易想到加入模擬退火的策略。

分享一個自己寫的自動調參工具chncwang/laozhongyi


1.better initialization helps a lot

2.use minibatch and choose batch_size(must)

3.use batch_norm dropout

4.use adam

5.plot the learning rate curve

6.plot the loss curve.

7.lstm gru are almost always better than sample RNN

8.use better framework(like tensorflow with tensorboard)

9.find hyper parameters used most often in paper

10 pray


cnn的調參主要是在優化函數、embedding的維度還要殘差網路的層數幾個方面。

  1. 優化函數方面有兩個選擇:sgd、adam,相對來說adam要簡單很多,不需要設置參數,效果也還不錯。
  2. embedding隨著維度的增大會出現一個最大值點,也就是開始時是隨維度的增加效果逐漸變好,到達一個點後,而後隨維度的增加,效果會變差。
  3. 殘差網路的層數與embedding的維度有關係,隨層數的增加,效果變化也是一個凸函數。

另外還有激活函數,dropout層和batchnormalize層的使用。激活函數推薦使用relu,dropout層數不易設置過大,過大會導致不收斂,調節步長可以是0.05,一般調整到0.4或者0.5就可找到最佳值。

以上是個人調參的一些經驗,可供參考。


1.無論是cnn還是rnn,batch normalization都有用,不一定結果提高几個點,收斂快多了
2.數據初始時normalize得好,有時候直接提高2個點,比如cifar10,轉到yuv下normalize再scn
3.loss不降了lr就除10
4. google的inception系列按它論文里說的永遠無法復現


momentum,初始一兩輪設置成很小的數值,根據我的實驗結果可以加快收斂速度和提升效果


剛剛總結了一下Deep Learning 的最優化方法,包括Adam,RMSProp,SGD,Momentum,adaGrad,以及一些傳統的二階優化方法等等,歡迎一起交流
博文地址:
http://blog.csdn.net/BVL10101111/article/details/72614711


這種事情怎麼能上手呢?
我都是上差分進化……


本人做rnn的文本相關研究,一直使用adam,下降速度巨快,看別人論文也嘗試過adadelta和adagrad,但不知是姿勢不對還是別的原因效果很差,batch-size大小設置在50(訓練集大小為17w),dropout隨大流0.5,另外我發現l2取值對我的結果影響挺大的,之前一直跟著別人論文用0.001,我換成0.0001以後發現提升了1%


27個回答太少了,我說一個,學習率很多時候都可以調一調,很有驚喜


推薦閱讀:

把深度學習作為自己的碩士課題,有什麼可以做的?
神經網路和深度學習在遊戲設計上是否有應用?
現在的深度學習的模型越來越大,有個結論是說,大腦的激活是非常稀疏的,對模型參數有什麼好的辦法壓縮嗎?
CNN(卷積神經網路)、RNN(循環神經網路)、DNN(深度神經網路)的內部網路結構有什麼區別?
ICLR 2018 有什麼值得關注的亮點?

TAG:深度學習(Deep Learning) |