Skip to content

Commit

Permalink
[1e feedback] fig caption, code comment shape and reference
Browse files Browse the repository at this point in the history
  • Loading branch information
astonzhang committed Jan 15, 2019
1 parent b1e246d commit d62e686
Show file tree
Hide file tree
Showing 37 changed files with 92 additions and 90 deletions.
20 changes: 10 additions & 10 deletions chapter_appendix/aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,40 @@

登陆AWS账号后,点击图11.8红框中的“EC2”进入EC2面板。

![登陆AWS账号](../img/aws.png)
![登陆AWS账号](../img/aws.png)


## 创建并运行EC2实例

图11.9展示了EC2面板的界面。在图11.9右上角红框处选择离我们较近的数据中心来减低延迟。我们可以选离国内较近的亚太地区,例如Asia Pacific(Seoul)。注意,有些数据中心可能没有GPU实例。点击图11.9下方红框内“Launch Instance”按钮启动实例。

![EC2面板](../img/ec2.png)
![EC2面板](../img/ec2.png)


图11.10的最上面一行显示了配置实例所需的7个步骤。在第一步“1. Choose AMI”中,选择Ubuntu 16.04作为操作系统。

![选择操作系统](../img/os.png)
![选择操作系统](../img/os.png)

EC2提供了大量不同配置的实例。如图11.11所示,在第二步“2. Choose Instance Type”中,选择有一个K80 GPU的“p2.xlarge”实例。我们也可以选择像“p2.16xlarge”这样有多个GPU的实例。如果你想比较不同实例的机器配置和收费,可参考 https://www.ec2instances.info/

![选择实例](../img/p2x.png)
![选择实例](../img/p2x.png)

我们建议在选择实例前先在图11.9左栏“Limits”标签里检查下有无数量限制。如图11.12所示,该账号的限制是最多在一个区域开一个“p2.xlarge”实例。如果需要开更多实例,可以通过点击右边“Request limit increase”链接来申请更大的实例容量。这通常需要一个工作日来处理。

![实例的数量限制](../img/limits.png)
![实例的数量限制](../img/limits.png)

我们将保持第三步“3. Configure Instance”、第五步“5. Add Tags”和第六步“6. Configure Security Group”中的默认配置不变。点击第四步“4.Add Storage”,如图11.13所示,将默认的硬盘大小增大到40GB。注意,安装CUDA需要4GB左右空间。

![修改实例的硬盘大小](../img/disk.png)
![修改实例的硬盘大小](../img/disk.png)


最后,在第七步“7. Review”中点击“Launch”来启动配置好的实例。这时候会提示我们选择用来访问实例的密钥。如果没有的话,可以选择图11.14中第一个下拉菜单的“Create a new key pair”选项来生成秘钥。之后,我们通过该下拉菜单的“Choose an existing key pair”选项选择生成好的密钥。点击“Launch Instances”按钮启动创建好的实例。

![选择密钥](../img/keypair.png)
![选择密钥](../img/keypair.png)

点击图11.15中的实例ID就可以查看该实例的状态了。

![点击实例ID](../img/launching.png)
![点击实例ID](../img/launching.png)

如图11.16所示,当实例状态(Instance State)变绿后,右击实例并选择“Connect”,这时就可以看到访问该实例的方法了。例如在命令行输入

Expand All @@ -70,7 +70,7 @@ sudo apt-get update && sudo apt-get install -y build-essential git libgfortran3

NVIDIA一般每年会更新一次CUDA主版本。这里我们下载作者写本书时的最新主版本CUDA 9.0(也可使用MXNet支持的其他版本)。访问NVIDIA官网(https://developer.nvidia.com/cuda-90-download-archive )获取正确版本的CUDA 9.0的下载地址,如图11.17所示。

![获取CUDA9.0的下载地址](../img/cuda.png)
![获取CUDA9.0的下载地址](../img/cuda.png)


获取下载地址后,我们将下载并安装CUDA9.0,例如
Expand Down Expand Up @@ -160,7 +160,7 @@ jupyter notebook

图11.18显示了运行后可能的输出,其中最后一行为8888端口下的URL。

![运行Jupyter记事本后的输出,其中最后一行为8888端口下的URL](../img/jupyter.png)
![运行Jupyter记事本后的输出,其中最后一行为8888端口下的URL](../img/jupyter.png)

由于创建的实例并没有暴露8888端口,我们可以在本地命令行启动ssh从实例映射到本地8889端口。

Expand Down
2 changes: 1 addition & 1 deletion chapter_appendix/buy-gpu.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ GPU的性能主要由以下三个参数构成:

图11.19描绘了GTX 900和1000系列里各个型号的32位浮点计算能力和价格的对比。其中价格为Wikipedia的建议价格。

![浮点计算能力和价格的对比](../img/gtx.png)
![浮点计算能力和价格的对比](../img/gtx.png)

我们可以从图11.19中读出两点信息:

Expand Down
12 changes: 6 additions & 6 deletions chapter_appendix/how-to-contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

第二步,登录Github。在浏览器输入本书代码库地址 [2]。点击图11.20右上方红框中的“Fork”按钮获得一份本书的代码库。

![代码库的页面](../img/contrib01.png)
![代码库的页面](../img/contrib01.png)


这时,本书的代码库会复制到你的用户名下,例如图11.21左上方显示的“你的Github ID/d2l-zh”。

![复制代码库](../img/contrib02.png)
![复制代码库](../img/contrib02.png)


第三步,点击图11.21右方的“Clone or download”绿色按钮,并点击红框中的按钮复制位于你用户名下的代码库地址。按[“获取和运行本书的代码”](../chapter_prerequisite/install.md)一节中介绍的方法进入命令行模式。假设我们希望将代码库保存在本地的“~/repo”路径之下。进入该路径,键入`git clone `并粘贴位于你用户名下的代码库地址。执行命令
Expand All @@ -38,7 +38,7 @@ git status

此时Git将提示“chapter_deep-learning-basics/linear-regression.md”文件已被修改,如图11.22所示。

![Git提示“chapter_deep-learning-basics/linear-regression.md”文件已被修改](../img/contrib03.png)
![Git提示“chapter_deep-learning-basics/linear-regression.md”文件已被修改](../img/contrib03.png)

确认将提交该修改的文件后,执行以下命令

Expand All @@ -54,17 +54,17 @@ git push
第五步,再次在浏览器输入本书代码库地址 [2]。点击图11.20左方红框中的“New pull request”按钮。在弹出的页面中,点击图11.23右方红框中的“compare across forks”链接,再点击下方红框中的“head fork: d2l-ai/d2l-zh”按钮。在弹出的文本框中输入你的Github ID,在下拉菜单中选择“你的Github-ID/d2l-zh”,如图11.23所示。


![选择改动来源所在的代码库](../img/contrib04.png)
![选择改动来源所在的代码库](../img/contrib04.png)


第六步,如图11.24所示,在标题和正文的文本框中描述想要提交的pull request。点击红框中的“Create pull request”绿色按钮提交pull request。

![描述并提交pull request](../img/contrib05.png)
![描述并提交pull request](../img/contrib05.png)


提交完成后,我们会看到图11.25所示的页面中显示pull request已提交。

![显示pull request已提交](../img/contrib06.png)
![显示pull request已提交](../img/contrib06.png)



Expand Down
14 changes: 7 additions & 7 deletions chapter_appendix/jupyter.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,38 @@

下面我们介绍如何在本地使用Jupyter记事本来编辑和运行本书代码。假设本书代码所在的本地路径为“xx/yy/d2l-zh/”。在命令行模式下进入该路径(`cd xx/yy/d2l-zh`),然后运行命令`jupyter notebook`。这时在浏览器打开 http://localhost:8888 (通常会自动打开)就可以看到Jupyter记事本的界面和本书代码所在的各个文件夹,如图11.1所示。

![本书代码所在的各个文件夹](../img/jupyter00.png)
![本书代码所在的各个文件夹](../img/jupyter00.png)


我们可以通过点击网页上显示的文件夹访问其中的记事本文件。它们的后缀通常是“ipynb”。
为了简洁起见,我们创建一个临时的“test.ipynb”文件,点击后所显示的内容如图11.2所示。该记事本包括了格式化文本单元(markdown cell)和代码单元(code cell)。其中格式化文本单元中的内容包括“这是标题”和“这是一段正文。”。代码单元中包括两行Python代码。

![“test.ipynb”文件包括了格式化文本单元和代码单元](../img/jupyter01.png)
![“test.ipynb”文件包括了格式化文本单元和代码单元](../img/jupyter01.png)


双击格式化文本单元,我们进入了编辑模式。在该单元的末尾添加一段新文本“你好世界。”,如图11.3所示。

![编辑格式化文本单元](../img/jupyter02.png)
![编辑格式化文本单元](../img/jupyter02.png)


如图11.4所示,点击菜单栏的“Cell” $\rightarrow$ “Run Cells”,运行编辑好的单元。

![运行单元](../img/jupyter03.png)
![运行单元](../img/jupyter03.png)


运行完以后,图11.5展示了编辑后的格式化文本单元。

![编辑后的格式化文本单元](../img/jupyter04.png)
![编辑后的格式化文本单元](../img/jupyter04.png)


接下来,点击代码单元。在最后一行代码后添加乘以2的操作 `* 2`,如图11.6所示。

![编辑代码单元](../img/jupyter05.png)
![编辑代码单元](../img/jupyter05.png)


我们也可以用快捷键运行单元(默认“Ctrl + Enter”),并得到图11.7中的输出结果。

![运行代码单元得到输出结果](../img/jupyter06.png)
![运行代码单元得到输出结果](../img/jupyter06.png)


当一个记事本包含的单元较多时,我们可以点击菜单栏的“Kernel” $\rightarrow$ “Restart & Run All”,以运行整个记事本中的所有单元。点击菜单栏的“Help” $\rightarrow$ “Edit Keyboard Shortcuts”后可以根据自己的喜好编辑快捷键。
Expand Down
2 changes: 1 addition & 1 deletion chapter_computational-performance/multiple-gpus.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

假设一台机器上有$k$个GPU。给定需要训练的模型,每个GPU将分别独立维护一份完整的模型参数。在模型训练的任意一次迭代中,给定一个随机小批量,我们将该批量中的样本划分成$k$份并分给每个GPU一份。然后,每个GPU将根据自己所分到的小批量子集和自己所维护的模型参数分别计算模型参数的本地梯度。接下来,我们把$k$个GPU上的本地梯度相加,便得到当前的小批量随机梯度。之后,每个GPU都使用这个小批量随机梯度分别更新自己所维护的那一份完整的模型参数。图8.1描绘了使用两个GPU的数据并行下的小批量随机梯度的计算。

![使用两个GPU的数据并行下的小批量随机梯度的计算](../img/data-parallel.svg)
![使用两个GPU的数据并行下的小批量随机梯度的计算](../img/data-parallel.svg)

为了从零开始实现多GPU训练中的数据并行,让我们先导入需要的包或模块。

Expand Down
4 changes: 2 additions & 2 deletions chapter_computer-vision/anchor.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ $$J(\mathcal{A},\mathcal{B}) = \frac{\left|\mathcal{A} \cap \mathcal{B}\right|}{

实际上,我们可以把边界框内的像素区域看成是像素的集合。如此一来,我们可以用两个边界框的像素集合的Jaccard系数衡量这两个边界框的相似度。当衡量两个边界框的相似度时,我们通常将Jaccard系数称为交并比(Intersection over Union,简称IoU),即两个边界框相交面积与相并面积之比,如图9.2所示。交并比的取值范围在0和1之间:0表示两个边界框无重合像素,1表示两个边界框相等。

![交并比是两个边界框相交面积与相并面积之比](../img/iou.svg)
![交并比是两个边界框相交面积与相并面积之比](../img/iou.svg)

在本节的剩余部分,我们将使用交并比来衡量锚框与真实边界框,以及锚框与锚框之间的相似度。

Expand All @@ -109,7 +109,7 @@ $$J(\mathcal{A},\mathcal{B}) = \frac{\left|\mathcal{A} \cap \mathcal{B}\right|}{

如图9.3(左)所示,假设矩阵$\boldsymbol{X}$中最大值为$x_{23}$,我们将为锚框$A_2$分配真实边界框$B_3$。然后,丢弃矩阵中所有第2行第3列的元素,找出剩余阴影部分的最大元素$x_{71}$,为锚框$A_7$分配真实边界框$B_1$。接着如图9.3(中)所示,丢弃矩阵中所有第7行第1列的元素,找出剩余阴影部分的最大元素$x_{54}$,为锚框$A_5$分配真实边界框$B_4$。最后如图9.3(右)所示,丢弃矩阵中所有第5行第4列的元素,找出剩余阴影部分的最大元素$x_{92}$,为锚框$A_9$分配真实边界框$B_2$。之后,我们只需遍历除去$A_2, A_5, A_7, A_9$的剩余锚框,并根据阈值判断是否为剩余锚框分配真实边界框。

![为锚框分配真实边界框](../img/anchor-label.svg)
![为锚框分配真实边界框](../img/anchor-label.svg)


现在我们可以标注锚框的类别和偏移量了。如果一个锚框$A$被分配了真实边界框$B$,将锚框$A$的类别设为$B$的类别,并根据$B$和$A$的中心坐标相对位置以及两个框的相对大小为锚框$A$标注偏移量。由于数据集中各个框的位置和大小各异,这些相对位置和相对大小通常需要一些特殊变换,才能使偏移量的分布更均匀从而更容易拟合。设锚框$A$及其被分配的真实边界框$B$的中心坐标分别为$(x_a, y_a), (x_b, y_b)$,$A$和$B$的宽分别为$w_a, w_b$,高分别为$h_a, h_b$,一个常用的技巧是将$A$的偏移量标注为
Expand Down
3 changes: 2 additions & 1 deletion chapter_computer-vision/bounding-box.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ dog_bbox, cat_bbox = [60, 45, 378, 516], [400, 112, 655, 493]

```{.python .input n=3}
def bbox_to_rect(bbox, color): # 本函数已保存在d2lzh包中方便以后使用
# 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式:((左上x,左上y),宽,高)
# 将边界框(左上x, 左上y, 右下x, 右下y)格式转换成matplotlib格式:
# ((左上x, 左上y), 宽, 高)
return d2l.plt.Rectangle(
xy=(bbox[0], bbox[1]), width=bbox[2]-bbox[0], height=bbox[3]-bbox[1],
fill=False, edgecolor=color, linewidth=2)
Expand Down
2 changes: 1 addition & 1 deletion chapter_computer-vision/fcn.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ conv_trans(Y).shape

我们在这里给出全卷积网络模型最基本的设计。如图9.11所示,全卷积网络先使用卷积神经网络抽取图像特征,然后通过$1\times 1$卷积层将通道数变换为类别个数,最后通过转置卷积层将特征图的高和宽变换为输入图像的尺寸。模型输出与输入图像的高和宽相同,并在空间位置上一一对应:最终输出的通道包含了该空间位置像素的类别预测。

![全卷积网络](../img/fcn.svg)
![全卷积网络](../img/fcn.svg)

下面我们使用一个基于ImageNet数据集预训练的ResNet-18模型来抽取图像特征,并将该网络实例记为`pretrained_net`。可以看到,该模型成员变量`features`的最后两层分别是全局最大池化层`GlobalAvgPool2D`和样本变平层`Flatten`,而`output`模块包含了输出用的全连接层。全卷积网络不需要使用这些层。

Expand Down
2 changes: 1 addition & 1 deletion chapter_computer-vision/fine-tuning.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
4. 在目标数据集(例如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

![微调](../img/finetune.svg)
![微调](../img/finetune.svg)


## 热狗识别
Expand Down
2 changes: 1 addition & 1 deletion chapter_computer-vision/kaggle-gluon-cifar10.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
图9.16展示了该比赛的网页信息。为了便于提交结果,请先在Kaggle网站上注册账号。

![CIFAR-10图像分类比赛的网页信息。比赛数据集可通过点击“Data”标签获取(来源:www.kaggle.com/c/cifar-10)](../img/kaggle_cifar10.png)
![CIFAR-10图像分类比赛的网页信息。比赛数据集可通过点击“Data”标签获取(来源:www.kaggle.com/c/cifar-10)](../img/kaggle_cifar10.png)

首先,导入比赛所需的包或模块。

Expand Down
2 changes: 1 addition & 1 deletion chapter_computer-vision/kaggle-gluon-dog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

图9.17展示了该比赛的网页信息。为了便于提交结果,请先在Kaggle网站上注册账号。

![狗的品种识别比赛的网页信息。比赛数据集可通过点击“Data”标签获取(来源:www.kaggle.com/c/dog-breed-identification)](../img/kaggle-dog.png)
![狗的品种识别比赛的网页信息。比赛数据集可通过点击“Data”标签获取(来源:www.kaggle.com/c/dog-breed-identification)](../img/kaggle-dog.png)

首先,导入比赛所需的包或模块。

Expand Down
8 changes: 4 additions & 4 deletions chapter_computer-vision/neural-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

在本节中,我们将介绍如何使用卷积神经网络自动将某图像中的样式应用在另一图像之上,即样式迁移(style transfer)[1]。这里我们需要两张输入图像,一张是内容图像,另一张是样式图像:我们将使用神经网络修改内容图像使得其在样式上接近样式图像。图9.12中的内容图像为本书作者在西雅图郊区的雷尼尔山国家公园(Mount Rainier National Park)拍摄的风景照,而样式图像则是一副主题为秋天橡树的油画。最终输出的合成图像在保留了内容图像中物体主体形状的情况下应用了样式图像的油画笔触,同时也让整体颜色更加鲜艳。

![输入内容图像和样式图像,输出样式迁移后的合成图像](../img/style-transfer.svg)
![输入内容图像和样式图像,输出样式迁移后的合成图像](../img/style-transfer.svg)

## 方法

图9.13用一个例子来阐述基于卷积神经网络的样式迁移方法。首先,我们初始化合成图像,例如将其初始化成内容图像。该合成图像是样式迁移过程中唯一需要更新的变量,即样式迁移所需迭代的模型参数。然后,我们选择一个预训练的卷积神经网络来抽取图像的特征,其中的模型参数在训练中无需更新。深度卷积神经网络凭借多个神经层逐级抽取图像的特征。我们可以选择其中某些层的输出作为内容特征或样式特征。以图9.13为例,这里选取的预训练的神经网络含有三个卷积层,其中第二层则输出图像的内容特征,而第一层和第三层的输出被作为图像的样式特征。接下来,我们通过正向传播(实线箭头方向)计算样式迁移的损失函数,并通过反向传播(虚线箭头方向)迭代模型参数,即不断更新合成图像。样式迁移常用的损失函数由三部分组成:内容损失(content loss)使合成图像与内容图像在内容特征上接近,样式损失(style loss)令合成图像与样式图像在样式特征上接近,而总变差损失(total variation loss)则有助于减少合成图像中的噪点。最后,当模型训练结束时,我们输出样式迁移的模型参数,即得到最终的合成图像。

![基于卷积神经网络的样式迁移。实线箭头和虚线箭头分别表示正向传播和反向传播](../img/neural-style.svg)
![基于卷积神经网络的样式迁移。实线箭头和虚线箭头分别表示正向传播和反向传播](../img/neural-style.svg)

下面,我们通过实验来进一步了解样式迁移的技术细节。实验需要用到一些导入的包或模块。

Expand Down Expand Up @@ -242,7 +242,7 @@ output = train(content_X, contents_Y, styles_Y, ctx, 0.01, 500, 200)
d2l.plt.imsave('../img/neural-style-1.png', postprocess(output).asnumpy())
```

![$150 \times 225$尺寸的合成图像](../img/neural-style-1.png)
![$150 \times 225$尺寸的合成图像](../img/neural-style-1.png)

为了得到更加清晰的合成图像,下面我们在更大的$300 \times 450$尺寸上训练。我们将图9.14的高和宽放大2倍,以初始化更大尺寸的合成图像。

Expand All @@ -257,7 +257,7 @@ d2l.plt.imsave('../img/neural-style-2.png', postprocess(output).asnumpy())

可以看到,由于图像尺寸更大,每一次迭代需要花费更多的时间。从训练得到的图9.15中可以看到,此时的合成图像由于尺寸更大,保留了更多的细节。合成图像里面不仅有大块的类似样式图像的油画色彩块,色彩块中甚至出现了细微的纹理。

![$300 \times 450$尺寸的合成图像](../img/neural-style-2.png)
![$300 \times 450$尺寸的合成图像](../img/neural-style-2.png)


## 小结
Expand Down
Loading

0 comments on commit d62e686

Please sign in to comment.