Skip to content

Commit

Permalink
Merge pull request #1100 from d2l-ai/master
Browse files Browse the repository at this point in the history
Post-edits till Mar 14 and lib upgrading
  • Loading branch information
astonzhang authored Mar 15, 2022
2 parents 7f205d2 + 84846ee commit 28e1114
Show file tree
Hide file tree
Showing 27 changed files with 136 additions and 125 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ stage("Build and Publish") {
def TARGET_BRANCH = env.CHANGE_TARGET ? env.CHANGE_TARGET : env.BRANCH_NAME
// such as d2l-en-master
def TASK = REPO_NAME + '-' + TARGET_BRANCH
node {
node('d2l-worker') {
ws("workspace/${TASK}") {
checkout scm
// conda environment
Expand Down
2 changes: 1 addition & 1 deletion chapter_attention-mechanisms/bahdanau-attention.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import tensorflow as tf

## 定义注意力解码器

下面我们看看如何定义Bahdanau注意力,实现循环神经网络编码器-解码器
下面我们看看如何定义Bahdanau注意力,实现循环神经网络编码器-解码器
其实,我们只需重新定义解码器即可。
为了更方便地显示学习的注意力权重,
以下`AttentionDecoder`类定义了[**带有注意力机制解码器的基本接口**]
Expand Down
6 changes: 3 additions & 3 deletions chapter_computer-vision/kaggle-dog.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ import os

### 下载数据集

登录Kaggle后,你可以点击 :numref:`fig_kaggle_dog`中显示的竞争网页上的“数据”选项卡,然后点击“全部下载”按钮下载数据集。在`../data`中解压下载的文件后,你将在以下路径中找到整个数据集:
登录Kaggle后,你可以点击 :numref:`fig_kaggle_dog`中显示的竞赛网页上的“数据”选项卡,然后点击“全部下载”按钮下载数据集。在`../data`中解压下载的文件后,你将在以下路径中找到整个数据集:

* ../data/dog-breed-identification/labels.csv
* ../data/dog-breed-identification/sample_submission.csv
* ../data/dog-breed-identification/train
* ../data/dog-breed-identification/test


你可能已经注意到,上述结构与 :numref:`sec_kaggle_cifar10`的CIFAR-10竞争对手类似,其中文件夹`train/``test/`分别包含训练和测试狗图像,`labels.csv`包含训练图像的标签。
你可能已经注意到,上述结构与 :numref:`sec_kaggle_cifar10`的CIFAR-10竞赛类似,其中文件夹`train/``test/`分别包含训练和测试狗图像,`labels.csv`包含训练图像的标签。
同样,为了便于入门,[**我们提供完整数据集的小规模样本**]`train_valid_test_tiny.zip`
如果你要在Kaggle比赛中使用完整的数据集,则需要将下面的`demo`变量更改为`False`

Expand Down Expand Up @@ -360,7 +360,7 @@ def train(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,
measures = f'train loss {metric[0] / metric[1]:.3f}'
if valid_iter is not None:
valid_loss = evaluate_loss(valid_iter, net, devices)
animator.add(epoch + 1, (None, valid_loss.detach()))
animator.add(epoch + 1, (None, valid_loss.detach().cpu()))
scheduler.step()
if valid_iter is not None:
measures += f', valid loss {valid_loss:.3f}'
Expand Down
2 changes: 1 addition & 1 deletion chapter_convolutional-modern/densenet.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ net.add(nn.BatchNorm(),
net = nn.Sequential(
b1, *blks,
nn.BatchNorm2d(num_channels), nn.ReLU(),
nn.AdaptiveMaxPool2d((1, 1)),
nn.AdaptiveAvgPool2d((1, 1)),
nn.Flatten(),
nn.Linear(num_channels, 10))
```
Expand Down
2 changes: 1 addition & 1 deletion chapter_convolutional-neural-networks/why-conv.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ $$[\mathbf{H}]_{i, j} = u + \sum_{a = -\Delta}^{\Delta} \sum_{b = -\Delta}^{\Del
:eqlabel:`eq_conv-layer`

简而言之, :eqref:`eq_conv-layer`是一个*卷积层*(convolutional layer),而卷积神经网络是包含卷积层的一类特殊的神经网络。
在深度学习研究社区中,$\mathbf{V}$被称为*卷积核*(convolution kernel)或者*滤波器*(filter),它仅仅是可学习的一个层的权重
在深度学习研究社区中,$\mathbf{V}$被称为*卷积核*(convolution kernel)或者*滤波器*(filter),亦或简单地称之为该卷积层的*权重*,通常该权重是可学习的参数
当图像处理的局部区域很小时,卷积神经网络与多层感知机的训练差异可能是巨大的:以前,多层感知机可能需要数十亿个参数来表示网络中的一层,而现在卷积神经网络通常只需要几百个参数,而且不需要改变输入或隐藏表示的维数。
参数大幅减少的代价是,我们的特征现在是平移不变的,并且当确定每个隐藏活性值时,每一层只包含局部的信息。
以上所有的权重学习都将依赖于归纳偏置。当这种偏置与现实相符时,我们就能得到样本有效的模型,并且这些模型能很好地泛化到未知数据中。
Expand Down
12 changes: 6 additions & 6 deletions chapter_installation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ pip install mxnet==1.7.0.post1
你可以按如下方式安装PyTorch的CPU或GPU版本:

```bash
pip install torch==1.8.1
pip install torchvision==0.9.1
pip install torch==1.10.2
pip install torchvision==0.11.3
```


Expand All @@ -99,8 +99,8 @@ pip install torchvision==0.9.1
你可以按如下方式安装TensorFlow的CPU或GPU版本:

```bash
pip install tensorflow==2.3.1
pip install tensorflow-probability==0.11.1
pip install tensorflow==2.8.0
pip install tensorflow-probability==0.16.0
```


Expand All @@ -109,7 +109,7 @@ pip install tensorflow-probability==0.11.1
我们的下一步是安装`d2l`包,以方便调取本书中经常使用的函数和类:

```bash
pip install d2l==0.17.3
pip install d2l==0.17.4
```


Expand Down Expand Up @@ -165,7 +165,7 @@ cd tensorflow
:end_tab:


安装完成后,你可以通过运行以下命令打开Jupyter笔记本:
安装完成后,你可以通过运行以下命令打开Jupyter笔记本(在Window系统的命令行窗口中运行以下命令前,需先将当前路径定位到刚下载的本书代码解压后的目录)

```bash
jupyter notebook
Expand Down
2 changes: 1 addition & 1 deletion chapter_linear-networks/linear-regression.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ $\eta$表示*学习率*(learning rate)。
%matplotlib inline
from d2l import mxnet as d2l
import math
from mxnet import np
import numpy as np
import time
```

Expand Down
17 changes: 8 additions & 9 deletions chapter_linear-networks/softmax-regression.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,23 +262,22 @@ $$H[P] = \sum_j - P(j) \log P(j).$$
我们至少需要$H[P]$“纳特(nat)”对其进行编码。
“纳特”相当于*比特*(bit),但是对数底为$e$而不是2。因此,一个纳特是$\frac{1}{\log(2)} \approx 1.44$比特。

### 惊异
### 信息量

压缩与预测有什么关系呢?
想象一下,我们有一个要压缩的数据流。
如果我们很容易预测下一个数据,那么这个数据很容易压缩
如果我们很容易预测下一个数据,那么这个数据就很容易压缩
为什么呢?
举一个极端的例子,假如数据流中的每个数据完全相同,这会是一个非常无聊的数据流。
由于它们总是相同的,所以很容易被预测。
所以,为了传递数据流的内容,我们不必传输任何信息。
因此,当数据易于预测,也就易于压缩。
由于它们总是相同的,我们总是知道下一个数据是什么。
所以,为了传递数据流的内容,我们不必传输任何信息。也就是说,“下一个数据是xx”这个事件毫无信息量。

但是,如果我们不能完全预测每一个事件,那么我们有时可能会感到"惊异"。
克劳德·香农决定用$\log \frac{1}{P(j)} = -\log P(j)$来量化*惊异*(surprisal)
在观察一个事件$j$,并赋予它(主观)概率$P(j)$。
当我们赋予一个事件较低的概率时,我们的惊异会更大。
克劳德·香农决定用信息量$\log \frac{1}{P(j)} = -\log P(j)$来量化这种惊异程度
在观察一个事件$j$,并赋予它(主观)概率$P(j)$。
当我们赋予一个事件较低的概率时,我们的惊异会更大,该事件的信息量也就更大
在 :eqref:`eq_softmax_reg_entropy`中定义的熵,
是当分配的概率真正匹配数据生成过程时的*预期惊异*(expected surprisal)
是当分配的概率真正匹配数据生成过程时的*信息量的期望*

### 重新审视交叉熵

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

>前提:一名男子正在运行Dive Into Deep Learning的编码示例。
假设:该男子正在睡觉。
>假设:该男子正在睡觉。
第三个例子显示了一种“中性”关系,因为“正在为我们表演”这一事实无法推断出“出名”或“不出名”。

Expand Down
4 changes: 2 additions & 2 deletions chapter_optimization/adadelta.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Adadelta算法是在 :cite:`Zeiler.2012`中提出的。

## Adadelta算法

简而言之,Adadelta使用两个状态变量,$\mathbf{s}_t$用于存储梯度二阶导数的漏平均值,$\Delta\mathbf{x}_t$用于存储模型本身中参数变化二阶导数的泄露平均值。请注意,为了与其他出版物和实现的兼容性,我们使用作者的原始符号和命名(没有其他真正理由为什么应该使用不同的希腊变量来表示在动量中用于相同用途的参数,即AdaGrad、RMSProp和Adadelta)。
简而言之,Adadelta使用两个状态变量,$\mathbf{s}_t$用于存储梯度二阶导数的泄露平均值,$\Delta\mathbf{x}_t$用于存储模型本身中参数变化二阶导数的泄露平均值。请注意,为了与其他出版物和实现的兼容性,我们使用作者的原始符号和命名(没有其它真正理由让大家使用不同的希腊变量来表示在动量法、AdaGrad、RMSProp和Adadelta中用于相同用途的参数)。

以下是Adadelta的技术细节。鉴于参数du jour是$\rho$,我们获得了与 :numref:`sec_rmsprop`类似的以下泄漏更新:

Expand Down Expand Up @@ -39,7 +39,7 @@ $$\begin{aligned}

## 代码实现

Adadelta需要为每个变量维护两个状态变量,即$\mathbf{s}_t$和$\Delta\mathbf{x}_t$。这将产生以下实施
Adadelta需要为每个变量维护两个状态变量,即$\mathbf{s}_t$和$\Delta\mathbf{x}_t$。这将产生以下实现

```{.python .input}
%matplotlib inline
Expand Down
6 changes: 3 additions & 3 deletions chapter_optimization/adagrad.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ $$f(\mathbf{x}) = \bar{f}(\bar{\mathbf{x}}) = \frac{1}{2} \bar{\mathbf{x}}^\top
$$\kappa = \frac{\boldsymbol{\Lambda}_1}{\boldsymbol{\Lambda}_d}.$$

如果条件编号$\kappa$很大,准确解决优化问题就会很难。
我们需要确保在获取大量动态的特征值范围时足够谨慎:我们不能简单地通过扭曲空间来“修复”这个问题,从而使所有特征值都是$1$?
我们需要确保在获取大量动态的特征值范围时足够谨慎:难道我们不能简单地通过扭曲空间来“修复”这个问题,从而使所有特征值都是$1$?
理论上这很容易:我们只需要$\mathbf{Q}$的特征值和特征向量即可将问题从$\mathbf{x}$整理到$\mathbf{z} := \boldsymbol{\Lambda}^{\frac{1}{2}} \mathbf{U} \mathbf{x}$中的一个。
在新的坐标系中,$\mathbf{x}^\top \mathbf{Q} \mathbf{x}$可以被简化为$\|\mathbf{z}\|^2$。
可惜,这是一个相当不切实际的想法。
Expand Down Expand Up @@ -110,7 +110,7 @@ $$\begin{aligned}
然而,在深度学习中,我们可能希望更慢地降低学习率。
这引出了许多AdaGrad算法的变体,我们将在后续章节中讨论它们。
眼下让我们先看看它在二次凸问题中的表现如何。
我们仍然同一函数为例
我们仍然以同一函数为例

$$f(\mathbf{x}) = 0.1 x_1^2 + 2 x_2^2.$$

Expand Down Expand Up @@ -260,7 +260,7 @@ d2l.train_concise_ch11(trainer, {'learning_rate' : 0.1}, data_iter)
1. 尝试对函数$f(\mathbf{x}) = 0.1 x_1^2 + 2 x_2^2$、以及它旋转45度后的函数即$f(\mathbf{x}) = 0.1 (x_1 + x_2)^2 + 2 (x_1 - x_2)^2$使用AdaGrad算法。它的表现会不同吗?
1. 证明[格什戈林圆盘定理](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem),其中提到,矩阵$\mathbf{M}$的特征值$\lambda_i$在至少一个$j$的选项中满足$|\lambda_i - \mathbf{M}_{jj}| \leq \sum_{k \neq j} |\mathbf{M}_{jk}|$的要求。
1. 关于对角线预处理矩阵$\mathrm{diag}^{-\frac{1}{2}}(\mathbf{M}) \mathbf{M} \mathrm{diag}^{-\frac{1}{2}}(\mathbf{M})$的特征值,格什戈林的定理告诉了我们什么?
1. 尝试对适当的深度网络使用AdaGrad算法,例如,当应用于时尚MNIST时,使用 :numref:`sec_lenet`
1. 尝试对适当的深度网络使用AdaGrad算法,例如,:numref:`sec_lenet`中应用于Fashion-MNIST的深度网络
1. 你要如何修改AdaGrad算法,才能使其在学习率方面的衰减不那么激进?

:begin_tab:`mxnet`
Expand Down
2 changes: 1 addition & 1 deletion chapter_optimization/adagrad_origin.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ d2l.train_concise_ch11(trainer, {'learning_rate' : 0.1}, data_iter)
1. Try out Adagrad for $f(\mathbf{x}) = 0.1 x_1^2 + 2 x_2^2$ and also for the objective function was rotated by 45 degrees, i.e., $f(\mathbf{x}) = 0.1 (x_1 + x_2)^2 + 2 (x_1 - x_2)^2$. Does it behave differently?
1. Prove [Gerschgorin's circle theorem](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem) which states that eigenvalues $\lambda_i$ of a matrix $\mathbf{M}$ satisfy $|\lambda_i - \mathbf{M}_{jj}| \leq \sum_{k \neq j} |\mathbf{M}_{jk}|$ for at least one choice of $j$.
1. What does Gerschgorin's theorem tell us about the eigenvalues of the diagonally preconditioned matrix $\mathrm{diag}^{-\frac{1}{2}}(\mathbf{M}) \mathbf{M} \mathrm{diag}^{-\frac{1}{2}}(\mathbf{M})$?
1. Try out Adagrad for a proper deep network, such as :numref:`sec_lenet` when applied to Fashion MNIST.
1. Try out Adagrad for a proper deep network, such as :numref:`sec_lenet` when applied to Fashion-MNIST.
1. How would you need to modify Adagrad to achieve a less aggressive decay in learning rate?

:begin_tab:`mxnet`
Expand Down
22 changes: 11 additions & 11 deletions chapter_optimization/adam.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* 在 :numref:`sec_sgd`中,我们学习了:随机梯度下降在解决优化问题时比梯度下降更有效。
* 在 :numref:`sec_minibatch_sgd`中,我们学习了:在一个小批量中使用更大的观测值集,可以通过向量化提供额外效率。这是高效的多机、多GPU和整体并行处理的关键。
* 在 :numref:`sec_momentum`中我们添加了一种机制,用于汇总过去梯度的历史以加速收敛。
* 在 :numref:`sec_adagrad`中,我们使用每坐标缩放来实现计算效率的预处理
* 在 :numref:`sec_adagrad`中,我们通过对每个坐标缩放来实现高效计算的预处理器
* 在 :numref:`sec_rmsprop`中,我们通过学习率的调整来分离每个坐标的缩放。

Adam算法 :cite:`Kingma.Ba.2014`将所有这些技术汇总到一个高效的学习算法中。
Expand All @@ -18,19 +18,19 @@ Adam算法 :cite:`Kingma.Ba.2014`将所有这些技术汇总到一个高效的

## 算法

Adam算法的关键组成部分之一是:它使用指数加权移动平均值来估算梯度的动量和第二力矩,即它使用状态变量
Adam算法的关键组成部分之一是:它使用指数加权移动平均值来估算梯度的动量和二次矩,即它使用状态变量

$$\begin{aligned}
\mathbf{v}_t & \leftarrow \beta_1 \mathbf{v}_{t-1} + (1 - \beta_1) \mathbf{g}_t, \\
\mathbf{s}_t & \leftarrow \beta_2 \mathbf{s}_{t-1} + (1 - \beta_2) \mathbf{g}_t^2.
\end{aligned}$$

这里$\beta_1$和$\beta_2$是非负加权参数。
他们的常见设置是$\beta_1 = 0.9$和$\beta_2 = 0.999$。
也就是说,方差的估计比动量的估计移动得远远更慢
常将它们设置为$\beta_1 = 0.9$和$\beta_2 = 0.999$。
也就是说,方差估计的移动远远慢于动量估计的移动
注意,如果我们初始化$\mathbf{v}_0 = \mathbf{s}_0 = 0$,就会获得一个相当大的初始偏差。
我们可以通过使用$\sum_{i=0}^t \beta^i = \frac{1 - \beta^t}{1 - \beta}$来解决这个问题。
相应地,标准化状态变量由以下获得
相应地,标准化状态变量由下式获得

$$\hat{\mathbf{v}}_t = \frac{\mathbf{v}_t}{1 - \beta_1^t} \text{ and } \hat{\mathbf{s}}_t = \frac{\mathbf{s}_t}{1 - \beta_2^t}.$$

Expand All @@ -50,8 +50,8 @@ $$\mathbf{x}_t \leftarrow \mathbf{x}_{t-1} - \mathbf{g}_t'.$$

回顾Adam算法,它的设计灵感很清楚:
首先,动量和规模在状态变量中清晰可见,
他们相当独特的定义使我们移除偏项目(这可以通过稍微不同的初始化和更新条件来修正)。
其次,RMSProp算法中两个项目的组合都非常简单
它们相当独特的定义使我们移除偏项(这可以通过稍微不同的初始化和更新条件来修正)。
其次,RMSProp算法中两项的组合都非常简单
最后,明确的学习率$\eta$使我们能够控制步长来解决收敛问题。

## 实现
Expand Down Expand Up @@ -161,13 +161,13 @@ d2l.train_concise_ch11(trainer, {'learning_rate': 0.01}, data_iter)
## Yogi

Adam算法也存在一些问题:
即使在凸环境下,当$\mathbf{s}_t$的第二力矩估计值爆炸时,它可能无法收敛。
即使在凸环境下,当$\mathbf{s}_t$的二次矩估计值爆炸时,它可能无法收敛。
:cite:`Zaheer.Reddi.Sachan.ea.2018`为$\mathbf{s}_t$提出了的改进更新和参数初始化。
论文中建议我们重写Adam算法更新如下:

$$\mathbf{s}_t \leftarrow \mathbf{s}_{t-1} + (1 - \beta_2) \left(\mathbf{g}_t^2 - \mathbf{s}_{t-1}\right).$$

每当$\mathbf{g}_t^2$具有高变量或更新稀疏时,$\mathbf{s}_t$可能会太快地“忘记”过去的值。
每当$\mathbf{g}_t^2$具有值很大的变量或更新很稀疏时,$\mathbf{s}_t$可能会太快地“忘记”过去的值。
一个有效的解决方法是将$\mathbf{g}_t^2 - \mathbf{s}_{t-1}$替换为$\mathbf{g}_t^2 \odot \mathop{\mathrm{sgn}}(\mathbf{g}_t^2 - \mathbf{s}_{t-1})$。
这就是Yogi更新,现在更新的规模不再取决于偏差的量。

Expand Down Expand Up @@ -236,13 +236,13 @@ d2l.train_ch11(yogi, init_adam_states(feature_dim),

* Adam算法将许多优化算法的功能结合到了相当强大的更新规则中。
* Adam算法在RMSProp算法基础上创建的,还在小批量的随机梯度上使用EWMA。
* 在估计动量和第二力矩时,Adam算法使用偏差校正来调整缓慢的启动速度。
* 在估计动量和二次矩时,Adam算法使用偏差校正来调整缓慢的启动速度。
* 对于具有显著差异的梯度,我们可能会遇到收敛性问题。我们可以通过使用更大的小批量或者切换到改进的估计值$\mathbf{s}_t$来修正它们。Yogi提供了这样的替代方案。

## 练习

1. 调节学习率,观察并分析实验结果。
1. 你能重写动量和第二力矩更新,从而使其不需要偏差校正吗?
1. 你能重写动量和二次矩更新,从而使其不需要偏差校正吗?
1. 当我们收敛时,为什么你需要降低学习率$\eta$?
1. 尝试构造一个使用Adam算法会发散而Yogi会收敛的例子。

Expand Down
Loading

0 comments on commit 28e1114

Please sign in to comment.