在很多機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的應(yīng)用中,我們發(fā)現(xiàn)用的最多的優(yōu)化器是 Adam,為什么呢?
下面是 TensorFlow 中的優(yōu)化器:
在 keras 中也有 SGD,RMSprop,Adagrad,Adadelta,Adam 等。
?
我們可以發(fā)現(xiàn)除了常見(jiàn)的梯度下降,還有 Adadelta,Adagrad,RMSProp 等幾種優(yōu)化器,都是什么呢,又該怎么選擇呢?
在 Sebastian Ruder 的這篇論文中給出了常用優(yōu)化器的比較,本文將梳理:
每個(gè)算法的梯度更新規(guī)則和缺點(diǎn)
為了應(yīng)對(duì)這個(gè)不足而提出的下一個(gè)算法
超參數(shù)的一般設(shè)定值
幾種算法的效果比較
選擇哪種算法
優(yōu)化器算法簡(jiǎn)述
首先來(lái)看一下梯度下降最常見(jiàn)的三種變形 BGD,SGD,MBGD,
這三種形式的區(qū)別就是取決于我們用多少數(shù)據(jù)來(lái)計(jì)算目標(biāo)函數(shù)的梯度,
這樣的話(huà)自然就涉及到一個(gè) trade-off,即參數(shù)更新的準(zhǔn)確率和運(yùn)行時(shí)間。
1. Batch gradient descent
梯度更新規(guī)則:
BGD 采用整個(gè)訓(xùn)練集的數(shù)據(jù)來(lái)計(jì)算 cost function 對(duì)參數(shù)的梯度:
缺點(diǎn):
由于這種方法是在一次更新中,就對(duì)整個(gè)數(shù)據(jù)集計(jì)算梯度,所以計(jì)算起來(lái)非常慢,遇到很大量的數(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ù)集來(lái)說(shuō),可能會(huì)有相似的樣本,這樣 BGD 在計(jì)算梯度時(shí)會(huì)出現(xiàn)冗余, 而 SGD 一次只進(jìn)行一次更新,就沒(méi)有冗余,而且比較快,并且可以新增樣本。
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í)庫(kù)中高度優(yōu)化的矩陣操作來(lái)進(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):
不過(guò) Mini-batch gradient descent 不能保證很好的收斂性,
learning rate 如果選擇的太小,收斂速度會(huì)很慢,如果太大,loss function 就會(huì)在極小值處不停地震蕩甚至偏離。
有一種措施是先設(shè)定大一點(diǎn)的學(xué)習(xí)率,當(dāng)兩次迭代之間的變化低于某個(gè)閾值后,就減小 learning rate,不過(guò)這個(gè)閾值的設(shè)定需要提前寫(xiě)好,這樣的話(huà)就不能夠適應(yīng)數(shù)據(jù)集的特點(diǎn)。
此外,這種方法是對(duì)所有參數(shù)更新時(shí)應(yīng)用同樣的 learning rate,如果我們的數(shù)據(jù)是稀疏的,我們更希望對(duì)出現(xiàn)頻率低的特征進(jìn)行大一點(diǎn)的更新。
評(píng)論
查看更多