提交 845ae538 编写于 作者: A Aston Zhang

adadelta

上级 d8e4c290
# Adadelta——使用`Gluon`
`Gluon`里,使用Adadelta很容易。我们无需重新实现它。
`Gluon`里,Adadelta,我们无需重新实现该算法。
首先,导入实验所需的包。
```{.python .input}
%config InlineBackend.figure_format = 'retina'
......@@ -15,6 +17,8 @@ sys.path.append('..')
import utils
```
下面生成实验数据集并定义线性回归模型。
```{.python .input n=1}
# 生成数据集。
num_inputs = 2
......@@ -32,7 +36,7 @@ net.add(gluon.nn.Dense(1))
我们需要在`gluon.Trainer`中指定优化算法名称`adadelta`并设置rho参数。
使用Adadelta,最终学到的参数值与真实值较接近
我们可以在Trainer中定义优化算法名称`adadelta`并定义$\rho$超参数`rho`。以下实验重现了[“Adadelta——从零开始”](adadelta-scratch.md)一节中实验结果
```{.python .input n=3}
net.collect_params().initialize(mx.init.Normal(sigma=1), force_reinit=True)
......@@ -47,7 +51,7 @@ utils.optimize(batch_size=10, trainer=trainer, num_epochs=3, decay_epoch=None,
## 练习
* 如果把试验中的参数rho改小会怎样,例如0.9?观察实验结果。
* 如果把试验中的参数$\rho$改小会怎样,例如0.9?观察并分析实验结果。
## 讨论
......
# Adadelta——从零开始
我们在[Adagrad](adagrad-scratch.md)里提到,由于学习率分母上的变量$\boldsymbol{s}$一直在累加按元素平方的梯度,每个元素的学习率在迭代过程中一直在降低或不变。所以在有些问题下,当学习率在迭代早期降得较快时且当前解依然不理想时,Adagrad在迭代后期可能较难找到一个有用的解。我们在[RMSProp](rmsprop-scratch.md)介绍了应对这一问题的一种方法:对梯度按元素平方使用指数加权移动平均而不是累加。
事实上,Adadelta也是一种应对这个问题的方法。有意思的是,它没有学习率参数。
我们在[“RMSProp——从零开始”](rmsprop-gluon.md)一节中描述了,RMSProp针对Adagrad在迭代后期可能较难找到有用解的问题,对小批量随机梯度按元素平方项做指数加权移动平均而不是累加。另一种应对该问题的优化算法叫做Adadelta [1]。有意思的是,它没有学习率超参数。
## Adadelta算法
Adadelta算法也像RMSProp一样,使用了一个梯度按元素平方的指数加权移动平均变量$\boldsymbol{s}$,并将其中每个元素初始化为0。在每次迭代中,首先计算[小批量梯度](gd-sgd-scratch.md) $\boldsymbol{g}$,然后对该梯度按元素平方后做指数加权移动平均并计算$\boldsymbol{s}$:
Adadelta算法也像RMSProp一样,使用了小批量随机梯度按元素平方的指数加权移动平均变量$\boldsymbol{s}$,并将其中每个元素初始化为0。
给定超参数$\rho$且$0 \leq \rho < 1$,
在每次迭代中,RMSProp首先计算小批量随机梯度$\boldsymbol{g}$,然后对该梯度按元素平方项$\boldsymbol{g} \odot \boldsymbol{g}$做指数加权移动平均,记为$\boldsymbol{s}$:
$$\boldsymbol{s} := \rho \boldsymbol{s} + (1 - \rho) \boldsymbol{g} \odot \boldsymbol{g} $$
$$\boldsymbol{s} \leftarrow \rho \boldsymbol{s} + (1 - \rho) \boldsymbol{g} \odot \boldsymbol{g}. $$
然后我们计算当前需要更新的参数的变化量
然后,计算当前需要迭代的目标函数自变量的变化量$\boldsymbol{g}^\prime$
$$ \boldsymbol{g}^\prime = \frac{\sqrt{\Delta\boldsymbol{x} + \epsilon}}{\sqrt{\boldsymbol{s} + \epsilon}} \odot \boldsymbol{g} $$
$$ \boldsymbol{g}^\prime \leftarrow \frac{\sqrt{\Delta\boldsymbol{x} + \epsilon}}{\sqrt{\boldsymbol{s} + \epsilon}} \odot \boldsymbol{g}, $$
其中$\epsilon$是为了维持数值稳定性而添加的常数,例如$10^{-5}$。和Adagrad一样,模型参数中每个元素都分别拥有自己的学习率。其中$\Delta\boldsymbol{x}$初始化为零张量,并做如下$\boldsymbol{g}^\prime$按元素平方的指数加权移动平均:
其中$\epsilon$是为了维持数值稳定性而添加的常数,例如$10^{-5}$。和Adagrad与RMSProp一样,目标函数自变量中每个元素都分别拥有自己的学习率。上式中$\Delta\boldsymbol{x}$初始化为零张量,并记录$\boldsymbol{g}^\prime$按元素平方的指数加权移动平均:
$$\Delta\boldsymbol{x} := \rho \Delta\boldsymbol{x} + (1 - \rho) \boldsymbol{g}^\prime \odot \boldsymbol{g}^\prime $$
$$\Delta\boldsymbol{x} \leftarrow \rho \Delta\boldsymbol{x} + (1 - \rho) \boldsymbol{g}^\prime \odot \boldsymbol{g}^\prime. $$
同样地,最后的参数迭代步骤与小批量随机梯度下降类似。只是这里梯度前的学习率已经被调整过了
同样地,最后的自变量迭代步骤与小批量随机梯度下降类似
$$\boldsymbol{x} := \boldsymbol{x} - \boldsymbol{g}^\prime $$
$$\boldsymbol{x} \leftarrow \boldsymbol{x} - \boldsymbol{g}^\prime. $$
## Adadelta的实现
......@@ -46,7 +43,7 @@ def adadelta(params, sqrs, deltas, rho, batch_size):
## 实验
实验中,我们以线性回归为例。其中真实参数`w`为[2, -3.4],`b`为4.2。我们把算法中基于指数加权移动平均的变量初始化为和参数形状相同的零张量
首先,导入实验所需的包
```{.python .input}
%config InlineBackend.figure_format = 'retina'
......@@ -62,6 +59,10 @@ sys.path.append('..')
import utils
```
实验中,我们依然以线性回归为例。设数据集的样本数为1000,我们使用权重`w`为[2, -3.4],偏差`b`为4.2的线性回归模型来生成数据集。该模型的平方损失函数即所需优化的目标函数,模型参数即目标函数自变量。
我们把算法中基于指数加权移动平均的变量初始化为和模型参数形状相同的零张量。
```{.python .input n=1}
# 生成数据集。
num_inputs = 2
......@@ -87,7 +88,7 @@ def init_params():
return params, sqrs, deltas
```
接下来定义训练函数。当epoch大于2时(epoch从1开始计数),学习率以自乘0.1的方式自我衰减。训练函数的period参数说明,每次采样过该数目的数据点后,记录当前目标函数值用于作图。例如,当period和batch_size都为10时,每次迭代后均会记录目标函数值
优化函数`optimize`[“Adagrad——从零开始”](adagrad-scratch.md)一节中的类似
```{.python .input n=2}
net = utils.linreg
......@@ -114,7 +115,7 @@ def optimize(batch_size, rho, num_epochs, log_interval):
utils.semilogy(x_vals, y_vals, 'epoch', 'loss')
```
使用Adadelta,最终学到的参数值与真实值较接近。
最终,优化所得的模型参数值与它们的真实值较接近。
```{.python .input n=3}
optimize(batch_size=10, rho=0.9999, num_epochs=3, log_interval=10)
......@@ -127,7 +128,7 @@ optimize(batch_size=10, rho=0.9999, num_epochs=3, log_interval=10)
## 练习
* Adadelta为什么不需要设置学习率参数?它被什么代替了?
* Adadelta为什么不需要设置学习率参数?它被什么代替了?
## 讨论
......@@ -135,3 +136,7 @@ optimize(batch_size=10, rho=0.9999, num_epochs=3, log_interval=10)
欢迎扫码直达[本节内容讨论区](https://discuss.gluon.ai/t/topic/2277)
![](../img/qr_adadelta-scratch.svg)
## 参考文献
[1] Zeiler, M. D. (2012). ADADELTA: an Adaptive Learning Rate Method. arXiv preprint arXiv:1212.5701.
......@@ -35,7 +35,7 @@ net = gluon.nn.Sequential()
net.add(gluon.nn.Dense(1))
```
我们可以在Trainer中定义优化算法名称`adagrad`。以下几组实验分别重现了[“Adagrad——从零开始”](adagrad-scratch.md)一节中实验结果。
我们可以在Trainer中定义优化算法名称`adagrad`。以下实验分别重现了[“Adagrad——从零开始”](adagrad-scratch.md)一节中实验结果。
```{.python .input n=3}
net.collect_params().initialize(mx.init.Normal(sigma=1), force_reinit=True)
......
......@@ -8,37 +8,37 @@ Adam是一个组合了[动量法](momentum-scratch.md)和[RMSProp](rmsprop-scrat
Adam算法会使用一个动量变量$\boldsymbol{v}$和一个RMSProp中梯度按元素平方的指数加权移动平均变量$\boldsymbol{s}$,并将它们中每个元素初始化为0。在每次迭代中,首先计算[小批量梯度](gd-sgd-scratch.md) $\boldsymbol{g}$,并递增迭代次数
$$t := t + 1$$
$$t \leftarrow t + 1.$$
然后对梯度做指数加权移动平均并计算动量变量$\boldsymbol{v}$:
$$\boldsymbol{v} := \beta_1 \boldsymbol{v} + (1 - \beta_1) \boldsymbol{g} $$
$$\boldsymbol{v} \leftarrow \beta_1 \boldsymbol{v} + (1 - \beta_1) \boldsymbol{g}. $$
该梯度按元素平方后做指数加权移动平均并计算$\boldsymbol{s}$:
$$\boldsymbol{s} := \beta_2 \boldsymbol{s} + (1 - \beta_2) \boldsymbol{g} \odot \boldsymbol{g} $$
$$\boldsymbol{s} \leftarrow \beta_2 \boldsymbol{s} + (1 - \beta_2) \boldsymbol{g} \odot \boldsymbol{g}. $$
在Adam算法里,为了减轻$\boldsymbol{v}$和$\boldsymbol{s}$被初始化为0在迭代初期对计算指数加权移动平均的影响,我们做下面的偏差修正:
$$\hat{\boldsymbol{v}} := \frac{\boldsymbol{v}}{1 - \beta_1^t} $$
$$\hat{\boldsymbol{v}} \leftarrow \frac{\boldsymbol{v}}{1 - \beta_1^t} $$
$$\hat{\boldsymbol{s}} := \frac{\boldsymbol{s}}{1 - \beta_2^t} $$
$$\hat{\boldsymbol{s}} \leftarrow \frac{\boldsymbol{s}}{1 - \beta_2^t}. $$
可以看到,当$0 \leq \beta_1, \beta_2 < 1$时(算法作者建议分别设为0.9和0.999),当迭代后期$t$较大时,偏差修正几乎就不再有影响。我们使用以上偏差修正后的动量变量和RMSProp中梯度按元素平方的指数加权移动平均变量,将模型参数中每个元素的学习率通过按元素操作重新调整一下:
$$\boldsymbol{g}^\prime := \frac{\eta \hat{\boldsymbol{v}}}{\sqrt{\hat{\boldsymbol{s}} + \epsilon}} $$
$$\boldsymbol{g}^\prime \leftarrow \frac{\eta \hat{\boldsymbol{v}}}{\sqrt{\hat{\boldsymbol{s}} + \epsilon}} $$
其中$\eta$是初始学习率,$\epsilon$是为了维持数值稳定性而添加的常数,例如$10^{-8}$。和Adagrad一样,模型参数中每个元素都分别拥有自己的学习率。
同样地,最后的参数迭代步骤与小批量随机梯度下降类似。只是这里梯度前的学习率已经被调整过了:
$$\boldsymbol{x} := \boldsymbol{x} - \boldsymbol{g}^\prime $$
$$\boldsymbol{x} \leftarrow \boldsymbol{x} - \boldsymbol{g}^\prime $$
## Adam的实现
......
......@@ -29,7 +29,7 @@
### 指数加权移动平均
为了更清晰地理解动量法,让我们先解释指数加权移动平均(exponentially weighted moving average)。给定超参数$\gamma$且$0 \leq \gamma \leq 1$,当前时刻$t$的变量$y^{(t)}$是上一时刻$t-1$的变量$y^{(t-1)}$和当前时刻另一变量$x^{(t)}$的线性组合:
为了更清晰地理解动量法,让我们先解释指数加权移动平均(exponentially weighted moving average)。给定超参数$\gamma$且$0 \leq \gamma < 1$,当前时刻$t$的变量$y^{(t)}$是上一时刻$t-1$的变量$y^{(t-1)}$和当前时刻另一变量$x^{(t)}$的线性组合:
$$y^{(t)} = \gamma y^{(t-1)} + (1-\gamma) x^{(t)}.$$
......
......@@ -35,7 +35,7 @@ net = gluon.nn.Sequential()
net.add(gluon.nn.Dense(1))
```
例如,以使用动量法的小批量随机梯度下降为例,我们可以在`Trainer`中定义动量超参数`momentum`。以下几组实验分别重现了[“RMSProp——从零开始”](rmsprop-scratch.md)一节中实验结果。
我们可以在Trainer中定义优化算法名称`rmsprop`并定义$\gamma$超参数`gamma1`。以下几组实验分别重现了[“RMSProp——从零开始”](rmsprop-scratch.md)一节中实验结果。
```{.python .input n=3}
net.collect_params().initialize(mx.init.Normal(sigma=1), force_reinit=True)
......@@ -59,7 +59,7 @@ utils.optimize(batch_size=10, trainer=trainer, num_epochs=3, decay_epoch=None,
## 练习
* 试着使用其他的初始学习率和$\gamma$超参数的组合,观察并分析实验现象
* 试着使用其他的初始学习率和$\gamma$超参数的组合,观察并分析实验结果
## 讨论
......
......@@ -9,7 +9,7 @@
## RMSProp算法
我们在[“动量法——从零开始”](momentum-scratch.md)一节里介绍过指数加权移动平均。事实上,RMSProp算法使用了小批量随机梯度按元素平方的指数加权移动平均变量$\boldsymbol{s}$,并将其中每个元素初始化为0。
给定超参数$\gamma$且$0 \leq \gamma \leq 1$,
给定超参数$\gamma$且$0 \leq \gamma < 1$,
在每次迭代中,RMSProp首先计算小批量随机梯度$\boldsymbol{g}$,然后对该梯度按元素平方项$\boldsymbol{g} \odot \boldsymbol{g}$做指数加权移动平均,记为$\boldsymbol{s}$:
$$\boldsymbol{s} \leftarrow \gamma \boldsymbol{s} + (1 - \gamma) \boldsymbol{g} \odot \boldsymbol{g}. $$
......@@ -87,7 +87,7 @@ def init_params():
return params, sqrs
```
优化函数`optimize`[梯度下降和随机梯度下降——从零开始”](gd-sgd-scratch.md)一节中的类似。
优化函数`optimize`[Adagrad——从零开始”](adagrad-scratch.md)一节中的类似。
```{.python .input n=2}
net = utils.linreg
......@@ -135,7 +135,7 @@ optimize(batch_size=10, lr=0.03, gamma=0.999, num_epochs=3, log_interval=10)
## 练习
* 把$\gamma$的改成小于0或大于1的值,观察并分析实验现象
* 把$\gamma$的值设为0或1,观察并分析实验结果
## 讨论
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册