天天看點

動手學PyTorch | (44) Adam算法

Adam算法在RMSProp算法基礎上對⼩批量随機梯度也做了指數權重移動平均。下面我們來介紹這個算法。是以Adam算法可以看做是RMSProp算法與動量法的結合。

目錄

1. 算法

2. 從0開始實作

3. 簡潔實作

4. 小結

1. 算法

Adam中使用了動量變量

動手學PyTorch | (44) Adam算法

和RMSprop算法中小批量随機梯度按元素平方的指數權重移動平均變量

動手學PyTorch | (44) Adam算法

,并在時間步0将它們中每個元素初始化為0。給定超參數

動手學PyTorch | (44) Adam算法

(算法作者建議設為0.9),時間步t的動量變量

動手學PyTorch | (44) Adam算法

即小批量随機梯度

動手學PyTorch | (44) Adam算法

的指數權重移動平均:

動手學PyTorch | (44) Adam算法

和RMSProp算法中⼀樣,給定超參數

動手學PyTorch | (44) Adam算法

(算法作者建議設為0.999), 将⼩批量随機梯度按元素平方後的項

動手學PyTorch | (44) Adam算法

做指數權重移動平均得到

動手學PyTorch | (44) Adam算法

:

動手學PyTorch | (44) Adam算法

由于我們将

動手學PyTorch | (44) Adam算法

中的元素都初始化為0, 在時間步t我們得到:

動手學PyTorch | (44) Adam算法

将過去各時間步小批量随機梯度的權值相加,得到:

動手學PyTorch | (44) Adam算法

需要注意的是,當t較小時,過去各時間步⼩批量随機梯度權值之和會較小。例如,當

動手學PyTorch | (44) Adam算法

時,

動手學PyTorch | (44) Adam算法

,為了消除這樣的影響,對于任意時間步t,我們可以将

動手學PyTorch | (44) Adam算法

除以

動手學PyTorch | (44) Adam算法

(做偏差修正,剛開始不準)。從⽽使過去各時間步小批量随機梯度權值之和為1。這也叫作偏差修正。在Adam算法中,我們對變量

動手學PyTorch | (44) Adam算法

均作偏差修正:

動手學PyTorch | (44) Adam算法

接下來,Adam算法使⽤以上偏差修正後的變量

動手學PyTorch | (44) Adam算法

将模型參數中每個元素的學習率通過按元素運算􏰀重新調整:

動手學PyTorch | (44) Adam算法

其中

動手學PyTorch | (44) Adam算法

是學習率,

動手學PyTorch | (44) Adam算法

是為了維持數值穩定性⽽添加的常數,如

動手學PyTorch | (44) Adam算法

.和AdaGrad算法、RMSProp算法以及AdaDelta算法一樣,⽬标函數⾃變量(參數)中每個元素都分别擁有⾃己的學習率。最後,使⽤

動手學PyTorch | (44) Adam算法

疊代⾃變量(參數):

動手學PyTorch | (44) Adam算法

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)
           
動手學PyTorch | (44) Adam算法

3. 簡潔實作

d2l.train_pytorch_ch7(torch.optim.Adam, {'lr': 0.01}, features, labels)
           
動手學PyTorch | (44) Adam算法

4. 小結

1)Adam算法在RMSProp算法的基礎上對小批量随機梯度也做了指數權重移動平均。

2)Adam算法使⽤了偏差修正。

繼續閱讀