作者:知乎 CVer

原文連結:請點選

本文僅作為學術分享,如果侵權,會刪文處理

Qustion 深度學習調參有哪些技巧?

深度學習的效果很大程度上取決於引數調節的好壞,那麼怎麼才能最快最好的調到合適的引數呢?求解

Answer 1 作者:Jarvix

只想說一句:初始化

一次慘痛的教訓是用normal初始化cnn的引數,最後acc只能到70%多,僅僅改成xavier,acc可以到98%。

還有一次給word embedding初始化,最開始使用了TensorFlow中預設的initializer(即glorot_uniform_initializer,也就是大家經常說的無腦使用xavier),訓練速度慢不說,結果也不好。改為uniform,訓練速度飆升,結果也飆升。

所以,初始化就跟黑科技一樣,用對了超參都不用調;沒用對,跑出來的結果就跟模型有bug一樣不忍直視。

Answer 2 作者:BBuf

大概調了快一年CNN(2019年1月到今天),看到這個話題挺感興趣的,以下是我的總結

做比賽

特徵提取。VGG16,VGG19,ResNet50,Xception是非常好用的幾個特徵提取模型。建議使用訓練好的經典模型對資料集提取特徵向量儲存到本地,更方便使用,同時可以大幅度降低視訊記憶體消耗。

ensemble:

將不同的經典網路提取出的特徵向量,假設

VGG16

提取出的特徵向量維度是

[N,c1]

ResNet50

提取的特徵向量維度是

[N,c2]

Xception

提取的特徵向量維度是

[N, c3]

,那麼我們可以使用三個係數

a、b、c

將其組合為形狀為

[N, a*c1+b*c2+c*c3]

,其中

a、b、c

三個引數的取值代表我們使用哪個模型的特徵多一些,如果是分類迴歸比賽,我們在後面接特徵處理網路就可以了。可以取不同的

a、b、c

得到不同的特徵,然後對結果做

voting

soft-voting

等多種處理,一般結果不會太差啦。

可以使用不同的初始化方式訓練出模型,然後做ensemble。

可以使用用不同超引數(如學習率,

batch_size

,最佳化器)訓練出不同模型,然後做ensemble。

因為我就做了一點點入門級比賽,上面介紹的方法取得了還不錯的結果,所以我就在這裡獻醜啦,方法確實挺無腦的,大家笑一笑就好啦。繼續想了下,我好像除了這些有接觸或者使用到,暫時沒有什麼其它的了,如果想起其他的了,之後補充下。

Answer 3 作者:Captain Jack

我和@楊軍類似, 也是半路出家。 現在的工作內容主要就是使用CNN做CV任務。 幹調參這種活也有兩年時間了。 我的回答可能更多的還是側重工業應用, 技術上只限制在CNN這塊。

先說下我的觀點, 調參就是trial-and-error。 沒有其他捷徑可以走。 唯一的區別是有些人盲目的嘗試, 有些人思考後再嘗試。

快速嘗試, 快速糾錯

這是調參的關鍵。

看了楊軍的回答。 對於這個回答, 下面的評論裡面@紀秋佳說的很對。 這個回答主要內容更多的是側重理解網路。 而非訓練網路。

我要再強調下,

楊軍的回答更多的涉及是理解網路而非訓練網路

。 是的, 沒錯。 你看完回答中的所有內容, 對不起, 你還是不知道怎麼實際訓練一個網路, 尤其是複雜任務下的網路(因為簡單任務根本不需要, 直接上來效果就會很好, 除非你要刷簡單任務的排行榜)。

首先說下視覺化:

我個人的理解, 對於視覺化, 更多的還是幫助人類以自己熟悉的方式來觀察網路。 因為, 你是不可能邊觀察網路, 還邊調參的。 你只是訓練完成後(或者準確率到達一個階段後), 才能視覺化。 在這之前, 網路沒有學習到良好的引數, 你可視化了也沒意義, 網路達到不錯的準確率了, 你看看其實也就聽個響。 同樣, 你的網路訓練的一塌糊塗, 你視覺化也沒什麼意義, 唯一能夠看到的就是中間結果亂七八糟, 或者全黑全白, 這時候你直接看最後準確率就可以知道這網路沒救了。

關於權重的視覺化[Visualize Layer Weights](現在是否強求smooth其實意義不大, 這個後面說.):

同樣, 你看到一個不滿足平滑結果的影象, 你知道, 這網路訓練的不好, 但是為什麼呢? 是資料不好? 沒有預處理? 網路結構問題? Learning Rate太大或者太小? 或者就是差了一個LRN層(之前我就遇到, 加個LRN就能出smooth的weights, 當然這其實和預處理有關)?

Smooth是需要看一下的, 心裡有個數。 但是具體調參怎麼調是沒轍的。

第一

, 你不可能告訴網路, 這層你得學個邊界檢測的功能出來。

第二

, 不同任務下會有不同的weights(雖然底層的特徵有很大的通用性), 你覺得你憑什麼來指導一個看圖片比你快得多的機器?

再說現在是否需要強求smooth。 現在的趨勢是鼓勵使用小filter, 3x3大小, 多加層次(這樣, 非線性更好點)。 換句話說, 3x3的圖片, 總共才9個畫素, 你怎麼判斷smooth與否呢? 當然如果你使用大的filter, 一般5x5往上, 運氣不差的話, 你是可以看到smooth的結果的。

咱們再說另外一個極端, 一個網路,執行的完美(滿足應用要求就算完美), 開啟一看, 這weights不smooth啊。 你告訴我, 你打算怎麼辦? 沒錯, 具有不平滑的權重的網路同樣可以獲得很好的結果(這種情況我都習以為常了)。

那麼視覺化網路就不重要了?

非常重要, 但是不在訓練這塊

, 而是幫助理解網路的原理這塊。 理解網路原理後, 你才能在設計結構的時候心裡有感覺(只是有感覺而已), 網路出了問題, 或者在某些情況下不滿意, 有更好的直覺去調整。(沒錯, 只是直覺, 雖然有些情況下的調整從網路原理來看邏輯上應該可以工作, 但是人家就是不工作, 你能咬機器去麼?)

那麼怎樣訓練一個不錯的網路呢?

這是一個很好的連結, 說明了如何從零開始不斷的trial-and-error(其實這裡面沒遇到什麼error):

Using convolutional neural nets to detect facial keypoints tutorial

========================================================

我自己的經驗, 有下面這些:

基本原則:

快速試錯

一些大的注意事項:

1。 剛開始, 先上小規模資料, 模型往大了放, 只要不爆視訊記憶體, 能用256個filter你就別用128個。 直接奔著過擬合去。 沒錯, 就是訓練過擬合網路, 連測試集驗證集這些都可以不用。

為什麼?

+ 你要驗證自己的訓練指令碼的流程對不對。 這一步小資料量, 生成速度快, 但是所有的指令碼都是和未來大規模訓練一致的(除了少跑點迴圈)

+ 如果小資料量下, 你這麼粗暴的大網路奔著過擬合去都沒效果。 那麼, 你要開始反思自己了, 模型的輸入輸出是不是有問題? 要不要檢查自己的程式碼(永遠不要懷疑工具庫, 除非你動過程式碼)? 模型解決的問題定義是不是有問題? 你對應用場景的理解是不是有錯? 不要懷疑NN的能力, 不要懷疑NN的能力, 不要懷疑NN的能力。 就我們調參狗能遇到的問題, NN沒法擬合的, 這機率是有多小?

+ 你可以不這麼做, 但是等你資料準備了兩天, 結果發現有問題要重新生成的時候, 你這周時間就醬油了。

2. Loss設計要合理.

+ 一般來說分類就是Softmax, 迴歸就是L2的loss。 但是要注意loss的錯誤範圍(主要是迴歸), 你預測一個label是10000的值, 模型輸出0, 你算算這loss多大, 這還是單變數的情況下。 一般結果都是nan。 所以不僅僅輸入要做normalization, 輸出也要這麼弄。

+ 多工情況下, 各loss想法限制在一個量級上, 或者最終限制在一個量級上, 初期可以著重一個任務的loss

3. 觀察loss勝於觀察準確率

準確率雖然是評測指標, 但是訓練過程中還是要注意loss的。 你會發現有些情況下, 準確率是突變的, 原來一直是0, 可能保持上千迭代, 然後突然變1。 要是因為這個你提前中斷訓練了, 只有老天替你惋惜了。 而loss是不會有這麼詭異的情況發生的, 畢竟最佳化目標是loss。

給NN一點時間, 要根據任務留給NN的學習一定空間。 不能說前面一段時間沒起色就不管了。 有些情況下就是前面一段時間看不出起色, 然後開始穩定學習。

4. 確認分類網路學習充分

分類網路就是學習類別之間的界限。 你會發現, 網路就是慢慢的從類別模糊到類別清晰的。 怎麼發現? 看Softmax輸出的機率的分佈。 如果是二分類, 你會發現, 剛開始的網路預測都是在0。5上下, 很模糊。 隨著學習過程, 網路預測會慢慢的移動到0,1這種極值附近。 所以, 如果你的網路預測分佈靠中間, 再學習學習。

5. Learning Rate設定合理

+ 太大: loss爆炸, 或者nan

+ 太小: 半天loss沒反映(但是, LR需要降低的情況也是這樣, 這裡視覺化網路中間結果, 不是weights, 有效果, 倆者視覺化結果是不一樣的, 太小的話中間結果有點水波紋或者噪點的樣子, 因為filter學習太慢的原因, 試過就會知道很明顯)

+ 需要進一步降低了: loss在當前LR下一路降了下來, 但是半天不再降了。

+ 如果有個複雜點的任務, 剛開始, 是需要人肉盯著調LR的。 後面熟悉這個任務網路學習的特性後, 可以扔一邊跑去了。

+ 如果上面的Loss設計那塊你沒法合理, 初始情況下容易爆, 先上一個小LR保證不爆, 等loss降下來了, 再慢慢升LR, 之後當然還會慢慢再降LR, 雖然這很蛋疼。

+ LR在可以工作的最大值下往小收一收, 免得ReLU把神經元弄死了。 當然, 我是個心急的人, 總愛設個大點的。

6 對比訓練集和驗證集的loss

判斷過擬合, 訓練是否足夠, 是否需要early stop的依據, 這都是中規中矩的原則, 不多說了。

7 清楚receptive field的大小

CV的任務, context window是很重要的。 所以你對自己模型的receptive field的大小要心中有數。 這個對效果的影響還是很顯著的。 特別是用FCN, 大目標需要很大的receptive field。 不像有fully connection的網路, 好歹有個fc兜底, 全域性資訊都有。

簡短的注意事項:

預處理: -mean/std zero-center就夠了, PCA, 白化什麼的都用不上。 我個人觀點, 反正CNN能學習encoder, PCA用不用其實關係不大, 大不了網路裡面自己學習出來一個。

shuffle, shuffle, shuffle。

網路原理的理解最重要, CNN的conv這塊, 你得明白sobel運算元的邊界檢測。

Dropout, Dropout, Dropout(不僅僅可以防止過擬合, 其實這相當於做人力成本最低的Ensemble, 當然, 訓練起來會比沒有Dropout的要慢一點, 同時網路引數你最好相應加一點, 對, 這會再慢一點)。

CNN更加適合訓練回答是否的問題, 如果任務比較複雜, 考慮先用分類任務訓練一個模型再finetune。

無腦用ReLU(CV領域)。

無腦用3x3。

無腦用xavier。

LRN一類的, 其實可以不用。 不行可以再拿來試試看。

filter數量2^n。

多尺度的圖片輸入(或者網路內部利用多尺度下的結果)有很好的提升效果。

第一層的filter, 數量不要太少。 否則根本學不出來(底層特徵很重要)。

sgd adam 這些選擇上, 看你個人選擇。 一般對網路不是決定性的。 反正我無腦用sgd + momentum。

batch normalization我一直沒用, 雖然我知道這個很好, 我不用僅僅是因為我懶。 所以要鼓勵使用batch normalization。

不要完全相信論文裡面的東西。 結構什麼的覺得可能有效果, 可以拿去試試。

你有95%機率不會使用超過40層的模型。

shortcut的聯接是有作用的。

暴力調參最可取, 畢竟, 自己的生命最重要。 你調完這個模型說不定過兩天這模型就扔掉了。

機器, 機器, 機器。

Google的inception論文, 結構要好好看看。

一些傳統的方法, 要稍微瞭解瞭解。 我自己的程式就用過1x14的手寫filter, 寫過之後你看看inception裡面的1x7, 7x1 就會會心一笑。。

作者:隨機漫步的傻瓜

https://www.zhihu.com/question/25097993/answer/951804080

1、首先,調參的時候你要整理好自己的心情。別誤會,我的意思是讓你狂躁一點。因為這玩意有時候的確是個玄學,經常調半天毛用都沒有,然後只是換一個初始值,分分鐘給你幹到95%以上。是的,你其實啥也沒做,但大部分時候這玩意兒跟人很像,“出身”很重要。

2、如上所述,

好的初始點 + 合適的LR + 好的最佳化方法

基本可以解決大部分問題。如果還不行可以考慮換個loss。其它的花樣太多往往很虛。

3、一定要注意實時儲存自己的結果,熟悉使用各種seed,養成好的習慣。有時候你覺得一個不太好的結果其實可能是你能調到的最好的結果了,你也不想因為沒儲存的緣故然後回頭發現再也找不著了的對吧?所謂今天你看我不起,明天我讓你高攀不起。別問我怎麼知道的。

4、新手剛上來調參的時候沒什麼經驗,所以一定要低調!啥叫低調?低調就是一開始調的時候千萬別考慮太遠,在能承受的範圍內,儘可能先把濾波器搞得多多的,把資料搞得少少的,

直奔過擬合去

!所謂

小步試錯,快速迭代

,網際網路公司都是這麼幹的。雖然過擬合也不好搞,但總歸是有不少套路的,比起過擬合,欠擬合的問題遠遠可怕的多。畢竟結果都訓練不出來還扯什麼遠方?

5、有很多無腦的配置確實可以嘗試,比如3x3的卷積核,relu啟用函式,加shuffle,加資料增強,加BN,加Dropout等。dropout可以從0。 5往上加,optimizer可以用Adam或者SGD+0。8/0。9的Momentum。大部分時候這些經驗比你自己辛苦挑出來的奇技淫巧要有價值的多,但不是絕對的。

6、一定要記得實時列印一些結果,比如訓練loss、訓練accuracy、驗證accuracy,能畫出圖的就畫個圖。一邊看圖一邊可以發現不少問題,尤其是關於學習率和過擬合的。另外,前面某位大神說的很對,看圖的時候loss要比accuracy有用的多,因為accuracy就像女人一樣經常善變,可能下一個step就差很多,而loss畢竟有個相對穩定下降的大趨勢。

7、在你夜深人靜的時候,或者不忙的時候,別忘了多想想原理。多研究研究別人的優秀結果,尤其是那些成熟的架構、和一些state-of-the-art的結果,自己的資料集也可以多翻翻,閒來無事搞點視覺化什麼的,既鍛鍊了技術又能幫助發現。除了調參,應用的時候不妨直接把別人的某些層拿過來自己用,能節省不少時間。

8、最後,什麼都不是絕對的。很多原理性的文章,你看看就好。什麼東西都是有條件的,離開了這個條件就啥也不是,而恰巧有時候這個條件可能僅僅就是運氣而已。所以萬一復現不出來,別較真,該丟則丟。調參雖苦,也一定不要忘了同時調整自己的心態:多行善事、及時記錄、少吹牛逼、多逛知乎。

Answer 4 作者:京東白條

相信很多剛開始接觸深度學習朋友,會感覺深度學習調參就像玄學一般,有時候引數調的好,模型會快速收斂,引數沒調好,可能迭代幾次loss值就直接變成Nan了。

記得剛開始研究深度學習時,做過兩個小例子。一個是用tensorflow構建了一個十分簡單的只有一個輸入層和一個softmax輸出層的Mnist手寫識別網路,第一次我對權重矩陣W和偏置b採用的是正態分佈初始化,一共迭代了20個epoch,當迭代完第一個epoch時,預測的準確度只有10%左右(和隨機猜一樣,Mnist是一個十分類問題),當迭代完二十個epoch,精度也僅僅達到了60%的樣子。

然後我僅僅是將權重矩陣W初始化方法改成了全為0的初始化,其他的引數均保持不變,結果在訓練完第一個epoch後預測精度就達到了85%以上,最終20個epoch後精度達到92%。另一個例子是迴歸問題的預測,當時採用的SGD最佳化器,一開始學習率設定的0。1,模型可以正常訓練,只是訓練速度有些慢,我試著將學習率調整到0。3,希望可以加速訓練速度,結果沒迭代幾輪loss就變成Nan了。於是從那時起我就深刻的感受到引數調節在深度學習模型訓練中的重要意義。

其實上述問題產生的原因也很好理解,對於引數初始化,因為我們學習的本來就是權重W與偏置b,如果初始化足夠好,直接就初始化到最優解,那都不用進行訓練了。良好的初始化,可以讓引數更接近最優解,這可以大大提高收斂速度,也可以防止落入區域性極小。對於學習率,學習率如果取太大,會使模型訓練非常震盪,可以想象我們最小化一個二次拋物線,選取一個很大的學習率,那麼迭代點會一直在拋物線的兩邊震盪,收斂不到最小值,甚至還有螺旋上升迭代點的可能。

下面對深度學習調參技巧談些心得,雖說不能讓你透過以下閱讀成為一個調參高手,但最起碼可以提供一些調參的思路。

1.

啟用函式選擇:

常用的啟用函式有relu、leaky-relu、sigmoid、tanh等。對於輸出層,多分類任務選用softmax輸出,二分類任務選用sigmoid輸出,迴歸任務選用線性輸出。而對於中間隱層,則優先選擇relu啟用函式(relu啟用函式可以有效的解決sigmoid和tanh出現的梯度彌散問題,多次實驗表明它會比其他啟用函式以更快的速度收斂)。另外,構建序列神經網路(RNN)時要優先選用tanh啟用函式。

2、學習率設定:

一般學習率從0。1或0。01開始嘗試。學習率設定太大會導致訓練十分不穩定,甚至出現Nan,設定太小會導致損失下降太慢。學習率一般要隨著訓練進行衰減。衰減係數設0。1,0。3,0。5均可,衰減時機,可以是驗證集準確率不再上升時,或固定訓練多少個週期以後自動進行衰減。

3、防止過擬合:

一般常用的防止過擬合方法有使用L1正則項、L2正則項、dropout、提前終止、資料集擴充等。如果模型在訓練集上表現比較好但在測試集上表現欠佳可以選擇增大L1或L2正則的懲罰力度(L2正則經驗上首選1。0,超過10很少見),或增大dropout的隨機失活機率(經驗首選0。5);或者當隨著訓練的持續在測試集上不增反降時,使用提前終止訓練的方法。當然最有效的還是增大訓練集的規模,實在難以獲得新資料也可以使用資料集增強的方法,比如CV任務可以對資料集進行裁剪、翻轉、平移等方法進行資料集增強,這種方法往往都會提高最後模型的測試精度。

4、最佳化器選擇:

如果資料是稀疏的,就用自適應方法,即 Adagrad, Adadelta, RMSprop, Adam。整體來講,Adam 是最好的選擇。SGD 雖然能達到極小值,但是比其它演算法用的時間長,而且可能會被困在鞍點。如果需要更快的收斂,或者是訓練更深更復雜的神經網路,需要用一種自適應的演算法。

5、殘差塊與BN層:

如果你希望訓練一個更深更復雜的網路,那麼殘差塊絕對是一個重要的元件,它可以讓你的網路訓練的更深。

BN層具有加速訓練速度,有效防止梯度消失與梯度爆炸,具有防止過擬合的效果,所以構建網路時最好要加上這個元件。

6.自動調參方法:

(1)Grid Search:網格搜尋,在所有候選的引數選擇中,透過迴圈遍歷,嘗試每一種可能性,表現最好的引數就是最終的結果。其原理就像是在數組裡找最大值。缺點是太費時間了,特別像神經網路,一般嘗試不了太多的引數組合。

(2)Random Search:經驗上,Random Search比Gird Search更有效。實際操作的時候,一般也是先用Gird Search的方法,得到所有候選引數,然後每次從中隨機選擇進行訓練。另外Random Search往往會和由粗到細的調參策略結合使用,即在效果比較好的引數附近進行更加精細的搜尋。

(3)Bayesian Optimization:貝葉斯最佳化,考慮到了不同引數對應的 實驗結果值,因此更節省時間,貝葉斯調參比Grid Search迭代次數少, 速度快;而且其針對非凸問題依然穩健。

7.引數隨機初始化與資料預處理:

引數初始化很重要,它決定了模型的訓練速度與是否可以躲開區域性極小。relu啟用函式初始化推薦使用He normal,tanh初始化推薦使用Glorot normal,其中Glorot normal也稱作Xavier normal初始化;資料預處理方法一般也就採用資料歸一化即可。