在很多機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的應(yīng)用中席纽,我們發(fā)現(xiàn)用的最多的優(yōu)化器是 Adam纽疟,為什么呢瞎嬉?
下面是 TensorFlow 中的優(yōu)化器:
詳情參見:https://www.tensorflow.org/api_guides/python/train
在 keras 中也有 SGD蜕琴,RMSprop挣轨,Adagrad串前,Adadelta瘫里,Adam 等,詳情:
我們可以發(fā)現(xiàn)除了常見的梯度下降荡碾,還有 Adadelta谨读,Adagrad,RMSProp 等幾種優(yōu)化器坛吁,都是什么呢漆腌,又該怎么選擇呢?
一阶冈、優(yōu)化器算法簡述
首先來看一下梯度下降最常見的三種變形 BGD闷尿,SGD,MBGD女坑,
這三種形式的區(qū)別就是取決于我們用多少數(shù)據(jù)來計(jì)算目標(biāo)函數(shù)的梯度填具,
這樣的話自然就涉及到一個(gè) trade-off,即參數(shù)更新的準(zhǔn)確率和運(yùn)行時(shí)間。
1. Batch gradient descent
梯度更新規(guī)則:
BGD 采用整個(gè)訓(xùn)練集的數(shù)據(jù)來計(jì)算 cost function 對(duì)參數(shù)的梯度:
缺點(diǎn):
由于這種方法是在一次更新中劳景,就對(duì)整個(gè)數(shù)據(jù)集計(jì)算梯度誉简,所以計(jì)算起來非常慢,遇到很大量的數(shù)據(jù)集也會(huì)非常棘手盟广,而且不能投入新數(shù)據(jù)實(shí)時(shí)更新模型
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
我們會(huì)事先定義一個(gè)迭代次數(shù) epoch闷串,首先計(jì)算梯度向量 params_grad,然后沿著梯度的方向更新參數(shù) params筋量,learning rate 決定了我們每一步邁多大烹吵。
Batch gradient descent 對(duì)于凸函數(shù)可以收斂到全局極小值,對(duì)于非凸函數(shù)可以收斂到局部極小值桨武。
2. Stochastic gradient descent
梯度更新規(guī)則:
和 BGD 的一次用所有數(shù)據(jù)計(jì)算梯度相比肋拔,SGD 每次更新時(shí)對(duì)每個(gè)樣本進(jìn)行梯度更新,
對(duì)于很大的數(shù)據(jù)集來說呀酸,可能會(huì)有相似的樣本凉蜂,這樣 BGD 在計(jì)算梯度時(shí)會(huì)出現(xiàn)冗余,
而 SGD 一次只進(jìn)行一次更新性誉,就沒有冗余窿吩,而且比較快,并且可以新增樣本错览。
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
看代碼纫雁,可以看到區(qū)別,就是整體數(shù)據(jù)集是個(gè)循環(huán)蝗砾,其中對(duì)每個(gè)樣本進(jìn)行一次參數(shù)更新先较。
缺點(diǎn):
但是 SGD 因?yàn)楦卤容^頻繁,會(huì)造成 cost function 有嚴(yán)重的震蕩悼粮。
BGD 可以收斂到局部極小值闲勺,當(dāng)然 SGD 的震蕩可能會(huì)跳到更好的局部極小值處。
當(dāng)我們稍微減小 learning rate扣猫,SGD 和 BGD 的收斂性是一樣的菜循。
3. Mini-batch gradient descent
梯度更新規(guī)則:
MBGD 每一次利用一小批樣本,即 n 個(gè)樣本進(jìn)行計(jì)算申尤,
這樣它可以降低參數(shù)更新時(shí)的方差癌幕,收斂更穩(wěn)定,
另一方面可以充分地利用深度學(xué)習(xí)庫中高度優(yōu)化的矩陣操作來進(jìn)行更有效的梯度計(jì)算昧穿。
和 SGD 的區(qū)別是每一次循環(huán)不是作用于每個(gè)樣本勺远,而是具有 n 個(gè)樣本的批次
for i in range(nb_epochs):
np.random.shuffle(data)
for batch in get_batches(data, batch_size=50):
params_grad = evaluate_gradient(loss_function, batch, params)
params = params - learning_rate * params_grad
超參數(shù)設(shè)定值:
n 一般取值在 50~256
缺點(diǎn):
不過 Mini-batch gradient descent 不能保證很好的收斂性:
learning rate 如果選擇的太小,收斂速度會(huì)很慢时鸵,如果太大胶逢,loss function 就會(huì)在極小值處不停地震蕩甚至偏離厅瞎。?
(有一種措施是先設(shè)定大一點(diǎn)的學(xué)習(xí)率,當(dāng)兩次迭代之間的變化低于某個(gè)閾值后初坠,就減小 learning rate和簸,不過這個(gè)閾值的設(shè)定需要提前寫好,這樣的話就不能夠適應(yīng)數(shù)據(jù)集的特點(diǎn))
此外碟刺,這種方法是對(duì)所有參數(shù)更新時(shí)應(yīng)用同樣的 learning rate锁保,如果我們的數(shù)據(jù)是稀疏的,我們更希望對(duì)出現(xiàn)頻率低的特征進(jìn)行大一點(diǎn)的更新半沽。
另外爽柒,對(duì)于非凸函數(shù),還要避免陷于局部極小值處抄囚,或者鞍點(diǎn)處霉赡,因?yàn)榘包c(diǎn)周圍的error 是一樣的橄务,所有維度的梯度都接近于0幔托,SGD 很容易被困在這里。?
鞍點(diǎn)就是:一個(gè)光滑函數(shù)的鞍點(diǎn)鄰域的曲線蜂挪,曲面重挑,或超曲面,都位于這點(diǎn)的切線的不同邊棠涮。
例如下圖這個(gè)二維圖形谬哀,像個(gè)馬鞍:在x-軸方向往上曲,在y-軸方向往下曲严肪,鞍點(diǎn)就是(0史煎,0)
為了應(yīng)對(duì)上述這三點(diǎn)挑戰(zhàn),于是就有了下面這些算法驳糯。
4. Momentum
SGD 在 ravines 的情況下容易被困住篇梭, ravines 就是曲面的一個(gè)方向比另一個(gè)方向更陡,這時(shí) SGD 會(huì)發(fā)生震蕩而遲遲不能接近極小值:
梯度更新規(guī)則:
Momentum 通過加入 γv_t?1 酝枢,可以加速 SGD恬偷, 并且抑制震蕩
當(dāng)我們將一個(gè)小球從山上滾下來時(shí),沒有阻力的話帘睦,它的動(dòng)量會(huì)越來越大袍患,但是如果遇到了阻力,速度就會(huì)變小竣付。
加入的這一項(xiàng)诡延,可以使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢古胆,這樣就可以加快收斂并減小震蕩肆良。
超參數(shù)設(shè)定值:
一般 γ 取值 0.9 左右。
缺點(diǎn):
這種情況相當(dāng)于小球從山上滾下來時(shí)是在盲目地沿著坡滾,如果它能具備一些先知妖滔,例如快要上坡時(shí)隧哮,就知道需要減速了的話,適應(yīng)性會(huì)更好座舍。
5. Nesterov accelerated gradient
梯度更新規(guī)則:
用 θ?γv_t?1 來近似當(dāng)做參數(shù)下一步會(huì)變成的值沮翔,則在計(jì)算梯度時(shí),不是在當(dāng)前位置曲秉,而是未來的位置上
超參數(shù)設(shè)定值:
γ 仍然取值 0.9 左右采蚀。
效果比較:
藍(lán)色是 Momentum 的過程,會(huì)先計(jì)算當(dāng)前的梯度承二,然后在更新后的累積梯度后會(huì)有一個(gè)大的跳躍榆鼠。
而 NAG 會(huì)先在前一步的累積梯度上(brown vector)有一個(gè)大的跳躍,然后衡量一下梯度做一下修正(red vector)亥鸠,這種預(yù)期的更新可以避免我們走的太快妆够。
NAG 可以使 RNN 在很多任務(wù)上有更好的表現(xiàn)。
目前為止负蚊,我們可以做到神妹,在更新梯度時(shí)順應(yīng) loss function 的梯度來調(diào)整速度,并且對(duì) SGD 進(jìn)行加速家妆。
我們還希望可以根據(jù)參數(shù)的重要性而對(duì)不同的參數(shù)進(jìn)行不同程度的更新鸵荠。
6. Adagrad
這個(gè)算法就可以對(duì)低頻的參數(shù)做較大的更新,對(duì)高頻的做較小的更新伤极,也因此蛹找,對(duì)于稀疏的數(shù)據(jù)它的表現(xiàn)很好,很好地提高了 SGD 的魯棒性哨坪,例如識(shí)別 Youtube 視頻里面的貓庸疾,訓(xùn)練 GloVe word embeddings,因?yàn)樗鼈兌际切枰诘皖l的特征上有更大的更新齿税。
梯度更新規(guī)則:
其中 g 為:t 時(shí)刻參數(shù) θ_i 的梯度
如果是普通的 SGD彼硫, 那么 θ_i 在每一時(shí)刻的梯度更新公式為:
但這里的 learning rate η 也隨 t 和 i 而變:
其中 G_t 是個(gè)對(duì)角矩陣, (i,i) 元素就是 t 時(shí)刻參數(shù) θ_i 的梯度平方和凌箕。
Adagrad 的優(yōu)點(diǎn)是減少了學(xué)習(xí)率的手動(dòng)調(diào)節(jié)
超參數(shù)設(shè)定值:
一般 η 就取 0.01拧篮。
缺點(diǎn):
它的缺點(diǎn)是分母會(huì)不斷積累,這樣學(xué)習(xí)率就會(huì)收縮并最終會(huì)變得非常小牵舱。
7. Adadelta
這個(gè)算法是對(duì) Adagrad 的改進(jìn)串绩,和 Adagrad 相比,就是分母的 G 換成了過去的梯度平方的衰減平均值:
這個(gè)分母相當(dāng)于梯度的均方根 root mean squared (RMS) 芜壁,所以可以用 RMS 簡寫:
其中 E 的計(jì)算公式如下礁凡,t 時(shí)刻的依賴于前一時(shí)刻的平均和當(dāng)前的梯度:
梯度更新規(guī)則:
此外高氮,還將學(xué)習(xí)率 η 換成了 RMS[Δθ],這樣的話顷牌,我們甚至都不需要提前設(shè)定學(xué)習(xí)率了:
超參數(shù)設(shè)定值:
γ 一般設(shè)定為 0.9剪芍。
8. RMSprop
RMSprop 是 Geoff Hinton 提出的一種自適應(yīng)學(xué)習(xí)率方法。
RMSprop 和 Adadelta 都是為了解決 Adagrad 學(xué)習(xí)率急劇下降問題的窟蓝,
梯度更新規(guī)則:
RMSprop 與 Adadelta 的第一種形式相同:
超參數(shù)設(shè)定值:
Hinton 建議設(shè)定 γ 為 0.9, 學(xué)習(xí)率 η 為 0.001罪裹。
9. Adam
這個(gè)算法是另一種計(jì)算每個(gè)參數(shù)的自適應(yīng)學(xué)習(xí)率的方法。
除了像 Adadelta 和 RMSprop 一樣存儲(chǔ)了過去梯度的平方 vt 的指數(shù)衰減平均值 运挫,也像 momentum 一樣保持了過去梯度 mt 的指數(shù)衰減平均值:
如果 mt 和 vt 被初始化為 0 向量状共,那它們就會(huì)向 0 偏置,所以做了偏差校正谁帕,
通過計(jì)算偏差校正后的 mt 和 vt 來抵消這些偏差:
梯度更新規(guī)則:
超參數(shù)設(shè)定值:
建議 β1 = 0.9峡继,β2 = 0.999,? = 10e?8
實(shí)踐表明匈挖,Adam 比其他適應(yīng)性學(xué)習(xí)方法效果要好碾牌。
10.效果比較?
下面看一下幾種算法在鞍點(diǎn)和等高線上的表現(xiàn):
上面兩種情況都可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向并前進(jìn)关划,收斂速度也相當(dāng)快小染,而其它方法要么很慢翘瓮,要么走了很多彎路才找到贮折。
由圖可知自適應(yīng)學(xué)習(xí)率方法即 Adagrad, Adadelta, RMSprop, Adam 在這種情景下會(huì)更合適而且收斂性更好。
如何選擇
1资盅、如果數(shù)據(jù)是稀疏的调榄,就用自適用方法,即 Adagrad, Adadelta, RMSprop, Adam呵扛。
2每庆、 RMSprop, Adadelta, Adam 在很多情況下的效果是相似的。
3今穿、Adam 就是在 RMSprop 的基礎(chǔ)上加了 bias-correction 和 momentum缤灵,
4、 隨著梯度變的稀疏蓝晒,Adam 比 RMSprop 效果會(huì)好腮出。
5、整體來講芝薇,Adam 是最好的選擇胚嘲。
6、 很多論文里都會(huì)用 SGD洛二,沒有 momentum 等馋劈。SGD 雖然能達(dá)到極小值攻锰,但是比其它算法用的時(shí)間長,而且可能會(huì)被困在鞍點(diǎn)妓雾。
7娶吞、如果需要更快的收斂,或者是訓(xùn)練更深更復(fù)雜的神經(jīng)網(wǎng)絡(luò)械姻,需要用一種自適應(yīng)的算法寝志。
![關(guān)注我的技術(shù)公眾號(hào)《漫談人工智能》,每天推送優(yōu)質(zhì)文章](https://upload-images.jianshu.io/upload_images/10019820-3f339ee96f43e84f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)