本文轉載自:https://zhuanlan.zhihu.com/p/24720954?utm_source=zhihu&utm_medium=social
轉載請注明:煉丹實驗室
之前曾經寫過一篇文章,講了一些深度學習訓練的技巧,其中包含了部分調參心得:深度學習訓練心得。不過由於一般深度學習實驗,相比普通機器學習任務,時間較長,因此調參技巧就顯得尤為重要。同時個人實踐中,又有一些新的調參心得,因此這里單獨寫一篇文章,談一下自己對深度學習調參的理解,大家如果有其他技巧,也歡迎多多交流。
好的實驗環境是成功的一半
由於深度學習實驗超參眾多,代碼風格良好的實驗環境,可以讓你的人工或者自動調參更加省力,有以下幾點可能需要注意:
- 將各個參數的設置部分集中在一起。如果參數的設置分布在代碼的各個地方,那么修改的過程想必會非常痛苦。
- 可以輸出模型的損失函數值以及訓練集和驗證集上的准確率。
- 可以考慮設計一個子程序,可以根據給定的參數,啟動訓練並監控和周期性保存評估結果。再由一個主程序,分配參數以及並行啟動一系列子程序。
畫圖
畫圖是一個很好的習慣,一般是訓練數據遍歷一輪以后,就輸出一下訓練集和驗證集准確率。同時畫到一張圖上。這樣訓練一段時間以后,如果模型一直沒有收斂,那么就可以停止訓練,嘗試其他參數了,以節省時間。
如果訓練到最后,訓練集,測試集准確率都很低,那么說明模型有可能欠擬合。那么后續調節參數方向,就是增強模型的擬合能力。例如增加網絡層數,增加節點數,減少dropout值,減少L2正則值等等。
如果訓練集准確率較高,測試集准確率比較低,那么模型有可能過擬合,這個時候就需要向提高模型泛化能力的方向,調節參數。
從粗到細分階段調參
實踐中,一般先進行初步范圍搜索,然后根據好結果出現的地方,再縮小范圍進行更精細的搜索。
- 建議先參考相關論文,以論文中給出的參數作為初始參數。至少論文中的參數,是個不差的結果。
- 如果找不到參考,那么只能自己嘗試了。可以先從比較重要,對實驗結果影響比較大的參數開始,同時固定其他參數,得到一個差不多的結果以后,在這個結果的基礎上,再調其他參數。例如學習率一般就比正則值,dropout值重要的話,學習率設置的不合適,不僅結果可能變差,模型甚至會無法收斂。
- 如果實在找不到一組參數,可以讓模型收斂。那么就需要檢查,是不是其他地方出了問題,例如模型實現,數據等等。可以參考我寫的深度學習網絡調試技巧
提高速度
調參只是為了尋找合適的參數,而不是產出最終模型。一般在小數據集上合適的參數,在大數據集上效果也不會太差。因此可以嘗試對數據進行精簡,以提高速度,在有限的時間內可以嘗試更多參數。
- 對訓練數據進行采樣。例如原來100W條數據,先采樣成1W,進行實驗看看。
- 減少訓練類別。例如手寫數字識別任務,原來是10個類別,那么我們可以先在2個類別上訓練,看看結果如何。
超參數范圍
建議優先在對數尺度上進行超參數搜索。比較典型的是學習率和正則化項,我們可以從諸如0.001 0.01 0.1 1 10,以10為階數進行嘗試。因為他們對訓練的影響是相乘的效果。不過有些參數,還是建議在原始尺度上進行搜索,例如dropout值: 0.3 0.5 0.7)。
經驗參數
這里給出一些參數的經驗值,避免大家調參的時候,毫無頭緒。
- learning rate: 1 0.1 0.01 0.001, 一般從1開始嘗試。很少見learning rate大於10的。學習率一般要隨着訓練進行衰減。衰減系數一般是0.5。 衰減時機,可以是驗證集准確率不再上升時,或固定訓練多少個周期以后。
不過更建議使用自適應梯度的辦法,例如adam,adadelta,rmsprop等,這些一般使用相關論文提供的默認值即可,可以避免再費勁調節學習率。對RNN來說,有個經驗,如果RNN要處理的序列比較長,或者RNN層數比較多,那么learning rate一般小一些比較好,否則有可能出現結果不收斂,甚至Nan等問題。 - 網絡層數: 先從1層開始。
- 每層結點數: 16 32 128,超過1000的情況比較少見。超過1W的從來沒有見過。
- batch size: 128上下開始。batch size值增加,的確能提高訓練速度。但是有可能收斂結果變差。如果顯存大小允許,可以考慮從一個比較大的值開始嘗試。因為batch size太大,一般不會對結果有太大的影響,而batch size太小的話,結果有可能很差。
- clip c(梯度裁剪): 限制最大梯度,其實是value = sqrt(w1^2+w2^2….),如果value超過了閾值,就算一個衰減系系數,讓value的值等於閾值: 5,10,15
- dropout: 0.5
- L2正則:1.0,超過10的很少見。
- 詞向量embedding大小:128,256
- 正負樣本比例: 這個是非常忽視,但是在很多分類問題上,又非常重要的參數。很多人往往習慣使用訓練數據中默認的正負類別比例,當訓練數據非常不平衡的時候,模型很有可能會偏向數目較大的類別,從而影響最終訓練結果。除了嘗試訓練數據默認的正負類別比例之外,建議對數目較小的樣本做過采樣,例如進行復制。提高他們的比例,看看效果如何,這個對多分類問題同樣適用。
在使用mini-batch方法進行訓練的時候,盡量讓一個batch內,各類別的比例平衡,這個在圖像識別等多分類任務上非常重要。
自動調參
人工一直盯着實驗,畢竟太累。自動調參當前也有不少研究。下面介紹幾種比較實用的辦法:
- Gird Search. 這個是最常見的。具體說,就是每種參數確定好幾個要嘗試的值,然后像一個網格一樣,把所有參數值的組合遍歷一下。優點是實現簡單暴力,如果能全部遍歷的話,結果比較可靠。缺點是太費時間了,特別像神經網絡,一般嘗試不了太多的參數組合。
- Random Search。Bengio在Random Search for Hyper-Parameter Optimization中指出,Random Search比Gird Search更有效。實際操作的時候,一般也是先用Gird Search的方法,得到所有候選參數,然后每次從中隨機選擇進行訓練。
- Bayesian Optimization. 貝葉斯優化,考慮到了不同參數對應的實驗結果值,因此更節省時間。和網絡搜索相比簡直就是老牛和跑車的區別。具體原理可以參考這個論文: Practical Bayesian Optimization of Machine Learning Algorithms ,這里同時推薦兩個實現了貝葉斯調參的Python庫,可以上手即用:
- jaberg/hyperopt, 比較簡單。
- fmfn/BayesianOptimization, 比較復雜,支持並行調參。
總結
- 合理性檢查,確定模型,數據和其他地方沒有問題。
- 訓練時跟蹤損失函數值,訓練集和驗證集准確率。
- 使用Random Search來搜索最優超參數,分階段從粗(較大超參數范圍訓練較少周期)到細(較小超參數范圍訓練較長周期)進行搜索。
參考資料
這里列了一些參數資料,大家有時間,可以進一步閱讀。
Practical recommendations for gradient-based training of deep architectures by Yoshua Bengio (2012)
Efficient BackProp, by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert Müller
Neural Networks: Tricks of the Trade, edited by Grégoire Montavon, Geneviève Orr, and Klaus-Robert Müller.