神經網絡的參數優化方法

 

轉載自:https://www.cnblogs.com/bonelee/p/8528863.html

著名: 本文是從 Michael Nielsen的電子書Neural Network and Deep Learning深度學習那一章的卷積神經網絡的參數優化方法的一些總結和摘錄,並不是我自己的結論和做實驗所得到的結果。我想Michael的實驗結果更有說服力一些。本書在github上有中文翻譯的版本,

前言

最近卷積神經網絡(CNN)很火熱,它在圖像分類領域的卓越表現引起了大家的廣泛關注。本文總結和摘錄了Michael Nielsen的那本Neural Network and Deep Learning一書中關於深度學習一章中關於提高泛化能力的一些概述和實驗結果。力爭用數據給大家一個關於正則化增加捲積層/全連接數棄權技術拓展訓練集等參數優化方法的效果。 
本文並不會介紹正則化棄權(Dropout)池化等方法的原理,只會介紹它們在實驗中的應用或者起到的效果,更多的關於這些方法的解釋請自行查詢。

mnist數據集介紹

本文的實驗是基於mnist數據集合的,mnist是一個從0到9的手寫數字集合,共有60,000張訓練圖片,10,000張測試圖片。每張圖片大小是28*28大小。我們的實驗就是構建一個神經網絡來高精度的分類圖片,也就是提高泛化能力。

提高泛化能力的方法

一般來說,提高泛化能力的方法主要有以下幾個:

  • 正則化
  • 增加神經網絡層數
  • 使用正確的代價函數
  • 使用好的權重初始化技術
  • 人爲拓展訓練集
  • 棄權技術 
    下面我們通過實驗結果給這些參數優化理論一個直觀的結果

1. 普通的全連接神經網絡的效果

我們使用一個隱藏層,包含100個隱藏神經元,輸入層是784,輸出層是one-hot編碼的形式,最後一層是Softmax層。訓練過程採用對數似然代價函數,60次迭代,學習速率η=0.1,隨機梯度下降的小批量數據大小爲10,沒有正則化。在測試集上得到的結果是97.8%

 

2.使用卷積神經網絡 — 僅一個卷積層

輸入層是卷積層,5*5的局部感受野,也就是一個5*5的卷積核,一共20個特徵映射。最大池化層選用2*2的大小。後面是100個隱藏神經元的全連接層。結構如圖所示 
CNN結構

在這個架構中,我們把卷積層和chihua層看做是學習輸入訓練圖像中的局部感受野,而後的全連接層則是一個更抽象層次的學習,從整個圖像整合全局信息。也是60次迭代,批量數據大小是10,學習率是0.1。

經過三次運行取平均後,準確率是98.78%,這是相當大的改善。錯誤率降低了1/3,。卷積神經網絡開始顯現威力。

3.使用卷積神經網絡 — 兩個卷積層

我們接着插入第二個卷積-混合層,把它插入在之前的卷積-混合層和全連接層之間,同樣的5*5的局部感受野,2*2的池化層。

這一次,我們擁有了99.06%的準確率。

4.使用卷積神經網絡 — 兩個卷積層+線性修正單元(ReLU)+正則化

上面我們使用的Sigmod激活函數,現在我們換成線性修正激活函數ReLU 
f(z)=max(0,z)

,我們選擇60個迭代期,學習速率η=0.03, ,使用L2正則化,正則化參數λ=0.1

這一次,我們獲得了99.23%的準確率,超過了S型激活函數的99.06%. ReLU的優勢是max(0,z)

中z取最大極限時不會飽和,不像是S函數,這有助於持續學習。

5.使用卷積神經網絡 — 兩個卷基層+線性修正單元(ReLU)+正則化+拓展數據集

拓展訓練集數據的一個簡單方法是將每個訓練圖像由一個像素來代替,無論是上一個像素,下一個像素,或者左右的像素。其他的方法也有改變亮度,改變分辨率,圖片旋轉,扭曲,位移等。 
我們把50,000幅圖像人爲拓展到250,000幅圖像。使用第4節一樣的網絡,因爲我們是在訓練5倍的數據,所以減少了過擬合的風險。

這次的到了99.37的訓練正確率。

6.使用卷積神經網絡 — 兩個卷基層+線性修正單元(ReLU)+正則化+拓展數據集+繼續插入額外的全連接層

繼續上面的網絡,我們拓展全連接層的規模,300個隱藏神經元和1000個神經元的額精度分別是99.46%和99.43%. 
我們插入一個額外的全連接層

這次取得了99.43%的精度。拓展後的網絡並沒有幫助太多。

7.使用卷積神經網絡 — 兩個卷基層+線性修正單元(ReLU)+拓展數據集+繼續插入額外的全連接層+棄權技術

棄權的基本思想就是在訓練網絡時隨機的移除單獨的激活值,使得模型對單獨的依據丟失更爲強勁,因此不太依賴於訓練數據的特質。我們嘗試應用棄權技術到最終的全連接層(不是在卷基層)。這裏,減少了迭代期的數量爲40個,全連接層使用1000個隱藏神經元,因爲棄權技術會丟棄一些神經元。Dropout是一種非常有效有提高泛化能力,降低過擬合的方法!

使用棄權技術,的到了99.60%的準確率。

8.使用卷積神經網絡 — 兩個卷基層+線性修正單元(ReLU)+正則化+拓展數據集+繼續插入額外的全連接層+棄權技術+組合網絡

組合網絡類似於隨機森林或者adaboost的集成方法,創建幾個神經網絡,讓他們投票來決定最好的分類。我們訓練了5個不同的神經網絡,每個都大到了99.60%的準去率,用這5個網絡來進行投票表決一個圖像的分類。 
採用這個方法,達到了99.67%的準確率。

總結

卷積神經網絡 的一些技巧總結如下:

1. 使用卷積層極大地減小了全連接層中的參數的數目,使學習的問題更容易
2. 使用更多強有力的規範化技術(尤其是棄權和卷積)來減小過度擬合,
3. 使用修正線性單元而不是S型神經元,來加速訓練-依據經驗,通常是3-5倍,
4. 使用GPU來計算
5. 利用充分大的數據集,避免過擬合
6. 使用正確的代價函數,避免學習減速
7. 使用好的權重初始化,避免因爲神經元飽和引起的學習減速

 

CNN超參數優化和可視化技巧詳解

轉自:https://zhuanlan.zhihu.com/p/27905191

在深度學習中,有許多不同的深度網絡結構,包括卷積神經網絡(CNN或convnet)、長短期記憶網絡(LSTM)和生成對抗網絡(GAN)等。

在計算機視覺領域,對卷積神經網絡(簡稱爲CNN)的研究和應用都取得了顯著的成果。CNN網絡最初的誕生收到了動物視覺神經機制的啓發,目前已成功用於機器視覺等領域中。

技術博客Towards Data Science最近發佈了一篇文章,作者Suki Lau。文章討論了在卷積神經網絡中,該如何調整超參數以及可視化卷積層。

爲什麼用卷積神經網絡?

首先,我們想要計算機具有什麼能力呢?

當我們看到一隻貓跳上窗臺或在沙發上睡覺時,我們的潛意識會認出它是一隻貓。

我們希望計算機也能完成這項任務,即將圖像輸入後,找出其獨有的特徵,最終輸出該圖像的類別信息。

卷積神經網絡可以完成這項任務。

何爲卷積神經網絡?

先談定義,卷積神經網絡是一種特殊的神經網絡,其中至少包含一個卷積層。在典型的CNN網絡結構中,輸入一張圖像,經由一系列卷積層、非線性激活層、池化層和全連接層後,可輸出相應的類別標籤。

卷積神經網絡的特別之處在於加入了卷積層。

在經典的神經網絡中,整張圖片會被傳入網絡中來訓練各網絡層權值。當輸入爲簡單居中的圖像時,如Mnist手寫數字圖,網絡識別效果較優,但是當輸入變爲更爲複雜多變的圖像時,如跳上窗戶的小貓,此時網絡識別效果不佳甚至無法辨識。

加入更多隱含層學習輸入圖像的抽象特徵,可能會有所幫助,但是這樣會增加神經元的數目,大大增加訓練所需的計算資源和佔用過多的內存,這是不切實際的。

而CNN識別目標的過程,是先尋找諸如邊緣、線段和曲線等相關低級特徵,然後使用多個卷積層來構建更多抽象的高級特徵。

在卷積層的學習過程中,CNN網絡通過共享多個卷積核(或特徵檢測器)的權值,來學習每張圖片的局部信息,並用於構建抽象特徵圖譜。卷積核共享特性大大降低了訓練網絡所需的參數量。

由於經過訓練的檢測器可以通過卷積層重複用來組合地檢測圖片中的抽象特徵,因此卷積神經網絡更適用於複雜的圖像識別任務。

超參數調整

在深度神經網絡中,調整超參數組合並非易事,因爲訓練深層神經網絡十分耗時,且需要配置多個參數。

接下來,我們簡單列舉幾個影響CNN網絡的關鍵超參數。

學習率

學習率是指在優化算法中更新網絡權重的幅度大小。

學習率可以是恆定的、逐漸降低的、基於動量的或者是自適應的,採用哪種學習率取決於所選擇優化算法的類型,如SGD、Adam、Adagrad、AdaDelta或RMSProp等算法。

優化策略這方面的內容可參閱量子位之前編譯過的“一文看懂各種神經網絡優化算法:從梯度下降到Adam方法”。

迭代次數

迭代次數是指整個訓練集輸入到神經網絡進行訓練的次數。當測試錯誤率和訓練錯誤率相差較小時,可認爲當前的迭代次數是合適的,否則需繼續增大迭代次數,或調整網絡結構。

批次大小

在卷積神經網絡的學習過程中,小批次會表現得更好,選取範圍一般位於區間[16,128]內。

還需要注意的是,CNN網絡對批次大小的調整十分敏感。

激活函數

激活函數具有非線性,理論上可以使模型擬合出任何函數。通常情況下,rectifier函數在CNN網絡中的效果較好。當然,可以根據實際任務,選擇其他類型的激活函數,如Sigmoid和Tanh等等。

隱含層的數目和單元數

增加隱含層數目以加深網絡深度,會在一定程度上改善網絡性能,但是當測試錯誤率不再下降時,就需要尋求其他的改良方法。增加隱含層數目也帶來一個問題,即提高了訓練該網絡的計算成本。

當網絡的單元數設置過少時,可能會導致欠擬合,而單元數設置過多時,只要採取合適的正則化方式,就不會產生不良影響。

權重初始化

在網絡中,通常會使用小隨機數來初始化各網絡層的權重,以防止產生不活躍的神經元,但是設置過小的隨機數可能生成零梯度網絡。一般來說,均勻分佈方法效果較好。

Dropout方法

作爲一種常用的正則化方式,加入Dropout層可以減弱深層神經網絡的過擬合效應。該方法會按照所設定的概率參數,在每次訓練中隨機地不激活一定比例的神經單元。該參數的默認值爲0.5。

手動調整超參數是十分費時也不切實際。接下來介紹兩種搜索最優超參數的常用方法。

網格搜索和隨機搜索

網格搜索是通過窮舉法列出不同的參數組合,確定性能最優的結構。隨機搜索是從具有特定分佈的參數空間中抽取出一定數量的候選組合。

網格搜索方法也需要制定策略,在初始階段最好先確定各超參數值的大概範圍。可以先嚐試在較小迭代次數或較小規模的訓練集上進行大步幅的網格搜索。然後在下個階段中,設置更大的迭代次數,或是使用整個訓練集,實現小幅精確定位。

雖然在許多機器學習算法中,通常會使用網格搜索來確定超參數組合,但是隨着參數量的增大,訓練網絡所需的計算量呈指數型增長,這種方法在深層神經網絡的超參數調整時效果並不是很好。

有研究指出,在深度神經網絡的超參數調整中,隨機搜索方法比網格搜索的效率更高,具體可參考文末中的“隨機搜索在超參數優化中的應用”。

當然,可根據神經網絡的理論經驗,進行超參數的手動調整在一些場景下也是可行的。

可視化

我們可以通過可視化各個卷積層,來更好地瞭解CNN網絡是如何學習輸入圖像的特徵。

可視化有兩種直接方式,分別是可視化激活程度可視化相關權重。在網絡訓練過程中,卷積層的激活情況通常會變得更爲稀疏和具有局部特性。當不同輸入圖像的激活圖都存在大片未激活的區域,那麼可能是設置了過高的學習率使得卷積核不起作用,導致產生零激活圖像。

性能優良的神經網絡通常含有多個明顯而平滑的卷積器,且沒有任何干擾特徵。若在權重中觀察到相關干擾特徵,可能原因是網絡未被充分訓練,或是正則化強度較低導致了過擬合效應。

 

神經網絡參數優化--基於CNN的驗證

轉自:https://ziyubiti.github.io/2016/11/20/cnnpara/

  當使用多層更深的隱藏層全連接網絡時,參數量會變得非常巨大,達到數十億量級;而採用CNN結構,則可以層間共享權重,極大減小待訓練的參數量;同時可採用二維卷積,保留圖像的空間結構信息;採用池化層,進一步減少參數計算。
  一般來說,提高泛化能力的方法主要有: 正則化、增加神經網絡層數、改變激活函數與代價函數、使用好的權重初始化技術、人爲擴展訓練集、棄權技術。
  下面以MNIST爲例,結合CNN、Pooling、Fc結構,通過不同的網絡結構變化,給這些參數優化理論一個直觀的驗證結果。

CNN不同網絡結構性能比較CNN不同網絡結構性能比較

  可以看出:
  1、使用L2正則化,dropout技術,擴展數據集等,有效緩解過擬合,提升了性能;
  2、使用ReLU,導數爲常量,可以緩解梯度下降問題,並加速訓練;
  3、增加Conv/Pooling與Fc層,可以改善性能。(我自己實測也是如此)
  
  Note:
  1、網絡並非越深越好,單純的Conv/Pooling/Fc結構,增加到一定深度後由於過擬合性能反而下降。
  2、網絡結構信息更重要,如使用GoogleNet、ResNet等。

知乎上的討論:

轉自:https://www.zhihu.com/question/41631631

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

參數初始化。

下面幾種方式,隨便選一個,結果基本都差不多。但是一定要做。否則可能會減慢收斂速度,影響收斂結果,甚至造成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在我的大部分實驗中,效果提升都非常明顯(實測sgd比adam好).因此可能的話,建議一定要嘗試一下。 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的話,性能會大大提升(例如max pool進入fc,實測發現加BN效果非常明顯)

(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的東西,其實網絡設計(關鍵!!!實測發現對於acc影響極大!)上博大精深,這也遠超過我的水平範疇,只說一些很簡單的

(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。。。

 

 

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

 

 

 

小白一枚,在這裏總結一下我在試驗中觀察到的現象(必然有理解錯誤的地方):
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 的結果, 也可以有提升.
  • 測試時可以將測試的參數和訓練的參數組合起來:

 

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

 

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系列按它論文裏說的永遠無法復現

 

 

 

如何訓練深度神經網絡?老司機的 15 點建議

   

導語:印度深度學習專家 Rishabh Shukla 對開發深度神經網絡的經驗總結。

本文爲印度深度學習專家、創業者 Rishabh Shukla 在 GitHub 上發表的長博文,總結了他過去的開發經驗,旨在給新入門的開發者提供指導。雷鋒網做了不改變原意的編譯。

在深度學習領域,爲了高效訓練深度神經網絡,有些實踐方法被過來人強烈推薦。

在這篇博文中,我會覆蓋幾種最常使用的實踐方法,從高品質訓練數據的重要性、超參數(hyperparameters)到更快創建 DNN(深度神經網絡) 原型模型的一般性建議。這些推薦方法中的大多數,已被學術界的研究所證實,並在論文中展示了相關實驗、數學證據,比如 Efficient BackProp(Yann LeCun et al.) 和 Practical Recommendations for Deep Architectures(Yoshua Bengio)

1. 訓練數據

許多 ML 開發者習慣把原始訓練數據直接扔給 DNN——爲什麼不這麼做呢?既然任何 DNN (大多數人的假設)仍然能夠給出不錯的結果,不是嗎?但是,有句老話叫“給定恰當的數據類型,一個簡單的模型能比複雜 DNN 提供更好、更快的結果”。雖然這有一些例外,但在今天,這句話仍然沒有過時。因此,不管你是在計算機視覺( CV),自然語言處理(NLP)還是統計建模(Statistical Modelling)等領域,想要對原始數據預處理,有幾個方法可以得到更好的訓練數據:

  • 獲取越大的數據庫越好。DNN 對數據很飢渴,越多越好。

  • 去除所有包含損壞數據的訓練樣本,比如短文字,高度扭曲的圖像,假輸出標籤,包含許多虛值(null values)的屬性。

  • Data Augmentation(數據擴張)——生成新樣例。以圖像爲例,重新調節,增加噪聲等等。

2. 選擇恰當的激勵函數(activation function)

激勵函數是所有神經網絡的核心部分之一。

激勵函數把渴望已久的非線性(non-linearity)加入了模型。多年來,Sigmoid 函數 一直是多數人傾向的選擇。但是,Sigmoid 函數不可避免地存在兩個缺陷:1. 尾部  sigmoids 的飽和,進一步導致梯度消失。2. 不以 0 爲中心(輸出在 0 到 1 之間)。

一個更好的替代選擇是 Tanh 函數。數學上來說,Tanh 只是調整、平移過的 Sigmoid 函數:tanh(x) = 2*sigmoid(x) - 1。雖然 Tanh 仍舊存在梯度消失的缺陷,但好消息是:Tanh 以 0 爲中心。因此,把 Tanh 作爲激勵函數能更快地收斂(converge)。我發現使用 Tanh 通常比 Sigmoid 效果更好。

你還可以探索其他選擇,比如 ReLU, SoftSign 等等。對於一些特定任務, 它們能夠改善上述問題。

3. 隱藏單元和隱層(Hidden Units and Layers)的數量

保留超出最優數量的隱藏單元,一般是比較保險的做法。這是因爲任何正則化方法( regularization method)都會處理好超出的單元,至少在某種程度上是這樣。在另一方面,保留比最優數量更少的隱藏單元,會導致更高的模型欠擬合(underfitting)機率。

另外,當採用無監督預訓練的表示時(unsupervised pre-trained representations,下文會做進一步解釋),隱藏單元的最優數目一般會變得更大。因此,預訓練的表示可能會包含許多不相關信息(對於特定任務)。通過增加隱藏單元的數目,模型會得到所需的靈活性,以在預訓練表示中過濾出最合適的信息。

選擇隱層的最優數目比較直接。正如 Yoshua Bengio 在  Quora 中提到的:

“你只需不停增加層,直到測試誤差不再減少。”

4. 權重初始化 (Weight Initialization)

永遠用小的隨機數字初始化權重,以打破不同單元間的對稱性(symmetry)。但權重應該是多小呢?推薦的上限是多少?用什麼概率分佈產生隨機數字?

當使用 Sigmoid 激勵函數時,如果權重初始化爲很大的數字,那麼 sigmoid 會飽和(尾部區域),導致死神經元(dead neurons)。如果權重特別小,梯度也會很小。因此,最好是在中間區域選擇權重,比如說那些圍繞平均值均衡分佈的數值。

幸運的是,已經有許多關於初始權重合適取值的研究。這對於高效的收斂非常重要。爲初始化均衡分佈的權重,均勻分佈(uniform distribution )或許是最好的選擇之一。另外,就像論文中所展示的(Glorot and Bengio, 2010),有更多輸入連接(fan_in)的單位,應該有相對更小的權重。

多虧這些十分透徹的試驗,現在我們已經有了經過檢驗的公式,可以直接用來權重的初始化。

比如說在  ~ Uniform(-r, r) 提取的權重,對於 tanh 激勵  r=sqrt(6/(fan_in+fan_out));對於 sigmoid 激勵 r=4*(sqrt(6/fan_in+fan_out)) 。fan_in 是上一層的大小, 而 fan_out 是下一層的。

5. 學習率

這或許是最重要的超參數之一,調節着學習過程。如果學習率設置得太小,你的模型很可能需要 n 年來收斂。設置得太大,再加上不多的初始訓練樣本,你的損失可能會極高。一般來說,0.01 的學習率比較保險

相比固定學習率,在每個週期、或每幾千個樣例後逐漸降低學習率是另一個選擇。雖然這能更快地訓練,但需要人工決定新的學習率。一般來說,學習率可以在每個週期後減半。幾年前,這種策略十分普遍。

幸運的是,我們現在有了更好的、基於動能(momentum based)的方法,來調整學習率。這取決於誤差函數的曲率。另外,既然有些參數有更快、或更慢的學習速率;它或許能幫助我們針對模型中的單獨參數,設定不同的學習率。

最近有大量關於優化方法的研究,導致了自適應學習率(adaptive learning rates)。目前我們有許多選擇,從老式動能方法( Momentum Method ),到  Adagrad、Adam (個人最愛)、 RMSProp 等等。;類似於 Adagrad 或 Adam 的方法,能替我們省去人工選擇初始學習率的麻煩;給定合適的時間,模型會開始平滑地收斂。當然,選擇一個特別合適的初始學習率仍然能起到幫助作用。

6. 超參數調參:扔掉網格搜索,擁抱隨機搜索

網格搜索(Grid Search )在經典機器學習中十分普遍。但它在尋找 DNN 的最優超參數方面一點也不高效。這主要是由於 DNN 嘗試不同超參數組合所耗費的時間。隨着超參數不斷增長,網格搜索需要的計算性能會指數級增長

有兩種解決辦法:

  1. 取決於你之前的經驗,你可以人工對部分常見超參數調參,比如學習率、隱層數目。

  2. 採用隨機搜索(random search),或者隨機採樣代替網格搜索,來選擇最優超參數。

超參數組合通常在期望範圍之內、從均勻分佈中被選擇出來。加入之前獲得的知識來進一步縮小搜尋空間,也是有可能的(比如,學習率不應該太大也不應該太小)。大家發現,隨機搜索比網格搜索高效地多。

7. 學習方法

隨機梯度下降( Stochastic Gradient Descent )的老方法也許對於 DNN 不是那麼有效率(有例外)。最近,有許多研究聚焦於開發更靈活的優化算法,比如 Adagrad、Adam,、AdaDelta,、RMSProp 等等。在提供自適應學習率之外,這些複雜的方法還對於模型的不同參數使用不同的學習率,通常能有更平滑的收斂。把這些當做超參數是件好事,你應該每次都在訓練數據的子集上試試它們。

8. 權重的維度保持爲 2 的冪

即便是運行最先進的深度學習模型,使用最新、最強大的計算硬件,內存管理仍然在字節(byte)級別上進行。所以,把參數保持在 64, 128, 512, 1024 等 2 的次方永遠是件好事。這也許能幫助分割矩陣和權重,導致學習效率的提升。當用 GPU 運算,這變得更明顯。

9. 無監督預訓練(Unsupervised Pretraining )

不管你進行的是 NLP(自然語言處理)、計算機視覺還是語音識別等任務,無監督預訓練永遠能幫助你訓練監督、或其他無監督模型:NLP 中詞向量就(Word Vectors)無所不在;你可以用 ImageNet 的數據庫,使用無監督方式對你的模型預訓練,或是對於兩個類別的監督分類;或是更大頻域的音頻樣本,來在揚聲器消崎模型(speaker disambiguation model)中使用該信息。

10. Mini-Batch(小批量) 對比隨機學習(Stochastic Learning)

訓練一個模型的主要目的是學習合適的參數,即產生輸入到輸出的最優映射。這些參數利用每個訓練樣本進行調參,不管你決定使用 batch, mini-batch 還是隨機學習。當採用隨機學習方法時,學習每個訓練樣本後權重的梯度都會進行調參,向梯度加入噪音(隨機學習中“隨機”的由來)。這樣做的結果十分理想,比如說,訓練中加入的噪音使得模型更不容易過擬合

但是,隨機學習方法也許效率不高。如今的計算設備有非常可觀的運算能力,隨機學習很可能會浪費其中的一大部分。如果我們能計算矩陣相乘,那麼爲什麼要限制自己,重複單個矢量組之間的乘法呢?因此,爲了更高的吞吐率和更快的學習,我推薦使用 mini-batch 而不是隨機學習。

但是,選擇適當的 batch 規模同樣重要。所以我們能保留一些噪音(相比大規模 batch),與此同時更高效地利用計算性能。一般來說,包含  16 個到 128 個樣例的 batch(2 的冪)是不錯的選擇。通常,一旦你發現了更重要的超參數(通過隨機搜索或是人工搜索),batch 規模就會確性下來。但是,有些場景中模型得到訓練數據流(比如網絡學習),那麼採用隨機學習就是不錯的選擇。

11. 打亂訓練樣本

這來自於信息理論(Information Theory)——“學習到一件不太可能發生的事卻發生了,比學習一件很可能發生的事已經發生,包含更多的信息。”同樣的,把訓練樣例的順序隨機化(在不同週期,或者 mini-batch),會導致更快的收斂。如果模型看到的很多樣例不在同一種順序下,運算速度會有小幅提升。

12. 使用 Dropout 正則化

如果有數百萬的參數需要學習,正則化就是避免 DNN 過擬合的必須手段。你也可以繼續使用 L1/L2 正則化,但 Dropout 是檢查 DNN 過擬合的更好方式(雷鋒網按:Dropout 是指隨機讓網絡某些隱層節點的權重不工作,不工作的那些節點可以暫時認爲不是網絡結構的一部分,但是它的權重會保留下來)。執行 Dropout 很容易,並且通常能帶來更快地學習。0.5 的默認值是一個不錯的選擇,當然,這取決於具體任務。如果模型不太複雜,0.2 的 Dropout 值或許就夠了。

在測試階段,Dropout 應該被關閉,權重要調整到相應大小。只要對一個模型進行 Dropout 正則化,多一點訓練時間,誤差一定會降低。

13. 週期 / 訓練迭代次數

“對深度學習模型進行多個週期的訓練,會得到更好的模型”——我們經常聽到這句話。但多少週期纔是“多”呢?其實,這裏有一個簡單的策略:繼續按照一個固定的樣例數或者週期訓練模型,比如兩萬個樣例或者一個週期。在每批樣例之後,比較測試誤差(test error)和訓練誤差(train error),如果它們的差距在縮小,那麼繼續訓練。另外,記得在每批訓練之後,保存模型的參數,所以訓練好之後你可以從多個模型中做選擇。

14. 可視化

訓練深度學習模型有上千種出差錯的方式。我猜大家都遇到過這樣的場景:模型已經訓練了幾個小時或者好幾天,然而在訓練完成之後,才意識到某個地方出問題了。爲了不讓你自己神經錯亂,一定要對訓練過程作可視化處理。比較顯而易見的措施是保存或打印損失值、訓練誤差、測試誤差等項目的日誌。

在此之外,一個很好的措施是採用可視化庫(visualization library ),在幾個訓練樣例之後、或者週期之間,生成權重柱狀圖。這或許能幫助我們追蹤深度學習模型中的一些常見問題,比如梯度消失與梯度爆發(Exploding Gradient)。

15. 使用支持 GPU 和自動微分法 (Automatic Differentiation)的庫

謝天謝地,對於快速創建原型模型,我們已經有了相當不錯的庫,比如 Theano, Tensorflow, Keras 等等。幾乎所有這些深度學習庫支持 GPU 計算和自動微分法。所以,你不需要深入研究核心 GPU 編程技術(除非你想——這絕對很有意思)。你也不需要寫自己的微分代碼——在非常複雜的模型上這相當費勁(但若需要,你應該有能力去做)。 Tensorflow還提供了分佈式計算的支持——如果你是土豪的話.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章