深度學習中的一些組件及使用技巧

【說在前面】本人博客新手一枚,象牙塔的老白,職業場的小白。如下內容僅爲我的看法,歡迎批評指正,不喜勿噴![認真看圖][認真看圖]html

【補充說明】深度學習有多火,我就很少說了。本文主要介紹深度學習項目實踐過程當中可能遇到的一些組件及使用技巧!python

1、Optimizor優化器選擇

1. 梯度降低:經典

梯度降低的通用計算公式以下:面試

  • g_t=\nabla_{\theta_{t-1}}{f(\theta_{t-1})}
  • \Delta{\theta_t}=-\eta*g_t

其中,\eta是學習率,g_t是梯度。梯度降低徹底依賴於當前的梯度,因此\eta可理解爲容許當前梯度多大程度影響參數更新。算法

梯度降低主要包含三種梯度降低:網絡

(1)批量梯度降低(Batch Gradient Descent)cors

  • 使用全部的訓練樣原本更新每次迭代中的模型參數

(2)隨機梯度降低(Stochastic Gradient Descent)框架

  • 在每次迭代中,僅使用單個訓練樣本更新參數(訓練樣本一般是隨機選擇的)

(3)小批量梯度降低(Mini-Batch Gradient Descent):這個最經常使用機器學習

  • 訓練時不是使用全部的樣本,而是取一個批次的樣原本更新模型參數
  • 小批量梯度降低試圖在隨機梯度降低的穩健性和批量梯度降低的效率之間找到平衡

梯度降低的缺點:函數

  • 選擇合適的learning rate比較困難
  • 對全部的參數更新均使用一樣的learning rate
  • 可能被困在鞍點,容易產生局部最優,不能達到全局最優

2. Momentum

Momentum是模擬物理裏動量的概念,公式以下:post

  • m_t=\mu*m_{t-1}+g_t
  • \Delta{\theta_t}=-\eta*m_t

其中,\mu是動量因子。Momentum積累以前的動量來替代真正的梯度。

Momentum有以下特色:

  • 降低初期時,因爲降低方向和梯度方向一致,而使t時刻的動量和變化量變大,從而達到加速的目的
  • 降低中後期時,在局部最小值來回震盪的時候,使得更新幅度增大,跳出陷阱
  • 在梯度改變方向的時候,可以減小更新 

總的來講,Momentum能夠加速SGD算法的收斂速度,而且下降SGD算法收斂時的震盪。

3. Nesterov

將上一節中的公式展開可得:

能夠看出,Momentum並無直接改變當前梯度。Nesterov的改進就是讓以前的動量直接影響當前的動量。即:

  • g_t=\nabla_{\theta_{t-1}}{f(\theta_{t-1}-\eta*\mu*m_{t-1})}
  • m_t=\mu*m_{t-1}+g_t
  • \Delta{\theta_t}=-\eta*m_t

其中,加上Nesterov項後,梯度在大的跳躍後,再計算當前梯度進行校訂。

Nesterov有以下特色:

  • 對於Momentum,首先計算一個梯度(短的藍色向量),而後在加速更新梯度的方向進行一個大的跳躍(長的藍色向量)
  • 對於Nesterov,首先在以前加速的梯度方向進行一個大的跳躍(棕色向量),而後計算梯度進行校訂(綠色梯向量)

總的來講,Nesterov項在梯度更新時作了一個校訂,避免前進太快,同時提升靈敏度。

以上三種方法均須要人工設置一些學習率,接下來介紹幾種自適應學習率的方法!

4. Adagrad

Adagrad對學習率進行了一個約束。即:

  • n_t=n_{t-1}+g_t^2
  • \Delta{\theta_t}=-\frac{\eta}{\sqrt{n_t+\epsilon}}*g_t

其中,對g_t從1到t進行一個遞推,造成一個約束項regularizer,\epsilon用來保證分母非0。

Adagrad有以下特色:

  • 前期g_t較小的時候,regularizer較大,可以放大梯度
  • 後期g_t較大的時候,regularizer較小,可以約束梯度
  • 高頻特徵更新步長較小,低頻特徵更新較大,適合處理稀疏梯度
  • 可以自適應學習率,避免了手動調整學習率的麻煩

Adagrad的缺點:

  • 由公式能夠看出,仍依賴於人工設置一個全局學習率
  • \eta設置過大的話,會使regularizer過於敏感,對梯度的調節太大
  • 中後期,分母上梯度平方的累加將會愈來愈大,使gradient\to0,使得訓練提早結束

5. Adadelta

Adadelta是對Adagrad的擴展,它主要解決了adagrad算法單調遞減學習率的問題。Adagrad會累加以前全部的梯度平方,而Adadelta只累加固定大小的項,而且也不直接存儲這些項,僅僅是近似計算對應的平均值。即:

  • n_t=\nu*n_{t-1}+(1-\nu)*g_t^2
  • \Delta{\theta_t} = -\frac{\eta}{\sqrt{n_t+\epsilon}}*g_t

其中,Adadelta仍是依賴於全局學習率,可是作了必定處理,通過近似牛頓迭代法以後:

  • E|g^2|_t=\rho*E|g^2|_{t-1}+(1-\rho)*g_t^2
  • \Delta{x_t}=-\frac{\sqrt{\sum_{r=1}^{t-1}\Delta{x_r}}}{\sqrt{E|g^2|_t+\epsilon}}

其中,E表明求指望。此時,能夠看出Adadelta已經不用依賴於全局學習率了。

Adadelta還有以下特色:

  • 訓練初中期,加速效果不錯,很快
  • 訓練後期,反覆在局部最小值附近抖動

6. RMSprop

RMSprop能夠算做Adadelta的一個特例,一樣是用於解決adagrad算法學習率消失的問題。

\rho=0.5時,E|g^2|_t=\rho*E|g^2|_{t-1}+(1-\rho)*g_t^2就變爲了求梯度平方和的平均數。

若是再求根的話,就變成了RMS(均方根):

  • RMS|g|_t=\sqrt{E|g^2|_t+\epsilon}

此時,這個RMS就能夠做爲學習率\eta的一個約束:

  • \Delta{x_t}=-\frac{\eta}{RMS|g|_t}*g_t

RMSprop有以下特色:

  • 依然依賴於全局學習率
  • 是Adagrad的一種發展,也是Adadelta的變體,效果趨於兩者之間
  • 適合處理非平穩目標 

7. Adam:經常使用

Adam本質上是帶有動量項的RMSprop,它利用梯度的一階矩估計和二階矩估計動態調整每一個參數的學習率。

通過偏置校訂後,每一次迭代學習率都有個肯定範圍,使得參數比較平穩。公式以下:

  • m_t=\mu*m_{t-1}+(1-\mu)*g_t
  • n_t=\nu*n_{t-1}+(1-\nu)*g_t^2
  • \hat{m_t}=\frac{m_t}{1-\mu^t}
  • \hat{n_t}=\frac{n_t}{1-\nu^t}
  • \Delta{\theta_t}=-\frac{\hat{m_t}}{\sqrt{\hat{n_t}}+\epsilon}*\eta

其中,m_tn_t分別是對梯度的一階矩估計和二階矩估計,能夠看做對指望E|g_t|E|g_t^2|的估計;\hat{m_t}\hat{n_t}是對m_tn_t的校訂,這樣能夠近似爲對指望的無偏估計。 能夠看出,直接對梯度的矩估計對內存沒有額外的要求,並且能夠根據梯度進行動態調整,而-\frac{\hat{m_t}}{\sqrt{\hat{n_t}}+\epsilon}對學習率造成一個動態約束,並且有明確的範圍。

Adam有以下特色:

  • 結合了Adagrad善於處理稀疏梯度和RMSprop善於處理非平穩目標的優勢
  • 對內存需求較小
  • 爲不一樣的參數計算不一樣的自適應學習率
  • 也適用於大多非凸優化,適用於大數據集和高維空間

8. 其餘

例如Adamax(Adam的一種變體)、Nadam(相似於帶有Nesterov動量項的Adam)等,這裏不展開了。

9. 經驗總結

  • 對於稀疏數據,使用學習率可自適應的優化方法(例如Adagrad/Adadelta/RMSprop/Adam等),且最好採用默認值
  • SGD一般訓練時間更長,可是在好的初始化和學習率調度方案的狀況下,結果更可靠
  • 若是須要更快的收斂,或者是訓練更深更復雜的神經網絡,須要用一種自適應的算法

2、激活函數選擇

1. 經常使用的激活函數

發現這麼寫下去,篇幅太大了,因此找到一張圖,歸納一下吧:

 

經常使用的主要是這些吧,各類激活函數的特色看圖也顯而易見,其餘的(例如PReLU等)就不拓展了。

2. 經驗總結

  • 對於輸出層:二分類任務通常選用Sigmoid輸出,多分類任務通常選用Softmax輸出,迴歸任務通常選用線性輸出。
  • 對於中間隱層:優先選擇Relu激活函數(Relu能夠有效解決Sigmoid和tanh出現的梯度彌散問題,且能更快收斂)。

3、防止過擬合

1. 數據集擴充

即增大訓練集的規模,實在難以得到新數據也可使用數據集加強的方法。

例如能夠對圖像數據集採用水平/垂直旋轉/翻轉、隨機改變亮度和顏色、隨機模糊圖像、隨機裁剪等方法進行數據集加強。

2. L1/L2正則化

正則化,就是在原來的loss function的基礎上,加上了一些正則化項或者稱爲模型複雜度懲罰項。

以線性迴歸爲例,優化目標:

min [公式] 

加上L1正則項(lasso迴歸):
min [公式] 

加上L2正則項(嶺迴歸):

min [公式] 

其中,L1範數更容易獲得稀疏解(解向量中0比較多);L2範數能讓解比較小(靠近0),可是比較平滑(不等於0)。

3. Dropout

Dropout提供了一個簡單的方法來提高性能。其實至關於作簡單的Ensemble,但訓練速度會慢一些。

 

4. 提早終止Early stopping

5. 交叉驗證

 

剩下就是選擇合適的模型和網絡結構了,甚至能夠採用多模型融合等思路。

4、防止梯度消失/爆炸

1. 使用合適的激活函數:ReLU等 

解決Sigmoid函數存在的梯度消失/爆炸問題。

2. 預訓練加微調:DBN等

Hinton爲了解決梯度的問題,提出採起無監督逐層訓練方法,其基本思想是每次訓練一層隱節點,訓練時將上一層隱節點的輸出做爲輸入,而本層隱節點的輸出做爲下一層隱節點的輸入,此過程就是逐層「預訓練」。在預訓練完成後,再對整個網絡進行「微調」。

3. 梯度剪切、正則

梯度剪切這個方案主要是針對梯度爆炸提出的,其思想是設置一個梯度剪切閾值,而後更新梯度的時候,若是梯度超過這個閾值,那麼就將其強制限制在這個範圍以內。另一種解決梯度爆炸的手段是採用權重正則化,比較常見的是L1正則和L2正則,以上已經提到了。

4. Batch Normalization

對每一層的輸出作scale和shift的方法,經過必定的規範化手段,把每層神經網絡任意神經元這個輸入值的分佈強行拉回到接近均值爲0方差爲1的標準正太分佈,即嚴重偏離的分佈強制拉回比較標準的分佈。這樣使得激活輸入值落在非線性函數對輸入比較敏感的區域,這樣輸入的小變化就會致使損失函數較大的變化,使得讓梯度變大,避免梯度消失問題產生。並且梯度變大意味着學習收斂速度快,能大大加快訓練速度。

5. 殘差結構 Resnet

若是你但願訓練一個更深更復雜的網絡,那麼殘差塊絕對是一個重要的組件,它可讓你的網絡訓練的更深。

6. 採用LSTM等模型

我在序列模型專題有介紹到LSTM,這裏再也不贅述。

5、權值初始化

1. 隨機初始化

有一些經常使用的初始化方法:

  • 直接用0.02*randn(num_params)來初始化,固然別的值也能夠。
  • 依次初始化每個weight矩陣,用init_scale / sqrt(layer_width) * randn,init_scale能夠被設置爲0.1或者1。

初始化很重要,知乎大佬們的慘痛教訓:

  • 用normal初始化CNN的參數,最後acc只能到70%多,僅僅改爲xavier,acc能夠到98%。
  • 初始化word embedding,使用了默認的initializer,速度慢且效果很差。改成uniform,訓練速度和結果也飆升。

2. 遷移學習

能夠採用遷移學習預訓練的方式。說到這裏,我以後想寫一個遷移學習的專題。

6、數據預處理

1. 標準化/歸一化處理

就是0均值和1方差化。主要是爲了公平對待每一個特徵、使優化過程變得平穩、消除量綱影響等。

2. Shuffle處理

在訓練的過程當中,若是數據很整齊,那每次學習到的特徵都是與某一個特徵相關,會讓學習效果有所誤差。

所以,通常在訓練的過程當中,建議要將數據打亂,這樣纔可以更好的實現泛化能力。

7、學習率 learning rate

通常建議從一個正常大小的學習率開始,朝着終點不斷縮小。

 

8、批次大小 batch_size

batch_size會影響優化過程,建議值取64和128等,過小訓練速度慢,太大容易過擬合。

9、損失函數 Loss

1. 多分類問題選用Softmax+交叉熵

當Sigmoid函數和MSE一塊兒使用時會出現梯度消失。緣由以下:

MSE對參數的偏導:

  • 在這裏插入圖片描述
  • 在這裏插入圖片描述

corss-entropy對參數的偏導:

  • 在這裏插入圖片描述
  • 在這裏插入圖片描述

以上,相對於Sigmoid求損失函數,在梯度計算層面上,交叉熵對參數的偏導不含對Sigmoid函數的求導,而均方偏差MSE等則含有Sigmoid函數的偏導項。同時,Sigmoid的值很小或者很大時梯度幾乎爲零,這會使得梯度降低算法沒法取得有效進展,交叉熵則避免了這一問題。

爲了彌補Sigmoid 型函數的導數形式易發生飽和的缺陷,能夠引入Softmax做爲預測結果,再計算交叉熵損失。因爲交叉熵涉及到計算每一個類別的機率,因此在神經網絡中,交叉熵與Softmax函數緊密相關。

10、其餘

例如訓練時能夠先用一小部分數據集跑,看看損失的變化趨勢,有助於更快找到錯誤並調整網絡結構等技巧。

另外,看到一張不一樣參數對於網絡訓練的影響程度圖,分享一下:

最後,雖然有不少組件和技巧能夠方便使用(框架中通常都封裝好了),可是仍是須要注意各組件、技巧之間的靈活組合,才能取得最佳結果。

 

若是您對數據挖掘感興趣,歡迎瀏覽個人另幾篇博客:數據挖掘比賽/項目全流程介紹

若是你對智能推薦感興趣,歡迎先瀏覽個人另幾篇隨筆:智能推薦算法演變及學習筆記

若是您對人工智能算法感興趣,歡迎瀏覽個人另外一篇博客:人工智能新手入門學習路線和學習資源合集(含AI綜述/python/機器學習/深度學習/tensorflow)人工智能領域經常使用的開源框架和庫(含機器學習/深度學習/強化學習/知識圖譜/圖神經網絡)

若是你是計算機專業的應屆畢業生,歡迎瀏覽個人另一篇博客:若是你是一個計算機領域的應屆生,你如何準備求職面試?

若是你是計算機專業的本科生,歡迎瀏覽個人另一篇博客:若是你是一個計算機領域的本科生,你能夠選擇學習什麼?

若是你是計算機專業的研究生,歡迎瀏覽個人另一篇博客:若是你是一個計算機領域的研究生,你能夠選擇學習什麼?

若是你對金融科技感興趣,歡迎瀏覽個人另外一篇博客:若是你想了解金融科技,不妨先了解金融科技有哪些可能?

以後博主將持續分享各大算法的學習思路和學習筆記:hello world: 個人博客寫做思路

相關文章
相關標籤/搜索