AdaDelta算法
Adadelta
Adadelta是AdaGrad的另一种变体( AdaGrad算法),
主要区别在于前者减少了学习率适应坐标的数量。
此外,广义上Adadelta被称为没有学习率,因为它使用变化量本身作为未来变化的校准。
Adadelta算法是在 中提出的。
Adadelta算法
简而言之,Adadelta使用两个状态变量,$\mathbf{s}_t$用于存储梯度二阶导数的泄露平均值,$\Delta\mathbf{x}_t$用于存储模型本身中参数变化二阶导数的泄露平均值。请注意,为了与其他出版物和实现的兼容性,我们使用作者的原始符号和命名(没有其它真正理由让大家使用不同的希腊变量来表示在动量法、AdaGrad、RMSProp和Adadelta中用于相同用途的参数)。
以下是Adadelta的技术细节。鉴于参数du jour是$\rho$,我们获得了与 RMSProp算法类似的以下泄漏更新:
$$\begin{aligned}
\mathbf{s}t & = \rho \mathbf{s}{t-1} + (1 - \rho) \mathbf{g}_t^2.
\end{aligned}$$
与 RMSProp算法的区别在于,我们使用重新缩放的梯度$\mathbf{g}_t’$执行更新,即
$$\begin{aligned}
\mathbf{x}t & = \mathbf{x}{t-1} - \mathbf{g}_t’. \
\end{aligned}$$
那么,调整后的梯度$\mathbf{g}_t’$是什么?我们可以按如下方式计算它:
$$\begin{aligned}
\mathbf{g}t’ & = \frac{\sqrt{\Delta\mathbf{x}{t-1} + \epsilon}}{\sqrt{\mathbf{s}_t + \epsilon}} \odot \mathbf{g}_t, \
\end{aligned}$$
其中$\Delta \mathbf{x}_{t-1}$是重新缩放梯度的平方$\mathbf{g}t’$的泄漏平均值。我们将$\Delta \mathbf{x}{0}$初始化为$0$,然后在每个步骤中使用$\mathbf{g}_t’$更新它,即
$$\begin{aligned}
\Delta \mathbf{x}t & = \rho \Delta\mathbf{x}{t-1} + (1 - \rho) {\mathbf{g}_t’}^2,
\end{aligned}$$
和$\epsilon$(例如$10^{-5}$这样的小值)是为了保持数字稳定性而加入的。
代码实现
Adadelta需要为每个变量维护两个状态变量,即$\mathbf{s}_t$和$\Delta\mathbf{x}_t$。这将产生以下实现。
1 | %matplotlib inline |
对于每次参数更新,选择$\rho = 0.9$相当于10个半衰期。由此我们得到:
1 | data_iter, feature_dim = d2l.get_data_ch11(batch_size=10) |
为了简洁实现,我们只需使用高级API中的Adadelta算法。
1 | d2l.train_concise_ch11('adadelta', {'rho': 0.9}, data_iter) |
1 | trainer = torch.optim.Adadelta |
小结
- Adadelta没有学习率参数。相反,它使用参数本身的变化率来调整学习率。
- Adadelta需要两个状态变量来存储梯度的二阶导数和参数的变化。
- Adadelta使用泄漏的平均值来保持对适当统计数据的运行估计。