今日大綱
SGD為隨機梯度下降法,與梯度下降法相同。隨機抽取一個樣本並更新權重,其優點是更新速度快,但是收斂的速度較慢,因為抽取的過程中會抽到不同的樣本。
如果是以全部的樣本一起訓練的話稱為批量梯度下降法 (Batch gradient descent, BGD)。結合前兩種做法,一次以一小批樣本訓練時,則稱為小批量梯度下降法 (Mini-batch gradient descent)。
SGD更新權重之公式如下,gradient即為函數的偏微分:
w = w - learning_rate * gradient
f(x) = x^2為例,f’(x) = 2x,第一次更新權重值時會減少0.1*(2*1),更新後的權重為0.8。
import tensorflow as tf
#SGD
opt = tf.keras.optimizers.SGD(learning_rate=0.1)
var = tf.Variable(1.0)
loss = lambda: (var ** 2)/2.0 # d(loss)/d(var1) = var1
step_count = opt.minimize(loss, [var]).numpy()
# Step is `- learning_rate * grad`
print(var.numpy())
輸出為0.8
如果SGD加入動能,納入物理的概念,在同方向的時候學習速度會變快,權重更新也會越來越快,如果方向改變時,學習速度會變慢。動能 (momentum)的值介於0到1之間設置。當動能為0時,代表學習率為固定值,等同於SGD優化器。權重更新之公式如下:
velocity = momentum * velocity - learning_rate * g
w = w + velocity
加入動能後,每次更新的差距不會固定在0.2。
##momentum
opt = tf.keras.optimizers.SGD(learning_rate=0.1, momentum=0.9)
var = tf.Variable(1.0)
val0 = var.value()
loss = lambda: (var ** 2) # d(loss)/d(var1) = var1
# First step is `- learning_rate * grad`
step_count = opt.minimize(loss, [var]).numpy()
val1 = var.value()
print(val1.numpy())
# On later steps, step-size increases because of momentum
step_count = opt.minimize(loss, [var]).numpy()
val2 = var.value()
print(val2.numpy())
輸出val1 = 0.8, val2 = 0.46
Adagrad會根據更新次數決定學習率的大小,當更新次數越多,學習率會越小。
opt = tf.keras.optimizers.Adagrad(learning_rate=0.1)
var1 = tf.Variable(1.0)
loss = lambda: (var1 ** 2) # d(loss)/d(var1) == var1
step_count = opt.minimize(loss, [var1]).numpy()
# The first step is `-learning_rate*sign(grad)`
var1.numpy()
輸出為0.90122706
Adam為較常使用的優化器,其結合SGD與Adagrad。根據Kingma et al. (2014)提出此優化器能夠處理較大且參數較多的資料集,且計算效率高,所耗費的記憶體少。
opt = tf.keras.optimizers.Adam(learning_rate=0.1)
var1 = tf.Variable(1.0)
loss = lambda: (var1 ** 2) # d(loss)/d(var1) == var1
step_count = opt.minimize(loss, [var1]).numpy()
# The first step is `-learning_rate*sign(grad)`
var1.numpy()
輸出為0.9
RMprop由Geoffrey Hinton所提出,其目的為解決遞迴神經網路 (Recurrent neural network) 梯度消失與梯度爆炸之問題,因此也較常與用於RNN。學習率也會動態地調整,不同的是梯度需除以開根號的移動平均平方梯度。
## RMSprop
opt = tf.keras.optimizers.RMSprop(learning_rate=0.1)
var1 = tf.Variable(1.0)
loss = lambda: (var1 ** 2)
step_count = opt.minimize(loss, [var1]).numpy()
var1.numpy()
輸出結果為0.6837723
感謝您的瀏覽,程式碼已上傳Github。