一文看懂常用的梯度下降演算法
梯度下降演算法(Gradient Descent Optimization)是神經網路模型訓練最常用的優化演算法。對於深度學習模型,基本都是採用梯度下降演算法來進行優化訓練的。梯度下降演算法背後的原理:目標函式關於引數的梯度將是目標函式上升最快的方向。對於最小化優化問題,只需要將引數沿著梯度相反的方向前進一個步長,就可以實現目標函式的下降。這個步長又稱為學習速率。引數更新公式如下:
其中是引數的梯度,根據計算目標函式採用資料量的不同,梯度下降演算法又可以分為批量梯度下降演算法(Batch Gradient Descent),隨機梯度下降演算法(Stochastic GradientDescent
對於神經網路模型,藉助於
01
Momentum optimization
衝量梯度下降演算法是BorisPolyak在1964年提出的,其基於這樣一個物理事實:將一個小球從山頂滾下,其初始速率很慢,但在加速度作用下速率很快增加,並最終由於阻力的存在達到一個穩定速率。對於衝量梯度下降演算法,其更新方程如下:
可以看到,引數更新時不僅考慮當前梯度值,而且加上了一個積累項(衝量),但多了一個超參,一般取接近1的值如0.9。相比原始梯度下降演算法,衝量梯度下降演算法有助於加速收斂。當梯度與衝量方向一致時,衝量項會增加,而相反時,衝量項減少,因此衝量梯度下降演算法可以減少訓練的震盪過程。TensorFlow中提供了這一優化器:tf.train.MomentumOptimizer(learning_rate=learning_rate,momentum=0.9)。
02
NAG
NAG演算法全稱Nesterov Accelerated Gradient,是YuriiNesterov在1983年提出的對衝量梯度下降演算法的改進版本,其速度更快。其變化之處在於計算“超前梯度”更新衝量項,具體公式如下:
既然引數要沿著更新,不妨計算未來位置的梯度,然後合併兩項作為最終的更新項,其具體效果如圖1所示,可以看到一定的加速效果。在TensorFlow中,NAG優化器為:tf.train.MomentumOptimizer(learning_rate=learning_rate,momentum=0.9, use_nesterov=True)
圖1 NAG效果圖
03
AdaGrad
AdaGrad是Duchi在2011年提出的一種學習速率自適應的梯度下降演算法。在訓練迭代過程,其學習速率是逐漸衰減的,經常更新的引數其學習速率衰減更快,這是一種自適應演算法。其更新過程如下:
其中是梯度平方的積累量,在進行引數更新時,學習速率要除以這個積累量的平方根,其中加上一個很小值是為了防止除0的出現。由於是該項逐漸增加的,那麼學習速率是衰減的。考慮如圖2所示的情況,目標函式在兩個方向的坡度不一樣,如果是原始的梯度下降演算法,在接近坡底時收斂速度比較慢。而當採用AdaGrad,這種情況可以被改觀。由於比較陡的方向梯度比較大,其學習速率將衰減得更快,這有利於引數沿著更接近坡底的方向移動,從而加速收斂。
圖2 AdaGrad效果圖
前面說到AdaGrad其學習速率實際上是不斷衰減的,這會導致一個很大的問題,就是訓練後期學習速率很小,導致訓練過早停止,因此在實際中AdaGrad一般不會被採用,下面的演算法將改進這一致命缺陷。不過TensorFlow也提供了這一優化器:tf.train.AdagradOptimizer。
04
RMSprop
RMSprop是Hinton在他的課程上講到的,其算是對Adagrad演算法的改進,主要是解決學習速率過快衰減的問題。其實思路很簡單,類似Momentum思想,引入一個超引數,在積累梯度平方項進行衰減:
可以認為僅僅對距離時間較近的梯度進行積累,其中一般取值0.9,其實這樣就是一個指數衰減的均值項,減少了出現的爆炸情況,因此有助於避免學習速率很快下降的問題。同時Hinton也建議學習速率設定為0.001。RMSprop是屬於一種比較好的優化演算法了,在TensorFlow中當然有其身影:tf.train.RMSPropOptimizer(learning_rate=learning_rate,momentum=0.9, decay=0.9, epsilon=1e-10)。
不得不說點題外話,同時期還有一個Adadelta演算法,其也是Adagrad演算法的改進,而且改進思路和RMSprop很像,但是其背後是基於一次梯度近似代替二次梯度的思想,感興趣的可以看看相應的論文,這裡不再贅述。
05
AdamAdam全稱Adaptive moment estimation,是Kingma等在2015年提出的一種新的優化演算法,其結合了Momentum和RMSprop演算法的思想。相比Momentum演算法,其學習速率是自適應的,而相比RMSprop,其增加了衝量項。所以,Adam是兩者的結合體:
可以看到前兩項和Momentum和RMSprop是非常一致的,由於和的初始值一般設定為0,在訓練初期其可能較小,第三和第四項主要是為了放大它們。最後一項是引數更新。其中超引數的建議值是。Adm是效能非常好的演算法,在TensorFlow其實現如下: tf.train.AdamOptimizer(learning_rate=0.001,beta1=0.9, beta2=0.999, epsilon=1e-08)。
二學習速率
前面也說過學習速率的問題,對於梯度下降演算法,這應該是一個最重要的超引數。如果學習速率設定得非常大,那麼訓練可能不會收斂,就直接發散了;如果設定的比較小,雖然可以收斂,但是訓練時間可能無法接受;如果設定的稍微高一些,訓練速度會很快,但是當接近最優點會發生震盪,甚至無法穩定。不同學習速率的選擇影響可能非常大,如圖3所示。
圖3不同學習速率的訓練效果
理想的學習速率是:剛開始設定較大,有很快的收斂速度,然後慢慢衰減,保證穩定到達最優點。所以,前面的很多演算法都是學習速率自適應的。除此之外,還可以手動實現這樣一個自適應過程,如實現學習速率指數式衰減:
在TensorFlow中,你可以這樣實現:
initial_learning_rate = 0.1
decay_steps = 10000
decay_rate = 1/10
global_step = tf.Variable(0, trainable=False)
learning_rate = tf.train.exponential_decay(initial_learning_rate,
global_step, decay_steps, decay_rate)
# decayed_learning_rate = learning_rate *
# decay_rate ^ (global_step / decay_steps)
optimizer = tf.train.MomentumOptimizer(learning_rate, momentum=0.9)
training_op = optimizer.minimize(loss, global_step=global_step)
三總結
本文簡單介紹了梯度下降演算法的分類以及常用的改進演算法,總結來看,優先選擇學習速率自適應的演算法如RMSprop和Adam演算法,大部分情況下其效果是較好的。還有一定要特別注意學習速率的問題。其實還有很多方面會影響梯度下降演算法,如梯度的消失與爆炸,這也是要額外注意的。最後不得不說,梯度下降演算法目前無法保證全域性收斂還將是一個持續性的數學難題。