Skip to content

Commit

Permalink
Merge pull request #893 from d2l-ai/master
Browse files Browse the repository at this point in the history
Build PyTorch pdf
  • Loading branch information
astonzhang authored Jun 30, 2021
2 parents fee3287 + b0ce242 commit 098eb16
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 85 deletions.
5 changes: 5 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ stage("Build and Publish") {
d2lbook build pdf
"""

sh label:"Build Pytorch PDF", script:"""set -ex
conda activate ${ENV_NAME}
d2lbook build pdf --tab pytorch
"""

if (env.BRANCH_NAME == 'release') {
sh label:"Release", script:"""set -ex
conda activate ${ENV_NAME}
Expand Down
4 changes: 4 additions & 0 deletions STYLE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
* 时刻t(不是t时刻)
* 形状使用英文标点
* (10, 20) 不是 (10,20)
* 空格:
* 文本中中文和英文、数字、数学公式、特殊字体等之间不要加空格
* 非行首的`:numref:`、`:cite:`等前留有一个英文空格(否则网页不渲染)
* 代码注释同上
* 人称
* 第一人称 → 我们
* 第二人称 → 读者、你、大家
Expand Down
2 changes: 1 addition & 1 deletion chapter_computer-vision/kaggle-cifar10.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ train(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,
lr_decay)
```

## 在 Kaggle 上对测试集进行分类并提交结果
## 在 Kaggle [对测试集进行分类并提交结果]

在获得具有超参数的满意的模型后,我们使用所有标记的数据(包括验证集)来重新训练模型并对测试集进行分类。

Expand Down
6 changes: 4 additions & 2 deletions chapter_convolutional-neural-networks/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,13 @@ corr2d_multi_in_out(X, K)
## $1\times 1$ 卷积层

[~~1x1卷积~~]
$1 \times 1 $卷积,即 $k_h = k_w = 1$,看起来似乎没有多大意义。毕竟,卷积的本质是有效提取相邻像素间的相关特征,而 $1 \times 1$ 卷积显然没有此作用。

$1\times 1$ 卷积,即 $k_h = k_w = 1$,看起来似乎没有多大意义。
毕竟,卷积的本质是有效提取相邻像素间的相关特征,而 $1 \times 1$ 卷积显然没有此作用。
尽管如此,$1 \times 1$ 仍然十分流行,时常包含在复杂深层网络的设计中。下面,让我们详细地解读一下它的实际作用。

因为使用了最小窗口,$1\times 1$ 卷积失去了卷积层的特有能力——在高度和宽度维度上,识别相邻元素间相互作用的能力。
$1\times 1$ 卷积的唯一计算发生在通道上。
其实 $1\times 1$ 卷积的唯一计算发生在通道上。

:numref:`fig_conv_1x1` 展示了使用 $1\times 1$ 卷积核与 $3$ 个输入通道和 $2$ 个输出通道的互相关计算。
这里输入和输出具有相同的高度和宽度,输出中的每个元素都是从输入图像中同一位置的元素的线性组合。
Expand Down
2 changes: 1 addition & 1 deletion chapter_convolutional-neural-networks/lenet.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ LeNet 被广泛用于自动取款机(ATM)机中,帮助识别处理支票
![LeNet中的数据流。输入是手写数字,输出为10种可能结果的概率。](../img/lenet.svg)
:label:`img_lenet`

每个卷积块中的基本单元是一个卷积层、一个 sigmoid 激活函数和平均池化层。请注意,虽然 ReLU 和最大池化层更有效,但它们在20世纪90年代还没有出现。每个卷积层使用 $5\times 5$ 卷积核,这些层将输入映射到多个二维特征输出,通常同时增加通道的数量。第一卷积层有 6 个输出通道,而第二个卷积层有 16 个输出通道。每个 $2\times2$ 池操作(步骤2)通过空间下采样将维数减少 4 倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。
每个卷积块中的基本单元是一个卷积层、一个 sigmoid 激活函数和平均池化层。请注意,虽然 ReLU 和最大池化层更有效,但它们在20世纪90年代还没有出现。每个卷积层使用 $5\times 5$ 卷积核和一个 sigmoid 激活函数。这些层将输入映射到多个二维特征输出,通常同时增加通道的数量。第一卷积层有 6 个输出通道,而第二个卷积层有 16 个输出通道。每个 $2\times2$ 池操作(步骤2)通过空间下采样将维数减少 4 倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。

为了将卷积块的输出传递给稠密块,我们必须在小批量中展平每个样本。换言之,我们将这个四维输入转换成全连接层所期望的二维输入。这里的二维表示的第一个维度索引小批量中的样本,第二个维度给出每个样本的平面向量表示。LeNet 的稠密块有三个全连接层,分别有 120、84 和 10 个输出。因为我们仍在执行分类,所以输出层的 10 维对应于最后输出结果的数量。

Expand Down
4 changes: 2 additions & 2 deletions chapter_convolutional-neural-networks/padding-and-strides.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ $$(n_h-k_h+p_h+1)\times(n_w-k_w+p_w+1)。$$
1. 内核的大小是奇数;
2. 所有边的填充行数和列数相同;
3. 输出与输入具有相同高度和宽度
则可以得出:输出 `Y[i, j]` 是通过以输入 `X[i, j]` 为中心,与卷积核进行互相关计算
则可以得出:输出 `Y[i, j]` 是通过以输入 `X[i, j]` 为中心,与卷积核进行互相关计算得到的

比如,在下面的例子中,我们创建一个高度和宽度为3的二维卷积层,并(**在所有侧边填充1个像素**)。给定高度和宽度为8的输入,则输出的高度和宽度也是8。

Expand Down Expand Up @@ -133,7 +133,7 @@ comp_conv2d(conv2d, X).shape
:numref:`img_conv_stride` 是垂直步幅为 $3$,水平步幅为 $2$ 的二维互相关运算。
着色部分是输出元素以及用于输出计算的输入和内核张量元素:$0\times0+0\times1+1\times2+2\times3=8$、$0\times0+6\times1+0\times2+0\times3=6$。

如何计算输出中第一列的第二个元素呢?如图所示,卷积窗口向下滑动三行、向右滑动两列。但是,当卷积窗口继续向右滑动两列时,没有输出,因为输入元素无法填充窗口(除非我们添加另一列填充)。
可以看到,为了计算输出中第一列的第二个元素和第一行的第二个元素,卷积窗口分别向下滑动三行和向右滑动两列。但是,当卷积窗口继续向右滑动两列时,没有输出,因为输入元素无法填充窗口(除非我们添加另一列填充)。

![垂直步幅为 $3$,水平步幅为 $2$ 的二维互相关运算。](../img/conv-stride.svg)
:label:`img_conv_stride`
Expand Down
20 changes: 11 additions & 9 deletions chapter_recurrent-modern/encoder-decoder.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# 编码器-解码器结构
:label:`sec_encoder-decoder`

正如我们在:numref:`sec_machine_translation`中所讨论的,机器翻译是序列转换模型的一个核心问题,其输入和输出都是长度可变的序列。为了处理这种类型的输入和输出,我们可以设计一个包含两个主要组件的结构。第一个组件是一个*编码器*(encoder):它接受一个长度可变的序列作为输入,并将其转换为具有形状固定的编码状态。第二个组件是*解码器*(decoder):它将形状固定的编码状态映射到长度可变的序列。这被称为*编码器-解码器*(encoder-decoder)结构。如:numref:`fig_encoder_decoder`所示。
正如我们在 :numref:`sec_machine_translation` 中所讨论的,机器翻译是序列转换模型的一个核心问题,其输入和输出都是长度可变的序列。为了处理这种类型的输入和输出,我们可以设计一个包含两个主要组件的结构。第一个组件是一个 *编码器*(encoder):它接受一个长度可变的序列作为输入,并将其转换为具有固定形状的编码状态。第二个组件是 *解码器*(decoder):它将固定形状的编码状态映射到长度可变的序列。这被称为 *编码器-解码器*(encoder-decoder)结构。如 :numref:`fig_encoder_decoder` 所示。

![编码器-解码器结构](../img/encoder-decoder.svg)
:label:`fig_encoder_decoder`

让我们以英语到法语的机器翻译为例。给定一个英文的输入序列:“They”、“are”、“watching”、“.”,这种“编码器-解码器”结构首先将长度可变的输入编码成一个状态,然后对该状态进行解码,一个标记接着一个标记地生成翻译后的序列作为输出:“Ils”、“regordent”、“.”。由于“编码器-解码器”结构是形成后续章节中不同序列转换模型的基础,因此本节将把这个结构转换为接口用于后面的代码实现
让我们以英语到法语的机器翻译为例。给定一个英文的输入序列:“They”、“are”、“watching”、“.”。首先,这种“编码器-解码器”结构将长度可变的输入序列编码成一个状态,然后对该状态进行解码,一个标记接着一个标记地生成翻译后的序列作为输出:“Ils”、“regordent”、“.”。由于“编码器-解码器”结构是形成后续章节中不同序列转换模型的基础,因此本节将把这个结构转换为接口方便后面的代码实现

## 编码器

在编码器接口中,我们只指定长度可变的序列作为编码器的输入`X`。任何继承这个`Encoder`基类的模型将完成代码实现。
在编码器接口中,我们只指定长度可变的序列作为编码器的输入 `X`。任何继承这个 `Encoder` 基类的模型将完成代码实现。

```{.python .input}
from mxnet.gluon import nn
Expand Down Expand Up @@ -41,7 +41,7 @@ class Encoder(nn.Module):

## 解码器

在下面的解码器接口中,我们新增一个`init_state`函数用于将编码器的输出(`enc_outputs`)转换为编码后的状态。注意,此步骤可能需要额外的输入,例如:输入序列的有效长度,这在:numref:`subsec_mt_data_loading`中进行了解释。为了逐个生成长度可变的标记序列,解码器在每个时间步都可以将输入(例如:在前一时间步生成的标记)和编码后的状态映射成当前时间步的输出标记。
在下面的解码器接口中,我们新增一个 `init_state` 函数用于将编码器的输出(`enc_outputs`)转换为编码后的状态。注意,此步骤可能需要额外的输入,例如:输入序列的有效长度,这在 :numref:`subsec_mt_data_loading` 中进行了解释。为了逐个地生成长度可变的标记序列,解码器在每个时间步都会将输入(例如:在前一时间步生成的标记)和编码后的状态映射成当前时间步的输出标记。

```{.python .input}
#@save
Expand Down Expand Up @@ -74,7 +74,7 @@ class Decoder(nn.Module):

## 合并编码器和解码器

最后,“编码器-解码器”结构包含了一个编码器和一个解码器,并且还包含了可选的额外的参数。在前向传播中,编码器的输出产生编码状态,解码器将使用该状态作为其输入之一
最后,“编码器-解码器”结构包含了一个编码器和一个解码器,并且还拥有可选的额外的参数。在前向传播中,编码器的输出用于生成编码状态,这个状态又被解码器作为其输入的一部分

```{.python .input}
#@save
Expand Down Expand Up @@ -107,13 +107,14 @@ class EncoderDecoder(nn.Module):
return self.decoder(dec_X, dec_state)
```

“编码器-解码器”体系结构中的术语“状态”可能会启发你使用具有状态的神经网络来实现该结构。在下一节中,我们将看到如何应用循环神经网络来设计基于这种“编码器-解码器”结构的序列转换模型。
“编码器-解码器”体系结构中的术语“状态”可能会启发你使用具有状态的神经网络来实现该结构。
在下一节中,我们将学习如何应用循环神经网络,来设计基于“编码器-解码器”结构的序列转换模型。

## 小结

* “编码器-解码器”结构可以处理长度可变的序列作为输入和输出,因此适用于机器翻译等序列转换问题。
* 编码器将长度可变的序列作为输入,并将其转换为具有形状固定的状态
* 解码器将形状固定的编码状态映射为长度可变的序列
* “编码器-解码器”结构可以将长度可变的序列作为输入和输出,因此适用于机器翻译等序列转换问题。
* 编码器将长度可变的序列作为输入,并将其转换为具有固定形状的编码状态
* 解码器将具有固定形状的编码状态映射为长度可变的序列

## 练习

Expand All @@ -127,3 +128,4 @@ class EncoderDecoder(nn.Module):
:begin_tab:`pytorch`
[Discussions](https://discuss.d2l.ai/t/2779)
:end_tab:

Loading

0 comments on commit 098eb16

Please sign in to comment.