Adam算法在RMSProp算法基礎上對⼩批量随機梯度也做了指數權重移動平均。下面我們來介紹這個算法。是以Adam算法可以看做是RMSProp算法與動量法的結合。
目錄
1. 算法
2. 從0開始實作
3. 簡潔實作
4. 小結
1. 算法
Adam中使用了動量變量
和RMSprop算法中小批量随機梯度按元素平方的指數權重移動平均變量
,并在時間步0将它們中每個元素初始化為0。給定超參數
(算法作者建議設為0.9),時間步t的動量變量
即小批量随機梯度
的指數權重移動平均:
和RMSProp算法中⼀樣,給定超參數
(算法作者建議設為0.999), 将⼩批量随機梯度按元素平方後的項
做指數權重移動平均得到
:
由于我們将
中的元素都初始化為0, 在時間步t我們得到:
将過去各時間步小批量随機梯度的權值相加,得到:
需要注意的是,當t較小時,過去各時間步⼩批量随機梯度權值之和會較小。例如,當
時,
,為了消除這樣的影響,對于任意時間步t,我們可以将
除以
(做偏差修正,剛開始不準)。從⽽使過去各時間步小批量随機梯度權值之和為1。這也叫作偏差修正。在Adam算法中,我們對變量
均作偏差修正:
接下來,Adam算法使⽤以上偏差修正後的變量
将模型參數中每個元素的學習率通過按元素運算重新調整:
其中
是學習率,
是為了維持數值穩定性⽽添加的常數,如
.和AdaGrad算法、RMSProp算法以及AdaDelta算法一樣,⽬标函數⾃變量(參數)中每個元素都分别擁有⾃己的學習率。最後,使⽤
疊代⾃變量(參數):
2. 從0開始實作
我們按照Adam算法中的公式實作該算法。其中時間步t通過hyperparams參數傳⼊ adam 函數。
%matplotlib inline
import torch
import sys
sys.path.append(".")
import d2lzh_pytorch as d2l
features, labels = d2l.get_data_ch7()
def init_adam_states():
v_w, v_b = torch.zeros((features.shape[1], 1), dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
s_w, s_b = torch.zeros((features.shape[1], 1), dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
return ((v_w, s_w), (v_b, s_b))
def adam(params, states, hyperparams):
beta1, beta2, eps = 0.9, 0.999, 1e-6
for p, (v, s) in zip(params, states):
v[:] = beta1 * v + (1 - beta1) * p.grad.data
s[:] = beta2 * s + (1 - beta2) * p.grad.data**2
v_bias_corr = v / (1 - beta1 ** hyperparams['t'])
s_bias_corr = s / (1 - beta2 ** hyperparams['t'])
p.data -= hyperparams['lr'] * v_bias_corr / (torch.sqrt(s_bias_corr) + eps)
hyperparams['t'] += 1
使⽤學習率為0.01的Adam算法來訓練模型。
d2l.train_ch7(adam, init_adam_states(), {'lr': 0.01, 't': 1}, features, labels)
3. 簡潔實作
d2l.train_pytorch_ch7(torch.optim.Adam, {'lr': 0.01}, features, labels)
4. 小結
1)Adam算法在RMSProp算法的基礎上對小批量随機梯度也做了指數權重移動平均。
2)Adam算法使⽤了偏差修正。