目錄
1.梯度下降法
梯度下降法可以分為三種,批量梯度下降法(BGD)、小批量梯度下降(MBGD)、隨機梯度下降法(SGD),這三種方法是優化時對資料所採取的的策略,但所運用的思想是一致的,都是梯度下降,現在先講解下梯度下降。
假設有一目標函式y =x2,對這一凸函式希望尋找到其最小值,這裡可以輕鬆得到梯度為2x,我們假設學習率eta=0.1,每次自變數的變化為eta*2x,既然是梯度下降,那麼可得到x = x-eta*2x,程式碼如下:
import numpy as np import math import matplotlib.pyplot as plt %matplotlib inline #y=x**2 def gd(eta): x =10 res = [x] for i in range(10): x -= eta*2*x res.append(x) return res res = gd(0.1) def show_trace(res): n = max(abs(min(res)), abs(max(res)), 10) f_line = np.arange(-n, n, 0.1) # plt.set_figsize() plt.plot(f_line, [x * x for x in f_line]) plt.plot(res, [x * x for x in res], '-o') plt.xlabel('x') plt.ylabel('f(x)') show_trace(res)
迭代10次後結果入下圖:
可見y隨著梯度一步步向最小值優化,這個就是梯度下降的核心,對於多元的也是如此,例如y=x12+2x22,見下圖,其他形式的變種也是在這個的基礎上進行改進,下面開始介紹三種下降方法。
為便於理解,我們假定進行線性迴歸擬合,設函式為
hθ (x(i)) = θ1x(i) + θ0 其中i = 1,2,3,...m 代表樣本數
對應的損失函式為
(1)批量梯度下降(Batch Gradient Descent,BGD)
BGD是指每次迭代時用所用樣本資料計算梯度,
- 對目標函式求偏導,其中 i=1,2,...,m 表示樣本數, j=0,1 表示特徵數。
- 每次迭代對引數進行更新
優點:
1.每次計算運用所有資料進行運算,可用矩陣實現平行計算
2.通過所有資料求梯度在全域性範圍進行搜尋,當目標函式為凸函式時,一定能達到全域性最優
缺點:
1.每次求梯度用全部資料會導致訓練速度緩慢
(2)隨機梯度下降(Stochastic Gradient Descent,SGD)
隨機梯度下降與批量梯度下降最大的不同在於前者每次計算梯度只採用一個隨機樣本,即m=1,公式中無求和符號
優點:
1.由於不是在全部訓練資料上的損失函式,而是在每輪迭代中,隨機優化某一條訓練資料上的損失函式,這樣每一輪引數的更新速度大大加快。
缺點:
1.準確度下降。由於即使在目標函式為強凸函式的情況下,SGD仍舊無法做到線性收斂。
2.可能會收斂到區域性最優,由於單個樣本並不能代表全體樣本的趨勢。
3.不易於並行實現。
解釋下為什麼SGD比BGD迭代更快,假如有100w條資料,BGD一次迭代需要計算100w個樣本,可能迭代10次後才能達到全域性最優,那麼就計算了1000w次梯度;要換成SGD每次隨機一個樣本,100w條資料迭代完後就可能找到了最優解,此時的計算時間是遠小於BGD的。
(3)小批量梯度下降(Mini-Batch Gradient Descent,MBGD)
結合BGD和SGD的優缺點,從而衍生出了小批量梯度下降法,跟批量梯度下降很相似,他們的差別在於m=batch,每次隨機更新batch個樣本資料的梯度,當batch為1時就為SGD,當batch為樣本數總數N時即為BGD
優點:
1.通過矩陣運算,每次在一個batch上優化神經網路引數並不會比單個資料慢太多。
2.每次使用一個batch可以大大減小收斂所需要的迭代次數,同時可以使收斂到的結果更加接近梯度下降的效果。(比如上例中的100W,設定batch_size=100時,需要迭代1w次,遠小於SGD的100w次)
3.可實現並行化。
缺點:
1.batch_size的不當選擇可能會帶來一些問題。
batch_size的選擇帶來的影響:
(1)在合理地範圍內,增大batch_size的好處:
a. 記憶體利用率提高了,大矩陣乘法的並行化效率提高。
b. 跑完一次 epoch(全資料集)所需的迭代次數減少,對於相同資料量的處理速度進一步加快。
c. 在一定範圍內,一般來說 Batch_Size 越大,其確定的下降方向越準,引起訓練震盪越小。
(2)盲目增大batch_size的壞處:
a. 記憶體利用率提高了,但是記憶體容量可能撐不住了。
b. 跑完一次 epoch(全資料集)所需的迭代次數減少,要想達到相同的精度,其所花費的時間大大增加了,從而對引數的修正也就顯得更加緩慢。
c. Batch_Size 增大到一定程度,其確定的下降方向已經基本不再變化。
下圖為三種迭代策略下目標函式的收斂過程
2.動量法(Momentum)
動量法又稱衝量演算法,其核心思想可看成指數平均,每次求得梯度後都跟前面的梯度進行指數平滑,讓梯度更加平滑去防止梯度變化過大,公式如下:
dw是我們計算出來的原始梯度,v則是用指數加權平均計算出來的梯度,α為學習率。這相當於對原始梯度做了一個平滑,然後再用來做梯度下降,對於二元函式迭代程式碼如下:
def momentum_2d(x1, x2, v1, v2): v1 = gamma * v1 + (1-gamma)*0.2 * x1 v2 = gamma * v2 + (1-gamma)*4 * x2 return x1 - eta * v1, x2 - eta * v2, v1, v2
3.AdaGrad演算法
AdaGrad演算法會使用一個小批量隨機梯度gt按元素平方的累加變數st,然後更新的梯度為gt除以st+ε的開方,η為學習率,ϵ是為了維持數值穩定性而新增的常數,如10-6,具體公式如下:
由於st會一直累積增大(公式中分母變大),實際可以看成學習率η隨機訓練而減小,當學習率在迭代早期降得較快且當前解依然不佳時,AdaGrad演算法在迭代後期由於學習率過小,自變數的迭代軌跡較平滑,可能較難找到一個有用的解,對於二元函式迭代程式碼如下:
def adagrad_2d(x1, x2, s1, s2): g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6 # 前兩項為自變數梯度 s1 += g1 ** 2 s2 += g2 ** 2 x1 -= eta / math.sqrt(s1 + eps) * g1 x2 -= eta / math.sqrt(s2 + eps) * g2 return x1, x2, s1, s2
4.RMSProP演算法
RMSProP演算法可以看成AdaGrad演算法的改進,在AdaGrad的基礎上加上Momentum法,第一步不再是直接加和,而是引入指數平滑,對每一次的平方和進行平滑,RMSprop迭代更新公式如下:
β的典型值是0.999。公式中還有一個ϵ,這是一個很小的數,典型值是10-8。對於二元函式迭代程式碼如下:
def rmsprop_2d(x1, x2, s1, s2): g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6 s1 = gamma * s1 + (1 - gamma) * g1 ** 2 s2 = gamma * s2 + (1 - gamma) * g2 ** 2 x1 -= eta / math.sqrt(s1 + eps) * g1 x2 -= eta / math.sqrt(s2 + eps) * g2 return x1, x2, s1, s2
5.AdaDelta演算法
AdaDelta演算法同樣是在AdaGrad演算法進行改進,有意思的是,AdaDelta演算法沒有學習率這一超引數,
(1)梯度平方求和並加入指數平滑
(2)AdaDelta演算法還維護一個額外的狀態變數Δxt,其元素同樣在時間步0時被初始化為0。我們使用Δxt-1來計算自變數的變化量
(3)其中ϵ是為了維持數值穩定性而新增的常數,如10-5。接著更新自變數
(4)最後,我們使用Δxt來記錄自變數變化量g′t按元素平方的指數加權移動平均
可以看到,如不考慮ϵ的影響,AdaDelta演算法與RMSProp演算法的不同之處在於使用√Δxt−1來替代超引數η。
6.Adam演算法
Adam演算法則是RMSProP演算法和Momentum法的結合。先看迭代更新公式:
分母部分取的是RMSProP演算法,分子部分取的是Momentum法,典型值:β1=0.9,β2=0.999,ϵ=10−8◂,▸β1=0.9,β2=0.999,ϵ=10−8。Adam演算法相當於先把原始梯度做一個指數加權平均,再做一次歸一化處理,然後再更新梯度值。
引用及參考
http://zh.gluon.ai/chapter_optimization/optimization-intro.html
https://www.cnblogs.com/lliuye/p/9451903.html
https://www.cnblogs.com/jiaxblog/p/9695042.html