上一期,我們一起學習了TensorFlow在訓練深度網絡的時候怎麼解決梯度消失或梯度爆炸的問題,以及怎麼儘可能的減少訓練時間。
深度學習三人行(第4期)---- TF訓練DNN之進階
這期我們繼續學習訓練深度網絡時的一大神器----優化器。學習的路上,我們多多交流,共同進步。本期主要內容如下:
- Momentum optimization
- Nesterov Accelerated Gradient
- AdaGrad
- RMSProp
- Adam Optimization
1. 回顧
我們知道在訓練一個比較大的深度神經網絡的時候,速度上一般都是比較慢的。通過上期的學習,我們已經知道有4種方法可以加速我們的訓練過程,如下:
a. 選擇一個合適的權重初始化策略
b. 用一個合適的激活函數
c. 運用Batch Normalization策略
d. 複用之前的網絡模型
但是今天我們要學習的是另外一個加速神器--優化器,它要比一般的梯度下降算法快很多。我們這裏主要介紹幾種常見的優化器,其中包括:Momentum optimization,Nesterov Accelerated Gradient,AdaGrad,RMSProp,Adam Optimization。
2. Momentum optimization
2.1 原理
momentum optimization可以翻譯爲動量優化器,該優化器背後的思想很簡單: 假設一個圓球從一個斜坡上滾下去,一開始速度會很慢,但是隨着時間的增加,速度會越來越快,考慮到摩擦力和空氣阻力,最終會達到一個恆定的速度(空氣阻力跟速度的平方成正比)。這就是momentum optimization 背後的思想。跟一般的梯度下降法相比,顯然動量優化速度更快。
我們再回顧下一般梯度下降權重的更新是用權重直接減去學習率乘以梯度:
這種更新權重的方式,並不關心之前的梯度,只根據當前梯度值進行更新。如果當前梯度比較小的話,那麼尋優的過程就比較費時。
動力優化根據這一缺點對一般的梯度下降法進行了改進。動力優化更多的考慮了之前的梯度信息,在每一次的迭代中,都會把當前梯度信息加到動力向量m中,最終根據減去動力向量來更新權重,如下公式:
換句話說,這裏把梯度當做是加速度而並不是速度,爲了模擬一些摩擦力和阻力來防止速度變得過大,該算法增加了一個超參數β,該值的取值範圍爲0~1,當β=0時表示較高的阻力,此時梯度的更新等同於一般的梯度優化。當β=1的時候表示沒有阻力,此時梯度更新最快,一般情況下該值設置爲0.9.
從上面公式可以看出,假如梯度恆定爲∇的話,權重更新的最終速度爲η∇/(1−β)。假如β=0.9的話,那麼momentum optimization的最終優化速度是一般梯度下降的10倍左右。這就使的動力優化比一般梯度優化能夠更快的逃離平坦區域。
由於動力加速度的存在,所以在尋優的時候可能會超過最優點一點,然後返回,再超過,再返回最終穩定在最優點。這就是爲什麼要在算法中加入超參數β的一個原因,它能夠減少震盪加速收斂。
2.2 實現
在TensorFlow中實現Momentum Optimization比較簡單,如下:
1optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, 2 momentum=0.9)
動力優化的一個缺點就是多了一個超參數β去調節。然而,這個超參數一般情況下設置爲0.9就能夠很好的工作,並不需要經常去調節。
3. Nesterov Accelerated Gradient
3.1 原理
Nesterov Accelerated Gradient(NAG)算法,其實是對Momentum Optimization的一個小小的改進,在動力優化中,更新動力變量m是在當前(θ)的梯度上進行更新的,而在NAG算法中,對動力變量的更新在動力方向上稍微提前了一些(θ+βm),如下:
上面的改進是可行的原因就在於,Momentum Optimization中的動力向量m的方向是指向最優點的,因此用更前一點的梯度來代替當前的梯度去更新動力向量更爲精確。如下圖:
上圖中,∇1代表損失函數在起始點θ的梯度,而∇2代表損失函數在點θ+βm的梯度值,可以看到NAG更接近最優點,隨着時間的累積,NAG會比動力優化器明顯的更快一些。此外我們還可以看到,當動力向量推動權重接近最優值的時候,∇1會繼續加速推動,使得遠離最優值,而∇2則已經開始往回拉了,這就減少了震盪進而使得更快收斂。
3.2 實現
在training深度網絡的時候,NAG通常會比Momentum Optimization更快收斂,用起來也比較簡單只需要將動力優化器中設置參數use_nesterov=True即可,如下:
1optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, 2 momentum=0.9, use_nesterov=True)
4. AdaGrad
4.1 原理
考慮到之前介紹的細長碗的最優化這個問題,一般的梯度優化會在陡峭的區域快速下降,而在平坦區域慢慢走向最優值。如果算法能夠提前監測到這種情況就會更好,就可以在陡峭的地方慢慢下降(防止錯過最優點),在平坦區域快速通過,這樣就能更快的找到最優點。AdaGrad算法就是通過衰減學習率來進行達到這個目的的。公式原理如下:
上面公式1中在s中累加了梯度的平方,(⊗表示矩陣中對應元素相乘),而在公式2中和之前的梯度下降比較類似,唯一不同的是對梯度向量進行了衰減或者說是對學習率η做了衰減(⊘表示矩陣中對應元素相除,而ε則是防止除數爲0,通常設置爲10^(−10))。
換句話說就是AdaGrad算法對學習率進行了自適應化,當梯度比較大的時候,學習率就比較小,而當梯度比較小的時候,學習率就比較大。如下圖,該算法能夠更明顯的向最優點逼近。
然而事實證明,AdaGrad算法在一些簡單的二項式問題上表現優異,但是在training深度網絡的時候,由於學習率衰減過多,常常會過早停止尋優。因此,儘管TensorFlow中有提供該方法AdaGradOptimizer,但是不建議用該優化器去訓練深度網絡。因此這裏就不寫出實現代碼了。
5. RMSProp
5.1 原理
儘管AdaGrad算法衰減過快而導致無法收斂到最優點的問題,RMSProp算法通過修改AdaGrad算法第一步的梯度累加方式,改累加所有的梯度爲對累加的梯度乘以一個衰減係數,如下公式:
可知,該方法又多了一個超參數衰減率β,一般設置爲β=0.9。理解了AdaGrad算法,這裏就不再過多解釋了。
5.2 實現
當然,TensorFlow對該算法也是有提供的,如下:
1optimizer = tf.train.RMSPropOptimizer(learning_rate=learning_rate, 2 momentum=0.9, decay=0.9, epsilon=1e-10)
這個方法的表現還是不錯的,在簡單問題上表現優於AdaGrad算法,一般情況下性能也優於Momentum Optimization和NAG方法。事實上,在Adam算法出現之前,這個方法是一般訓練網絡時候的最優選則。
6. Adam Optimization
6.1 原理
Adam代表adaptive moment estimation,結合了Momentum Optimization和RMSProp的思想。運用了動力優化方法中的利用歷史梯度信息,和RMSProp中利用歷史歷史梯度的平方的相關信息,公式如下:
從上面1,2,5公式可以看出,該算法跟Momentum Optimization和RMSProp特別像,唯一不同的是在公式1中運用了歷史梯度指數衰減的均值而不是歷史梯度指數衰減的和。公式3,4其實是一個小技巧點,因爲一般m和s會被初始化爲0,所以在training開始的時候回一直偏向0,公式3,4能夠在training初期快速提高這兩個變量值。
上公式中多了3個超參數β1,β2,ε,這三個參數一般設置爲0.9,0.99和10^(−8).
6.2 實現
在Tensorflow中用法都是很簡單,所有參數都爲默認值的情況下如下:
1optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
其實Adam算法是一個自動調節學習率的算法,一般可以將學習率設置爲0.001.事實證明該算法在一般深度網絡中是優選擇。
7. 小結
我們從一般梯度下降出發,一起學習了最近比較常見的優化器,包括Momentum Optimization, Nesterov Accelerated Gradient, AdaGrad, RMSProp和Adam Optimization。其中Adam算法是目前在training深度網絡中的優選。