From 39f837c32aae806dd4bd8ac508c90503a794fbc3 Mon Sep 17 00:00:00 2001 From: xiaotinghe Date: Fri, 5 Mar 2021 01:06:13 +0800 Subject: [PATCH] ch1, ch2 (#681) --- chapter_installation/index.md | 37 ++++++++++++---------- chapter_notation/index.md | 8 ++--- chapter_preliminaries/autograd.md | 6 ++-- chapter_preliminaries/calculus.md | 38 +++++++++++----------- chapter_preliminaries/index.md | 6 ++-- chapter_preliminaries/linear-algebra.md | 14 ++++----- chapter_preliminaries/lookup-api.md | 10 +++--- chapter_preliminaries/ndarray.md | 42 ++++++++++++------------- chapter_preliminaries/pandas.md | 2 +- chapter_preliminaries/probability.md | 16 +++++----- 10 files changed, 92 insertions(+), 87 deletions(-) diff --git a/chapter_installation/index.md b/chapter_installation/index.md index 04593ce51..b3bd4699d 100644 --- a/chapter_installation/index.md +++ b/chapter_installation/index.md @@ -1,21 +1,24 @@ # 安装 :label:`chap_installation` -我们需要设置一个环境来运行 Python,Jupyter Notebook,相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。 +我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。 ## 安装 Miniconda -最简单的方法就是安装依赖 Python 3.x 的 [Miniconda](https://conda.io/en/latest/miniconda.html)。如果已安装 conda,则可以跳过以下步骤。从网站下载相应的 Miniconda sh 文件,然后使用 `sh -b` 从命令行执行安装。对于 macOS 用户: +最简单的方法就是安装依赖 Python 3.x 的 [Miniconda](https://conda.io/en/latest/miniconda.html)。如果已安装 conda,则可以跳过以下步骤。 +从网站下载相应的 Miniconda sh 文件,然后使用 `sh -b` 从命令行执行安装。 + +对于 macOS 用户: ```bash -# The file name is subject to changes +# 文件名可能会更改 sh Miniconda3-latest-MacOSX-x86_64.sh -b ``` 对于 Linux 用户: ```bash -# The file name is subject to changes +# 文件名可能会更改 sh Miniconda3-latest-Linux-x86_64.sh -b ``` @@ -25,7 +28,7 @@ sh Miniconda3-latest-Linux-x86_64.sh -b ~/miniconda3/bin/conda init ``` -现在关闭并重新打开当前的 shell。你应该能够创建一个新的环境,如下所示: +现在关闭并重新打开当前的 shell。你应该能用下面的命令创建一个新的环境: ```bash conda create --name d2l python=3.8 -y @@ -33,7 +36,7 @@ conda create --name d2l python=3.8 -y ## 下载 D2L Notebook -接下来,需要下载这本书的代码。你可以点击任何 HTML 页面顶部的 “Jupyter 笔记本文件” 选项卡下载,并解压代码。或者可以按照如下方式进行下载: +接下来,需要下载这本书的代码。你可以点击任何 HTML 页面顶部的 “Jupyter 记事本文件” 选项下载后解压代码。或者可以按照如下方式进行下载: ```bash mkdir d2l-zh && cd d2l-zh @@ -51,9 +54,9 @@ conda activate d2l ## 安装框架和 `d2l` 软件包 -在安装深度学习框架之前,请先检查你的计算机上是否有正确的 GPU(在标准笔记本电脑上为显示器提供电源的 GPU 不计入我们的目的)。如果要在 GPU 服务器上安装,请继续执行 :ref:`subsec_gpu` 以获取有关安装 GPU 支持版本的说明。 +在安装深度学习框架之前,请先检查你的计算机上是否有可用的 GPU(在笔记本电脑上为显示器提供输出的GPU不算)。如果要在 GPU 机器上安装,请继续在 :ref:`subsec_gpu` 获取有关安装GPU支持版本的说明。 -或者,你可以按照如下方法安装CPU版本。这将足够帮助你完成前几章,但你需要在运行更大的模型之前访问 GPU。 +或者,你可以按照如下方法安装CPU版本。这将足够帮助你完成前几章,但你需要在运行更大模型之前获取GPU。 :begin_tab:`mxnet` @@ -77,50 +80,50 @@ pip install tensorflow tensorflow-probability ``` :end_tab: -我们还安装了 `d2l` 软件包,它封装了本书中常用的函数和类。 +你还需要安装 `d2l` 软件包,它封装了本书中常用的函数和类。 ```bash # -U:将所有包升级到最新的可用版本 pip install -U d2l ``` -安装完成后,我们现在通过运行以下操作打开 Jupyter 笔记本: +安装完成后,我们通过运行以下命令打开 Jupyter 笔记本: ```bash jupyter notebook ``` -此时,你可以在 Web 浏览器中打开 (通常会自动打开)。然后我们可以运行这本书的每个部分的代码。在运行书籍代码或更新深度学习框架或 `d2l` 软件包之前,请始终执行 `conda activate d2l` 以激活运行时环境。要退出环境,请运行 `conda deactivate`。 +现在,你可以在 Web 浏览器中打开 (通常会自动打开)。然后我们可以运行这本书中每个部分的代码。在运行书籍代码、更新深度学习框架或 `d2l` 软件包之前,请始终执行 `conda activate d2l` 以激活运行时环境。要退出环境,请运行 `conda deactivate`。 ## GPU 支持 :label:`subsec_gpu` :begin_tab:`mxnet` -默认情况下,安装MXNet时不支持 GPU,以确保它在任何计算机(包括大多数笔记本电脑)上运行。本书的一部分要求或建议使用 GPU 运行。如果你的计算机具有 NVIDIA 显卡并且已安装 [CUDA](https://developer.nvidia.com/cuda-downloads),则应安装启用 GPU 的版本。如果你已经安装了仅 CPU 版本,则可能需要首先通过运行以下操作将其删除: +默认情况下,安装的MXNet不支持GPU。这可以确保它在任何计算机(包括大多数笔记本电脑)上运行。本书的部分内容建议或要求使用 GPU 运行。如果你的计算机带有 NVIDIA 显卡并且已安装 [CUDA](https://developer.nvidia.com/cuda-downloads),则应安装支持 GPU 的版本。如果你已经安装了仅支持 CPU 版本,则可能需要先通过运行以下命令将其删除: ```bash pip uninstall mxnet ``` -然后,我们需要找到你安装的 CUDA 版本。你可以通过 `nvcc --version` 或 `cat /usr/local/cuda/version.txt` 查看它。假定你已安装 CUDA 10.1,则可以使用以下命令进行安装: +然后,我们需要找到安装的 CUDA 版本。你可以通过 `nvcc --version` 或 `cat /usr/local/cuda/version.txt` 查看。假设你已安装 CUDA 10.1,则可以使用以下命令进行安装: ```bash -# For Windows users +# 对于 Windows 用户: pip install mxnet-cu101==1.7.0 -f https://dist.mxnet.io/python -# For Linux and macOS users +# 对于 Linux 和 macOS 用户: pip install mxnet-cu101==1.7.0 ``` -你可以根据你的 CUDA 版本更改最后一位数字,例如:CUDA 10.0 的 `cu100` 和 CUDA 9.0 的 `cu90`。 +你可以根据你的 CUDA 版本更改最后一位数字,例如:CUDA 10.0 是 `cu100`, CUDA 9.0 是 `cu90`。 :end_tab: :begin_tab:`pytorch,tensorflow` 默认情况下,深度学习框架安装了GPU支持。 -如果你的计算机有NVIDIA GPU,并且已经安装了[CUDA](https://developer.nvidia.com/cuda-downloads),那么你应该已经设置好了。 +如果你的计算机有NVIDIA GPU,并且已经安装了[CUDA](https://developer.nvidia.com/cuda-downloads),那么你应该已经配置好了。 :end_tab: ## 练习 diff --git a/chapter_notation/index.md b/chapter_notation/index.md index aed9570e1..cddd9295f 100644 --- a/chapter_notation/index.md +++ b/chapter_notation/index.md @@ -10,14 +10,14 @@ * $\mathbf{X}$:矩阵 * $\mathsf{X}$:张量 * $\mathbf{I}$:单位矩阵 -* $x_i$, $[\mathbf{x}]_i$:向量$\mathbf{x}$的第$i$个元素 +* $x_i$, $[\mathbf{x}]_i$:向量$\mathbf{x}$第$i$个元素 * $x_{ij}$, $[\mathbf{X}]_{ij}$:矩阵$\mathbf{X}$第$i$行第$j$列的元素 ## 集合论 * $\mathcal{X}$: 集合 -* $\mathbb{Z}$: 整数的集合 -* $\mathbb{R}$ 实数的集合 +* $\mathbb{Z}$: 整数集合 +* $\mathbb{R}$ 实数集合 * $\mathbb{R}^n$: $n$维实数向量 * $\mathbb{R}^{a\times b}$: 包含$a$行和$b$列的实数矩阵 * $\mathcal{A}\cup\mathcal{B}$: 集合$\mathcal{A}$和$\mathcal{B}$的并集 @@ -47,7 +47,7 @@ * $\frac{dy}{dx}$:$y$关于$x$的导数 * $\frac{\partial y}{\partial x}$:$y$关于$x$的偏导数 * $\nabla_{\mathbf{x}} y$:$y$关于$\mathbf{x}$的梯度 -* $\int_a^b f(x) \;dx$: $f$从$a$到$b$关于$x$的定积分 +* $\int_a^b f(x) \;dx$: $f$在$a$到$b$区间上关于$x$的定积分 * $\int f(x) \;dx$: $f$关于$x$的不定积分 ## 概率与信息论 diff --git a/chapter_preliminaries/autograd.md b/chapter_preliminaries/autograd.md index ae652f099..e7a2db515 100644 --- a/chapter_preliminaries/autograd.md +++ b/chapter_preliminaries/autograd.md @@ -3,7 +3,7 @@ 正如我们在 :numref:`sec_calculus` 中所说的那样,求导是几乎所有深度学习优化算法的关键步骤。虽然求导的计算很简单,只需要一些基本的微积分,但对于复杂的模型,手工进行更新是一件很痛苦的事情(而且经常容易出错)。 -深度学习框架通过自动计算导数,即 *自动求导*(automatic differentiation),来加快这项工作。实际中,根据我们设计的模型,系统会构建一个 *计算图*(computational graph),来跟踪数据通过若干操作组合起来产生输出。自动求导使系统能够随后反向传播梯度。 +深度学习框架通过自动计算导数,即 *自动求导* (automatic differentiation),来加快这项工作。实际中,根据我们设计的模型,系统会构建一个 *计算图* (computational graph),来跟踪数据通过若干操作组合起来产生输出。自动求导使系统能够随后反向传播梯度。 这里,*反向传播*(backpropagate)只是意味着跟踪整个计算图,填充关于每个参数的偏导数。 @@ -40,9 +40,9 @@ x ```{.python .input} -# 我们通过调用attach_grad`来为一个张量的梯度分配内存 +# 我们通过调用`attach_grad`来为一个张量的梯度分配内存 x.attach_grad() -# 在我们计算关于`x`的梯度后,我们将能够通过' grad '属性访问它,它的值被初始化为0 +# 在我们计算关于`x`的梯度后,我们将能够通过'grad'属性访问它,它的值被初始化为0 x.grad ``` diff --git a/chapter_preliminaries/calculus.md b/chapter_preliminaries/calculus.md index 1b5c5cd3c..bd5a39fe1 100644 --- a/chapter_preliminaries/calculus.md +++ b/chapter_preliminaries/calculus.md @@ -1,15 +1,15 @@ # 微分 :label:`sec_calculus` -直到至少2500年前,古希腊人把一个多边形分成三角形,并把它们的面积相加,才找到计算多边形面积的方法。 -为了求出曲线形状(比如圆)的面积,古希腊人在这样的形状上刻内接多边形。如 :numref:`fig_circle_area` 所示,内接多边形的等长边越多,就越接近圆。这个过程也被称为 *穷举法*(method of exhaustion)。 +在2500年前,古希腊人把一个多边形分成三角形,并把它们的面积相加,才找到计算多边形面积的方法。 +为了求出曲线形状(比如圆)的面积,古希腊人在这样的形状上刻内接多边形。如 :numref:`fig_circle_area` 所示,内接多边形的等长边越多,就越接近圆。这个过程也被称为 *逼近法*(method of exhaustion)。 -![用穷举法求圆的面积。](../img/polygon-circle.svg) +![用逼近法求圆的面积。](../img/polygon-circle.svg) :label:`fig_circle_area` -事实上,穷举法就是 *积分*(integral calculus)的起源,我们将在 :numref:`sec_integral_calculus` 中详细描述。2000 多年后,微积分的另一支,*微分*(differential calculus),被发明出来。在微分学最重要的应用中,优化问题考虑如何把事情做到最好。正如在 :numref:`subsec_norms_and_objectives` 中讨论的那样,这种问题在深度学习中是无处不在的。 +事实上,逼近法就是 *积分*(integral calculus)的起源,我们将在 :numref:`sec_integral_calculus` 中详细描述。2000 多年后,微积分的另一支,*微分*(differential calculus),被发明出来。在微分学最重要的应用是优化问题,即考虑如何把事情做到最好。正如在 :numref:`subsec_norms_and_objectives` 中讨论的那样,这种问题在深度学习中是无处不在的。 -在深度学习中,我们“训练”模型,不断更新它们,使它们在看到越来越多的数据时变得越来越好。通常情况下,变得更好意味着最小化一个 *损失函数*(loss function),即一个衡量“我们的模型有多*糟糕*”这个问题的分数。这个问题比看上去要微妙得多。最终,我们真正关心的是生成一个能够在我们从未见过的数据上表现良好的模型。但我们只能将模型与我们实际能看到的数据相拟合。因此,我们可以将拟合模型的任务分解为两个关键问题:i) *优化*(optimization):用模型拟合观测数据的过程;ii) *泛化*(generalization):数学原理和实践者的智慧,能够指导我们生成出有效性超出用于训练的数据集本身的模型。 +在深度学习中,我们“训练”模型,不断更新它们,使它们在看到越来越多的数据时变得越来越好。通常情况下,变得更好意味着最小化一个 *损失函数*(loss function),即一个衡量“我们的模型有多糟糕”这个问题的分数。这个问题比看上去要微妙得多。最终,我们真正关心的是生成一个能够在我们从未见过的数据上表现良好的模型。但我们只能将模型与我们实际能看到的数据相拟合。因此,我们可以将拟合模型的任务分解为两个关键问题:(1)*优化*(optimization):用模型拟合观测数据的过程;(2)*泛化*(generalization):数学原理和实践者的智慧,能够指导我们生成出有效性超出用于训练的数据集本身的模型。 为了帮助你在后面的章节中更好地理解优化问题和方法,这里我们对深度学习中常用的微分知识提供了一个非常简短的入门教程。 @@ -81,13 +81,15 @@ $$f'(x) = y' = \frac{dy}{dx} = \frac{df}{dx} = \frac{d}{dx} f(x) = Df(x) = D_x f 其中符号 $\frac{d}{dx}$ 和 $D$ 是*微分运算符*,表示*微分*操作。我们可以使用以下规则来对常见函数求微分: -* $DC = 0$ ($C$ 是一个常数); -* $Dx^n = nx^{n-1}$ (*幂律*(power rule), $n$是任意实数); -* $De^x = e^x$, -* $D\ln(x) = 1/x.$ +* $DC = 0$ ($C$ 是一个常数) +* $Dx^n = nx^{n-1}$ (*幂律*(power rule), $n$是任意实数) +* $De^x = e^x$ +* $D\ln(x) = 1/x$ 为了微分一个由一些简单函数(如上面的常见函数)组成的函数,下面的法则使用起来很方便。 -假设函数$f$和$g$都是可微的,$C$是一个常数,我们有*常数相乘法则* +假设函数$f$和$g$都是可微的,$C$是一个常数,我们有: + +*常数相乘法则* $$\frac{d}{dx} [Cf(x)] = C \frac{d}{dx} f(x),$$ *加法法则* @@ -104,11 +106,11 @@ $$\frac{d}{dx} \left[\frac{f(x)}{g(x)}\right] = \frac{g(x) \frac{d}{dx} [f(x)] - 现在我们可以应用上述几个法则来计算 $u' = f'(x) = 3 \frac{d}{dx} x^2-4\frac{d}{dx}x = 6x-4$。因此,通过令 $x = 1$ ,我们有 $u' = 2$ :这一点得到了我们在本节前面的实验的支持,在这个实验中,数值结果接近$2$。当 $x=1$ 时,此导数也是曲线 $u = f(x)$ 切线的斜率。 -[**为了对导数的这种解释进行可视化,**]我们将使用 `matplotlib`,一个Python中流行的绘图库。要配置`matplotlib`生成图形的属性,我们需要(**定义几个函数**)。 +[**为了对导数的这种解释进行可视化,**]我们将使用 `matplotlib`,这是一个Python中流行的绘图库。要配置`matplotlib`生成图形的属性,我们需要(**定义几个函数**)。 在下面,`use_svg_display` 函数指定 `matplotlib` 软件包输出svg图表以获得更清晰的图像。 注意,注释`#@save`是一个特殊的标记,会将对应的函数、类或语句保存在`d2l`包中 -因此,以后无需重新定义就可以直接调用它们(例如,`d2l.use\u svg\u display()`)。 +因此,以后无需重新定义就可以直接调用它们(例如,`d2l.use_svg_display()`)。 ```{.python .input} #@tab all @@ -117,7 +119,7 @@ def use_svg_display(): #@save display.set_matplotlib_formats('svg') ``` -我们定义 `set_figsize` 函数来指定图表大小。注意,这里我们直接使用 `d2l.plt`,因为导入语句 `from matplotlib import pyplot as plt` 已在`d2l` 软件包的开头被标记为保存。 +我们定义 `set_figsize` 函数来设置图表大小。注意,这里我们直接使用 `d2l.plt`,因为导入语句 `from matplotlib import pyplot as plt` 已在前言中标记为保存到`d2l` 包中。 ```{.python .input} #@tab all @@ -194,11 +196,11 @@ plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)']) 到目前为止,我们只讨论了仅含一个变量的函数的微分。在深度学习中,函数通常依赖于许多变量。因此,我们需要将微分的思想推广到这些 *多元函数* (multivariate function)上。 -设 $y = f(x_1, x_2, \ldots, x_n)$ 是一个具有 $n$ 个变量的函数。$y$ 相对于第$i^\mathrm{th}$ 个参数$x_i$*偏导数*(partial derivative)为: +设 $y = f(x_1, x_2, \ldots, x_n)$ 是一个具有 $n$ 个变量的函数。$y$ 关于第$i$ 个参数$x_i$的*偏导数*(partial derivative)为: $$ \frac{\partial y}{\partial x_i} = \lim_{h \rightarrow 0} \frac{f(x_1, \ldots, x_{i-1}, x_i+h, x_{i+1}, \ldots, x_n) - f(x_1, \ldots, x_i, \ldots, x_n)}{h}.$$ -为了计算 $\frac{\partial y}{\partial x_i}$,我们可以简单地将 $x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n$ 看作常数,并计算 $y$相对于$x_i$ 的导数。对于偏导数的表示,以下是等价的: +为了计算 $\frac{\partial y}{\partial x_i}$,我们可以简单地将 $x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n$ 看作常数,并计算 $y$关于$x_i$ 的导数。对于偏导数的表示,以下是等价的: $$\frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f.$$ @@ -213,9 +215,9 @@ $$\nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\parti 假设$\mathbf{x}$为$n$维向量,在微分多元函数时经常使用以下规则: -* 对于所有$\mathbf{A} \in \mathbb{R}^{m \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top$, -* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times m}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A}$, -* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x}$, +* 对于所有$\mathbf{A} \in \mathbb{R}^{m \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top$ +* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times m}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A}$ +* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x}$ * $\nabla_{\mathbf{x}} \|\mathbf{x} \|^2 = \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{x} = 2\mathbf{x}$ 同样,对于任何矩阵 $\mathbf{X}$,我们都有 $\nabla_{\mathbf{X}} \|\mathbf{X} \|_F^2 = 2\mathbf{X}$。正如我们之后将看到的,梯度对于设计深度学习中的优化算法有很大用处。 diff --git a/chapter_preliminaries/index.md b/chapter_preliminaries/index.md index c43ea3546..7637b8613 100644 --- a/chapter_preliminaries/index.md +++ b/chapter_preliminaries/index.md @@ -1,15 +1,15 @@ # 预备知识 :label:`chap_preliminaries` -要开始深度学习课程的学习,我们需要掌握一些基本技能。所有的机器学习方法都涉及从数据中提取信息。因此,我们首先将学习存储、操作和预处理数据的实用技能。 +要开始深度学习课程的学习,我们需要掌握一些基本技能。所有的机器学习方法都涉及从数据中提取信息。因此,我们首先将学习一些实用技能,包括存储、操作和预处理数据。 机器学习通常需要处理大型数据集。我们可以将数据集视为表,其中表的行对应于样本,列对应于属性。线性代数为我们提供了一些用来处理表格数据的技术。我们不会太深入细节,而是将重点放在矩阵运算的基本原理及其实现上。 -深度学习是关于优化的。我们有一个带有参数的模型,我们想要找到那些能拟合数据最好的模型。在算法的每个步骤中,决定以何种方式移动每个参数需要一点微积分知识。在本节中将简要介绍这些知识。幸运的是,`autograd`包会自动为我们计算微分,在本节中我们也将介绍它。 +深度学习是关于优化的。我们有一个带有参数的模型,我们想要找到那些能拟合数据的最好模型。在算法的每个步骤中,决定以何种方式调整参数需要一点微积分知识。在本节中将简要介绍这些知识。幸运的是,`autograd`包会自动为我们计算微分,在本节中我们也将介绍它。 接下来,机器学习涉及如何做出预测:给定我们观察到的信息,某些未知属性的可能值是多少?要在不确定的情况下进行严格的推理,我们需要引用概率语言。 -最后,官方文档提供了本书之外的大量描述和示例。作为本章的结束,我们将向你展示如何在文档中查找所需信息。 +最后,官方文档提供了本书之外的大量描述和示例。在本章的结尾,我们将向你展示如何在文档中查找所需信息。 这本书将对数学的要求保持在正确理解深度学习所需的最低限度。然而,这并不意味着这本书是没有数学的。 因此,本章提供了基本且常用的数学知识的快速介绍,使任何人能够至少理解书中的大部分数学内容。如果你希望理解全部的数学内容,进一步学习[数学的在线附录](https://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html)就足够了。 diff --git a/chapter_preliminaries/linear-algebra.md b/chapter_preliminaries/linear-algebra.md index 220283b1a..00403ab69 100644 --- a/chapter_preliminaries/linear-algebra.md +++ b/chapter_preliminaries/linear-algebra.md @@ -6,9 +6,9 @@ ## 标量 -如果你从来没有学过线性代数或机器学习,那么你过去的数学经历可能是一次只想一个数字。而且,如果你曾经报销过发票,或者在餐厅支付餐费,那么你已经知道如何做一些基本的事情,如在数字间相加或相乘。例如,北京的温度为 $52$ 华氏度(除了摄氏度外,另一种温度刻度)。严格来说,我们称仅包含一个数值的叫 *标量* (scalar)。如果要将此华氏度值转换为更常用的摄氏度,则可以计算表达式 $c = \frac{5}{9}(f - 32)$,并将 $f$ 赋为 $52$。在此等式中,每一项($5$、$9$ 和 $32$)都是标量值。符号 $c$ 和 $f$ 称为 *变量*(variables),它们表示未知的标量值。 +如果你从来没有学过线性代数或机器学习,那么你过去的数学经历可能是一次只想一个数字。如果你曾经报销过发票,或者在餐厅支付餐费,那么你已经知道如何做一些基本的事情,比如在数字间相加或相乘。例如,北京的温度为 $52$ 华氏度(除了摄氏度外,另一种温度刻度)。严格来说,我们称仅包含一个数值的叫 *标量* (scalar)。如果要将此华氏度值转换为更常用的摄氏度,则可以计算表达式 $c = \frac{5}{9}(f - 32)$,并将 $f$ 赋为 $52$。在此等式中,每一项($5$、$9$ 和 $32$)都是标量值。符号 $c$ 和 $f$ 称为 *变量*(variables),它们表示未知的标量值。 -在本书中,我们采用了数学表示法,其中标量变量由普通小写字母表示(例如,$x$、$y$ 和 $z$)。我们用 $\mathbb{R}$ 表示所有(连续)*实数* 标量的空间。为了方便,我们之后将严格定义 *空间*(space)是什么,但现在只要记住,表达式 $x \in \mathbb{R}$ 是表示$x$是一个实值标量的严格形式。符号 $\in$ 称为 “属于”,它表示“是集合中的成员”。我们可以用 $x, y \in \{0, 1\}$ 来表明 $x$ 和 $y$ 是值只能为 $0$ 或 $1$的数字。 +在本书中,我们采用了数学表示法,其中标量变量由普通小写字母表示(例如,$x$、$y$ 和 $z$)。我们用 $\mathbb{R}$ 表示所有(连续)*实数* 标量的空间。为了方便,我们之后将严格定义 *空间*(space)是什么,但现在只要记住,表达式 $x \in \mathbb{R}$ 是表示$x$是一个实值标量的正式形式。符号 $\in$ 称为 “属于”,它表示“是集合中的成员”。我们可以用 $x, y \in \{0, 1\}$ 来表明 $x$ 和 $y$ 是值只能为 $0$ 或 $1$的数字。 (**标量由只有一个元素的张量表示**)。在下面的代码中,我们实例化两个标量,并使用它们执行一些熟悉的算术运算,即加法,乘法,除法和指数。 @@ -44,7 +44,7 @@ x + y, x * y, x / y, x**y ## 向量 -[**你可以将向量视为标量值列表**]。我们将这些值称为向量的 *元素*(elements)或*分量*(components)。当我们的向量表示数据集中的样本时,它们的值具有一定的现实意义。例如,如果我们正在训练一个模型来预测贷款违约风险,我们可能会将每个申请人与一个向量相关联,其分量与其收入、工作年限、过往违约次数和其他因素相对应。如果我们正在研究医院患者可能面临的心脏病发作风险,我们可能会用一个向量来表示每个患者,其分量为最近的生命体征、胆固醇水平、每天运动时间等。在数学表示法中,我们通常将向量表示为粗体、小写的符号(例如,$\mathbf{x}$、$\mathbf{y}$和$\mathbf{z})$)。 +[**你可以将向量视为标量值组成的列表**]。我们将这些标量值称为向量的 *元素*(elements)或*分量*(components)。当我们的向量表示数据集中的样本时,它们的值具有一定的现实意义。例如,如果我们正在训练一个模型来预测贷款违约风险,我们可能会将每个申请人与一个向量相关联,其分量与其收入、工作年限、过往违约次数和其他因素相对应。如果我们正在研究医院患者可能面临的心脏病发作风险,我们可能会用一个向量来表示每个患者,其分量为最近的生命体征、胆固醇水平、每天运动时间等。在数学表示法中,我们通常将向量记为粗体、小写的符号(例如,$\mathbf{x}$、$\mathbf{y}$和$\mathbf{z})$)。 我们通过一维张量处理向量。一般来说,张量可以具有任意长度,取决于机器的内存限制。 @@ -65,7 +65,7 @@ x = tf.range(4) x ``` -我们可以使用下标来引用向量的任一元素。例如,我们可以通过 $x_i$ 来引用第 $i$ 个元素。注意,元素 $x_i$ 是一个标量,所以我们在引用它时不会加粗。大量文献认为列向量是向量的默认方向,在本书中也是如此。在数学中,向量 $\mathbf{x}$ 可以写为 +我们可以使用下标来引用向量的任一元素。例如,我们可以通过 $x_i$ 来引用第 $i$ 个元素。注意,元素 $x_i$ 是一个标量,所以我们在引用它时不会加粗。大量文献认为列向量是向量的默认方向,在本书中也是如此。在数学中,向量 $\mathbf{x}$ 可以写为: $$\mathbf{x} =\begin{bmatrix}x_{1} \\x_{2} \\ \vdots \\x_{n}\end{bmatrix},$$ :eqlabel:`eq_vec_def` @@ -122,7 +122,7 @@ x.shape x.shape ``` -请注意,“维度”(dimension)这个词在不同上下文时往往会有不同的含义,这往往会使人感到困惑。为了清楚起见,我们在此明确一下。*向量*或*轴*的维度被用来表示*向量*或*轴*的长度,即向量或轴的元素数量。然而,张量的维度用来表示张量具有的轴数。在这个意义上,张量的某个轴的维数就是这个轴的长度。 +请注意,*维度*(dimension)这个词在不同上下文时往往会有不同的含义,这经常会使人感到困惑。为了清楚起见,我们在此明确一下。*向量*或*轴*的维度被用来表示*向量*或*轴*的长度,即向量或轴的元素数量。然而,张量的维度用来表示张量具有的轴数。在这个意义上,张量的某个轴的维数就是这个轴的长度。 ## 矩阵 @@ -219,7 +219,7 @@ B == B.T B == tf.transpose(B) ``` -矩阵是有用的数据结构:它们允许我们组织具有不同变化模式的数据。例如,我们矩阵中的行可能对应于不同的房屋(数据样本),而列可能对应于不同的属性。如果你曾经使用过电子表格软件或已阅读过 :numref:`sec_pandas`,这应该听起来很熟悉。因此,尽管单个向量的默认方向是列向量,但在表示表格数据集的矩阵中,将每个数据样本视为矩阵中的行向量更为常见。而且,我们将在后面的章节中讲到。这种约定将支持常见的深度学习实践。例如,沿着张量的最外轴,我们可以访问或遍历小批量的数据样本。如果不存在小批量,我们也可以只访问数据样本。 +矩阵是有用的数据结构:它们允许我们组织具有不同变化模式的数据。例如,我们矩阵中的行可能对应于不同的房屋(数据样本),而列可能对应于不同的属性。如果你曾经使用过电子表格软件或已阅读过 :numref:`sec_pandas`,这应该听起来很熟悉。因此,尽管单个向量的默认方向是列向量,但在表示表格数据集的矩阵中,将每个数据样本作为矩阵中的行向量更为常见。我们将在后面的章节中讲到这点。这种约定将支持常见的深度学习实践。例如,沿着张量的最外轴,我们可以访问或遍历小批量的数据样本。如果不存在小批量,我们也可以只访问数据样本。 ## 张量 @@ -788,7 +788,7 @@ tf.norm(tf.ones((4, 9))) 1. 运行 `A / A.sum(axis=1)`,看看会发生什么。你能分析原因吗? 1. 当你在曼哈顿的两点之间旅行时,你需要在坐标上走多远,也就是说,就大街和街道而言?你能斜着走吗? 1. 考虑一个具有形状(2, 3, 4)的张量,在轴 0,1,2 上的求和输出是什么形状? -1. 向 `linalg.norm` 函数提供 3 个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算什么? +1. 向 `linalg.norm` 函数提供 3 个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算得到什么? :begin_tab:`mxnet` [Discussions](https://discuss.d2l.ai/t/1752) diff --git a/chapter_preliminaries/lookup-api.md b/chapter_preliminaries/lookup-api.md index 63fab7efa..ebd043022 100644 --- a/chapter_preliminaries/lookup-api.md +++ b/chapter_preliminaries/lookup-api.md @@ -1,14 +1,14 @@ # 查阅文档 :begin_tab:`mxnet` -由于这本书篇幅的限制,我们不可能介绍每一个 MXNet 函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看MXNet API 的指导。 +由于这本书篇幅的限制,我们不可能介绍每一个 MXNet 函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看MXNet API 的指导。 :end_tab: :begin_tab:`pytorch` -由于本书篇幅的限制,我们不可能介绍每一个PyTorch函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看PyTorch API的指导。 +由于本书篇幅的限制,我们不可能介绍每一个PyTorch函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看PyTorch API的指导。 :end_tab: :begin_tab:`tensorflow` -由于本书篇幅的限制,我们不可能介绍每一个TensorFlow函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查TensorFlow API的指导。 +由于本书篇幅的限制,我们不可能介绍每一个TensorFlow函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查TensorFlow API的指导。 :end_tab: ## 查找模块中的所有函数和类 @@ -32,7 +32,7 @@ import tensorflow as tf print(dir(tf.random)) ``` -通常,我们可以忽略以 `__` 开始和结束的函数(Python 中的特殊对象)或以单个 `_` 开始的函数(通常是内部函数)。根据剩余的函数名或属性名,我们可能会猜测这个模块提供了各种生成随机数的方法,包括从均匀分布 (`uniform`)、正态分布 (`normal`) 和多项分布 (`multinomial`) 中采样。 +通常,我们可以忽略以 `__` 开始和结束的函数(Python 中的特殊对象)或以单个 `_` 开始的函数(通常是内部函数)。根据剩余的函数名或属性名,我们可能会猜测这个模块提供了各种生成随机数的方法,包括从均匀分布(`uniform`)、正态分布 (`normal`)和多项分布(`multinomial`)中采样。 ## 查找特定函数和类的用法 @@ -68,7 +68,7 @@ torch.ones(4) tf.ones(4) ``` -在Jupyter记事本中,我们可以使用 `?`在另一个窗口中显示文档。例如,`list?`将创建与`help(list)` 几乎相同的内容,并在新的浏览器窗口中显示它。此外,如果我们使用两个问号,如 `list??`,将显示实现该函数的 Python 代码。 +在Jupyter记事本中,我们可以使用 `?` 在另一个窗口中显示文档。例如,`list?`将创建与`help(list)` 几乎相同的内容,并在新的浏览器窗口中显示它。此外,如果我们使用两个问号,如 `list??`,将显示实现该函数的 Python 代码。 ## 小结 diff --git a/chapter_preliminaries/ndarray.md b/chapter_preliminaries/ndarray.md index 729960f99..d26945761 100644 --- a/chapter_preliminaries/ndarray.md +++ b/chapter_preliminaries/ndarray.md @@ -1,14 +1,14 @@ # 数据操作 :label:`sec_ndarray` -为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要进行两件重要的事情:(1)获取数据;(2)在数据进入计算机后对其进行处理。如果没有某种方法来存储数据,那么获取数据是没有意义的。我们先尝试一个合成数据。首先,我们介绍$n$维数组,也称为 *张量*(tensor)。 +为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要做两件重要的事情:(1)获取数据;(2)在数据读入计算机后对其进行处理。如果没有某种方法来存储数据,那么获取数据是没有意义的。我们先尝试一个合成数据。首先,我们介绍$n$维数组,也称为 *张量*(tensor)。 -如果你使用过 Python 中最广泛使用的科学计算包 NumPy,那么你会感觉很熟悉本部分。无论你使用哪个框架,它的 *张量类*(在 MXNet 中为 `ndarray`,在 PyTorch 和TensorFlow中为 `Tensor`)与 Numpy 的 `ndarray` 类似,但都比Numpy 的 `ndarray`多一些重要功能。首先,GPU 很好地支持加速计算,而 NumPy 仅支持 CPU 计算。其次,张量类支持自动微分。这些功能使得张量类更适合深度学习。除非另有说明,在整本书中所说的张量指的是张量类的实例。 +如果你使用过 Python 中最广泛使用的科学计算包 NumPy,那么你会感觉怼本部分很熟悉。无论你使用哪个框架,它的 *张量类*(在 MXNet 中为 `ndarray`,在 PyTorch 和TensorFlow中为 `Tensor`)与 Numpy 的 `ndarray` 类似,但都比Numpy 的 `ndarray`多一些重要功能。首先,GPU 很好地支持加速计算,而 NumPy 仅支持 CPU 计算。其次,张量类支持自动微分。这些功能使得张量类更适合深度学习。除非另有说明,在整本书中所说的张量指的是张量类的实例。 ## 入门 -在本节中,我们的目标是帮助你开始了解并运行一些基本数值计算工具。在你阅读本书的过程中,将利用到这些工具。如果你很难理解一些数学概念或库函数,请不要担心。下面的章节将通过一些实际的例子来回顾这些内容。如果你已经有了一些背景知识,想要深入学习数学内容,可以就跳过这一节。 +在本节中,我们的目标是帮助你开始了解并运行一些基本数值计算工具。在你阅读本书的过程中,将用到这些工具。如果你很难理解一些数学概念或库函数,请不要担心。在后面的章节将通过一些实际的例子来回顾这些内容。如果你已经有了一些背景知识,想要深入学习数学内容,可以就跳过这一节。 :begin_tab:`mxnet` 首先,我们从MXNet导入 `np`(`numpy`)模块和 `npx`(`numpy_extension`)模块。`np` 模块包含了 NumPy 支持的函数。而 `npx` 模块包含了一组扩展函数,用来在类似 NumPy 的环境中实现深度学习开发。当使用张量时,我们几乎总是会调用 `set_np` 函数:这是为了兼容 MXNet 其他的张量处理组件。 @@ -67,8 +67,8 @@ x x.shape ``` -如果我们只想知道张量中元素的总数,即所有形状元素的乘积,我们可以检查它的大小(size)。 -因为这里在处理的是一个向量,所以它的`shape`与它的大小相同。 +如果我们只想知道张量中元素的总数,即形状的所有元素乘积,我们可以检查它的大小(size)。 +因为这里在处理的是一个向量,所以它的 `shape` 与它的 `size` 相同。 ```{.python .input} x.size @@ -85,7 +85,7 @@ tf.size(x) ``` [**要改变一个张量的形状而不改变元素数量和元素值,我们可以调用 `reshape` 函数。**] -例如,我们可以把张量 `x` 从形状为 (12,) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。 +例如,我们可以把张量 `x` 从形状为 (12, ) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。 ```{.python .input} @@ -137,7 +137,7 @@ torch.ones((2, 3, 4)) tf.ones((2, 3, 4)) ``` -有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为(3, 4)的张量。其中的每个元素都从均值为0,标准差为1的标准高斯(正态)分布中随机采样。 +有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为 (3, 4) 的张量。其中的每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样。 ```{.python .input} @@ -171,11 +171,11 @@ torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) tf.constant([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) ``` -## 操作 +## 运算 -这本书不是关于软件工程的。我们的兴趣不仅仅限于从数组读取和写入数据。我们想在这些数组上执行数学运算。一些最简单且最有用的操作是 *逐元素*(elementwise) 操作。它们将标准标量运算应用于数组的每个元素。对于将两个数组作为输入的函数,逐元素运算将二元运算符应用于两个数组中的每对位置对应的元素。我们可以基于任何从标量到标量的函数来创建逐元素函数。 +这本书不是关于软件工程的。我们的兴趣不仅仅限于从数组读取和写入数据。我们想在这些数组上执行数学运算。一些最简单且最有用的操作是 *逐元素*(elementwise) 操作。它们将标准标量运算符应用于数组的每个元素。对于将两个数组作为输入的函数,逐元素运算将二元运算符应用于两个数组中的每对位置对应的元素。我们可以基于任何从标量到标量的函数来创建逐元素函数。 -在数学表示法中,我们将通过符号 $f: \mathbb{R} \rightarrow \mathbb{R}$ 来表示 *一元* 标量运算符(只接收一个输入)。这意味着该函数从任何实数($\mathbb{R}$)映射到另一个实数。同样,我们通过符号 $f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}$ 表示 *二元* 标量运算符,这意味着该函数接收两个输入,并产生一个输出。给定同一形状的任意两个向量$\mathbf{u}$和$\mathbf{v}$ 和二元运算符 $f$,我们可以得到向量$\mathbf{c} = F(\mathbf{u},\mathbf{v})$。具体计算方法是$c_i \gets f(u_i, v_i)$ ,其中 $c_i, u_i$ 和 $v_i$ 分别是向量$\mathbf{c}, \mathbf{u}$和 $\mathbf{v}$中的元素。在这里,我们通过将标量函数升级为逐元素向量运算来生成向量值 $F: \mathbb{R}^d, \mathbb{R}^d \rightarrow \mathbb{R}^d$。 +在数学表示法中,我们将通过符号 $f: \mathbb{R} \rightarrow \mathbb{R}$ 来表示 *一元* 标量运算符(只接收一个输入)。这意味着该函数从任何实数($\mathbb{R}$)映射到另一个实数。同样,我们通过符号 $f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}$ 表示 *二元* 标量运算符,这意味着该函数接收两个输入,并产生一个输出。给定同一形状的任意两个向量$\mathbf{u}$和$\mathbf{v}$ 和二元运算符 $f$,我们可以得到向量$\mathbf{c} = F(\mathbf{u},\mathbf{v})$。具体计算方法是$c_i \gets f(u_i, v_i)$ ,其中 $c_i$、u_i$ 和 $v_i$ 分别是向量$\mathbf{c}$、$\mathbf{u}$ 和 $\mathbf{v}$中的元素。在这里,我们通过将标量函数升级为逐元素向量运算来生成向量值 $F: \mathbb{R}^d, \mathbb{R}^d \rightarrow \mathbb{R}^d$。 对于任意具有相同形状的张量,[**常见的标准算术运算符(`+`、`-`、`*`、`/` 和 `**`)都可以被升级为逐元素运算**]。我们可以在同一形状的任意两个张量上调用逐元素操作。在下面的例子中,我们使用逗号来表示一个具有5个元素的元组,其中每个元素都是逐元素操作的结果。 @@ -265,9 +265,9 @@ tf.reduce_sum(X) ## 广播机制 :label:`subsec_broadcasting` -在上面的部分中,我们看到了如何在相同形状的两个张量上执行逐元素操作。在某些情况下,[**即使形状不同,我们仍然可以通过调用 *广播机制*(broadcasting mechanism) 来执行逐元素操作**]。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行逐元素操作。 +在上面的部分中,我们看到了如何在相同形状的两个张量上执行逐元素操作。在某些情况下,[**即使形状不同,我们仍然可以通过调用 *广播机制* (broadcasting mechanism) 来执行逐元素操作**]。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行逐元素操作。 -在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下样本: +在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下例子: ```{.python .input} @@ -301,7 +301,7 @@ a + b 就像在任何其他 Python 数组中一样,张量中的元素可以通过索引访问。与任何 Python 数组一样:第一个元素的索引是 0;可以指定范围以包含第一个元素和最后一个之前的元素。与标准 Python 列表一样,我们可以通过使用负索引根据元素到列表尾部的相对位置访问元素。 -因此,我[**可以用`[-1]` 选择最后一个元素,可以用`[1:3]` 选择第二个元素和第三个元素**],如下所示: +因此,我们[**可以用 `[-1]` 选择最后一个元素,可以用 `[1:3]` 选择第二个和第三个元素**],如下所示: ```{.python .input} #@tab all @@ -309,7 +309,7 @@ X[-1], X[1:3] ``` :begin_tab:`mxnet, pytorch` -[**除读取之外,我们还可以通过指定索引来将元素写入矩阵。**] +[**除读取外,我们还可以通过指定索引来将元素写入矩阵。**] :end_tab: :begin_tab:`tensorflow` @@ -332,7 +332,7 @@ X_var ``` 如果我们想[**为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。**] -例如,`[0:2, :]` 访问第1行和第2行,其中 `:` 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。 +例如,`[0:2, :]` 访问第1行和第2行,其中 “:” 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。 ```{.python .input} #@tab mxnet, pytorch @@ -360,14 +360,14 @@ Y = Y + X id(Y) == before ``` -这可能是不可取的,原因有两个。首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。 +这可能是不可取的,原因有两个:首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。 :begin_tab:`mxnet, pytorch` -幸运的是,(**执行原地操作**)非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 `Y[:] = `。为了说明这个概念,我们首先创建一个新的矩阵 `Z`,其形状与另一个 `Y` 相同,使用 `zeros_like` 来分配一个全$0$的块。 +幸运的是,(**执行原地操作**)非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 `Y[:] = `。为了说明这一点,我们首先创建一个新的矩阵 `Z`,其形状与另一个 `Y` 相同,使用 `zeros_like` 来分配一个全$0$的块。 :end_tab: :begin_tab:`tensorflow` -`Variables` 是TensorFlow中的可变容器。它们提供了一种存储模型参数的方法。我们可以通过`assign`将一个操作的结果分配给一个 `Variable`。为了说明这个概念,我们创建了一个与另一个张量 `Y` 相同的形状的 `Z`,使用 `zeros_like` 来分配一个全$0$的块。 +`Variables` 是TensorFlow中的可变容器。它们提供了一种存储模型参数的方法。我们可以通过`assign`将一个操作的结果分配给一个 `Variable`。为了说明这一点,我们创建了一个与另一个张量 `Y` 相同的形状的 `Z`,使用 `zeros_like` 来分配一个全$0$的块。 :end_tab: ```{.python .input} @@ -400,7 +400,7 @@ print('id(Z):', id(Z)) :begin_tab:`tensorflow` 即使你将状态持久存储在 `Variable` 中,你也可能希望避免为不是模型参数的张量过度分配内存,从而进一步减少内存使用量。 -由于 TensorFlow `Tensors` 是不可变的,而且梯度不会通过 `Variable` 流动,因此 TensorFlow 没有提供一种明确的方式来原地运行单个操作。 +由于 TensorFlow的 `Tensors` 是不可变的,而且梯度不会通过 `Variable` 流动,因此 TensorFlow 没有提供一种明确的方式来原地运行单个操作。 但是,TensorFlow提供了`tf.function`修饰符,将计算封装在TensorFlow图中,该图在运行前经过编译和优化。这允许TensorFlow删除未使用的值,并复用先前分配的且不再需要的值。这样可以最大限度地减少 TensorFlow 计算的内存开销。 :end_tab: @@ -428,7 +428,7 @@ computation(X, Y) ## 转换为其他 Python 对象 [**转换为 NumPy 张量**]很容易,反之也很容易。转换后的结果不共享内存。 -这个小的不便实际上是非常重要的:当等待Python的NumPy包希望使用相同的内存块执行其他操作时,且在 CPU 或 GPU 上执行操作时,你不希望停止计算。 +这个小的不便实际上是非常重要的:当你在 CPU 或 GPU 上执行操作的时候,此时Python的NumPy包也希望使用相同的内存块执行其他操作时,你不希望停止计算。 ```{.python .input} @@ -471,7 +471,7 @@ a, a.item(), float(a), int(a) ## 小结 -* 深度学习存储和操作数据的主要接口是张量($n$维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换为其他 Python 对象。 +* 深度学习存储和操作数据的主要接口是张量($n$维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他 Python 对象。 ## 练习 diff --git a/chapter_preliminaries/pandas.md b/chapter_preliminaries/pandas.md index 982783dea..5369a47e7 100644 --- a/chapter_preliminaries/pandas.md +++ b/chapter_preliminaries/pandas.md @@ -5,7 +5,7 @@ ## 读取数据集 -举一个例子,我们首先(**创建一个人工数据集,并存储在csv(逗号分隔值)文件**) `../data/house_tiny.csv` 中。以其他格式存储的数据也可以通过类似的方式进行处理。下面的`mkdir_if_not_exist` 函数可确保目录 `../data` 存在。注意,注释 `#@save`是一个特殊的标记,该标记下面的函数、类或语句将保存在 `d2l` 软件包中,以便以后可以直接调用它们(例如 `d2l.mkdir_if_not_exist(path)`)而无需重新定义。 +举一个例子,我们首先(**创建一个人工数据集,并存储在csv(逗号分隔值)文件**) `../data/house_tiny.csv` 中。以其他格式存储的数据也可以通过类似的方式进行处理。下面的`mkdir_if_not_exist` 函数可确保目录 `../data` 存在。注意,注释 `#@save`是一个特殊的标记,该标记下方的函数、类或语句将保存在 `d2l` 软件包中,以便以后可以直接调用它们(例如 `d2l.mkdir_if_not_exist(path)`)而无需重新定义。 下面我们将数据集按行写入 csv 文件中。 diff --git a/chapter_preliminaries/probability.md b/chapter_preliminaries/probability.md index 0692152a5..fb24a5353 100644 --- a/chapter_preliminaries/probability.md +++ b/chapter_preliminaries/probability.md @@ -3,8 +3,8 @@ 在某种形式上,机器学习就是做出预测。 -根据病人的临床病史,我们可能想预测他们在下一年心脏病发作的*概率*。在异常检测中,我们可能想要评估飞机喷气发动机的一组读数是正常运行情况的*可能性*有多大。在强化学习中,我们希望智能体(agent)能在一个环境中智能地行动。这意味着我们需要考虑在每种可行的行为下获得高奖励的概率。当我们建立推荐系统时,我们也需要考虑概率。例如,*假设*我们为一家大型在线书店工作。我们可能希望估计特定用户购买特定图书的概率。为此,我们需要使用概率的语言。 -有完整的课程,专业,论文,职业,甚至院系,都致力于概率的工作。所以很自然地,我们在这部分的目标不是教授整个科目。相反,我们希望让你起步,教给你足够的知识,使你能够开始构建你的第一个深度学习模型,并让你对该主题有足够的了解,以便你可以开始自己探索它。 +根据病人的临床病史,我们可能想预测他们在下一年心脏病发作的*概率*。在异常检测中,我们可能想要评估飞机喷气发动机的一组读数是正常运行情况的*可能性*有多大。在强化学习中,我们希望智能体(agent)能在一个环境中智能地行动。这意味着我们需要考虑在每种可行的行为下获得高奖励的概率。当我们建立推荐系统时,我们也需要考虑概率。例如,假设我们为一家大型在线书店工作。我们可能希望估计特定用户购买特定图书的概率。为此,我们需要使用概率学。 +有完整的课程、专业、论文、职业、甚至院系,都致力于概率学的工作。所以很自然地,我们在这部分的目标不是教授整个科目。相反,我们希望让你起步,教给你足够的知识,使你能够开始构建你的第一个深度学习模型,并让你对该主题有足够的了解,以便你可以开始自己探索它。 在前面的章节中,我们已经提到了概率,但没有明确说明它们是什么,也没有给出具体的例子。现在让我们更认真地考虑第一个例子:根据照片区分猫和狗。这听起来可能很简单,但实际上是一个艰巨的挑战。首先,问题的难度可能取决于图像的分辨率。 @@ -14,18 +14,18 @@ 如 :numref:`fig_cat_dog` 所示,虽然人类很容易以 $160 \times 160$ 像素的分辨率识别猫和狗,但它在 $40 \times 40$ 像素上变得具有挑战性,而且在 $10 \times 10$ 像素下几乎是不可能的。换句话说,我们在很远的距离(从而降低分辨率)区分猫和狗的能力可能会接近不知情的猜测。 概率给了我们一种正式的途径来说明我们的确定性水平。 -如果我们完全肯定图像是一只猫,我们说标签$y$是"猫"的*概率*,表示为$P(y=$ "猫"$)$ 等于 $1$。如果我们没有证据表明 $y =$ “猫” 或 $y =$ “狗”,那么我们可以说这两种可能性是等可能的,把它表示为$P(y=$ "猫"$) = P(y=$ "狗"$) = 0.5$ +如果我们完全肯定图像是一只猫,我们说标签$y$是"猫"的*概率*,表示为$P(y=$ "猫"$)$ 等于 $1$。如果我们没有证据表明 $y =$ “猫” 或 $y =$ “狗”,那么我们可以说这两种可能性是等可能的,把它表示为$P(y=$ "猫"$) = P(y=$ "狗"$) = 0.5$。 如果我们有足够的信心,但不确定图像描绘的是一只猫,我们可以将概率赋值为$0.5 < P(y=$ "猫"$) < 1$。 -现在考虑第二个例子:给出一些天气监测数据,我们想预测明天北京下雨的概率。如果是夏季,如果是夏天,下雨的概率是0.5。 +现在考虑第二个例子:给出一些天气监测数据,我们想预测明天北京下雨的概率。如果是夏天,下雨的概率是0.5。 -在这两种情况下,我们有一定的兴趣价值。在这两种情况下,我们都不确定结果。但这两种情况之间有一个关键区别。在这第一种情况下,图像实际上是狗或猫,我们只是不知道哪个。在第二种情况下,结果实际上可能是一个随机的事件(如果你相信这些东西。大多数物理学家都相信)。因此,概率是一种灵活的语言,用于说明我们的确定程度,并且它可以有效地应用于广泛的上下文中。 +在这两种情况下,我们都不确定结果。但这两种情况之间有一个关键区别。在第一种情况中,图像实际上是狗或猫,我们只是不知道哪个。在第二种情况下,结果实际上可能是一个随机的事件(如果你相信这些东西。大多数物理学家都相信)。因此,概率是一种灵活的语言,用于说明我们的确定程度,并且它可以有效地应用于广泛的上下文中。 ## 基本概率论 -假设我们掷骰子,想知道看到1的几率有多大,而不是看到另一个数字。如果骰子是公平的,那么所有六个结果$\{1, \ldots, 6\}$都有相同的可能发生,因此我们将在每六次中看到一个$1$。我们正式声明$1$发生的概率为$\frac{1}{6}$。 +假设我们掷骰子,想知道看到1的几率有多大,而不是看到另一个数字。如果骰子是公平的,那么所有六个结果$\{1, \ldots, 6\}$都有相同的可能发生,因此我们将在每六次中看到一个$1$。我们可以说$1$发生的概率为$\frac{1}{6}$。 -对于我们从工厂收到的真实骰子,我们可能不知道那些比例,我们需要检查它是否有污染。调查骰子的唯一方法是多次投掷并记录结果。对于每个骰子,我们将观察到 $\{1, \ldots, 6\}$ 中的一个值。给定这些结果,我们想调查观察每个结果的概率。 +对于我们从工厂收到的真实骰子,我们可能不知道那些比例,我们需要检查它是否有污染。调查骰子的唯一方法是多次投掷并记录结果。对于每个骰子,我们将观察到 $\{1, \ldots, 6\}$ 中的一个值。给定这些结果,我们想调查每个结果的概率。 对于每个值,一种自然的方法是将单个计数的值除以投掷的总次数。 这给了我们一个给定*事件*的概率的*估计值*。*大数定律*(law of large numbers)告诉我们,随着投掷次数的增加,这个估计值会越来越接近真实的潜在概率。在深入了解这里的细节之前,让我们先试一试。 @@ -305,7 +305,7 @@ $$ ## 期望和差异 -为了概括概率分布的关键特征,我们需要一些测量方法。随机变量 $X$ 的 * 期望 *(或平均值)表示为 +为了概括概率分布的关键特征,我们需要一些测量方法。随机变量 $X$ 的 *期望*(或平均值)表示为 $$E[X] = \sum_{x} x P(X = x).$$