ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

动手学深度学习

2021-05-04 16:32:35  阅读:380  来源: 互联网

标签:tensor 元素 张量 学习 动手 PYTORCH clipboard 深度 Copy


安装
我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。

安装 Miniconda
最简单的方法就是安装依赖 Python 3.x 的 Miniconda。如果已安装 conda,则可以跳过以下步骤。 从网站下载相应的 Miniconda sh 文件,然后使用 sh -b 从命令行执行安装。

对于 macOS 用户:

文件名可能会更改

sh Miniconda3-latest-MacOSX-x86_64.sh -b
Copy to clipboard
对于 Linux 用户:

文件名可能会更改

sh Miniconda3-latest-Linux-x86_64.sh -b
Copy to clipboard
接下来,初始化终端 Shell,以便我们可以直接运行 conda。

~/miniconda3/bin/conda init
Copy to clipboard
现在关闭并重新打开当前的 shell。你应该能用下面的命令创建一个新的环境:

conda create --name d2l python=3.8 -y
Copy to clipboard
下载 D2L Notebook
接下来,需要下载这本书的代码。你可以点击任何 HTML 页面顶部的 “Jupyter 记事本文件” 选项下载后解压代码。或者可以按照如下方式进行下载:

mkdir d2l-zh && cd d2l-zh
curl https://zh-v2.d2l.ai/d2l-zh.zip -o d2l-zh.zip
unzip d2l-zh.zip && rm d2l-zh.zip
Copy to clipboard
注意:如果没有安装 unzip,则可以通过运行 sudo apt install unzip 进行安装。

现在我们要激活 d2l 环境。

conda activate d2l
Copy to clipboard
安装框架和 d2l 软件包
在安装深度学习框架之前,请先检查你的计算机上是否有可用的 GPU(在笔记本电脑上为显示器提供输出的GPU不算)。如果要在 GPU 机器上安装,请继续在 GPU 支持 获取有关安装GPU支持版本的说明。

或者,你可以按照如下方法安装CPU版本。这将足够帮助你完成前几章,但你需要在运行更大模型之前获取GPU。

MXNET
PYTORCH
TENSORFLOW
pip install mxnet==1.7.0.post1
Copy to clipboard
你还需要安装 d2l 软件包,它封装了本书中常用的函数和类。

-U:将所有包升级到最新的可用版本

pip install -U d2l
Copy to clipboard
安装完成后,我们通过运行以下命令打开 Jupyter 笔记本:

jupyter notebook
Copy to clipboard
现在,你可以在 Web 浏览器中打开 http://localhost:8888(通常会自动打开)。然后我们可以运行这本书中每个部分的代码。在运行书籍代码、更新深度学习框架或 d2l 软件包之前,请始终执行 conda activate d2l 以激活运行时环境。要退出环境,请运行 conda deactivate。

GPU 支持
MXNET
PYTORCH
TENSORFLOW
默认情况下,安装的MXNet不支持GPU。这可以确保它在任何计算机(包括大多数笔记本电脑)上运行。本书的部分内容建议或要求使用 GPU 运行。如果你的计算机带有 NVIDIA 显卡并且已安装 CUDA,则应安装支持 GPU 的版本。如果你已经安装了仅支持 CPU 版本,则可能需要先通过运行以下命令将其删除:

pip uninstall mxnet
Copy to clipboard
然后,我们需要找到安装的 CUDA 版本。你可以通过 nvcc --version 或 cat /usr/local/cuda/version.txt 查看。假设你已安装 CUDA 10.1,则可以使用以下命令进行安装:

对于 Windows 用户:

pip install mxnet-cu101==1.7.0 -f https://dist.mxnet.io/python

对于 Linux 和 macOS 用户:

pip install mxnet-cu101==1.7.0
Copy to clipboard
你可以根据你的 CUDA 版本更改最后一位数字,例如:CUDA 10.0 是 cu100, CUDA 9.0 是 cu90。
2.1. 数据操作
COLAB [PYTORCH]Open the notebook in Colab
为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要做两件重要的事情:(1)获取数据;(2)在数据读入计算机后对其进行处理。如果没有某种方法来存储数据,那么获取数据是没有意义的。我们先尝试一个合成数据。首先,我们介绍(n)维数组,也称为 张量(tensor)。

如果你使用过 Python 中最广泛使用的科学计算包 NumPy,那么你会感觉怼本部分很熟悉。无论你使用哪个框架,它的 张量类(在 MXNet 中为 ndarray,在 PyTorch 和TensorFlow中为 Tensor)与 Numpy 的 ndarray 类似,但都比Numpy 的 ndarray多一些重要功能。首先,GPU 很好地支持加速计算,而 NumPy 仅支持 CPU 计算。其次,张量类支持自动微分。这些功能使得张量类更适合深度学习。除非另有说明,在整本书中所说的张量指的是张量类的实例。

2.1.1. 入门
在本节中,我们的目标是帮助你开始了解并运行一些基本数值计算工具。在你阅读本书的过程中,将用到这些工具。如果你很难理解一些数学概念或库函数,请不要担心。在后面的章节将通过一些实际的例子来回顾这些内容。如果你已经有了一些背景知识,想要深入学习数学内容,可以就跳过这一节。

MXNET
PYTORCH
TENSORFLOW
首先,我们导入 torch。请注意,虽然它被称为PyTorch,但我们应该导入 torch 而不是 pytorch。

import torch
Copy to clipboard
张量表示一个数值组成的数组,这个数组可能有多个维度。具有一个轴的张量对应于数学上的 向量(vector)。具有两个轴的张量对应于数学上的 矩阵(matrix)。具有两个轴以上的张量没有特殊的数学名称。

首先,我们可以使用 arange 创建一个行向量 x。这个行向量包含以0开始的前12个整数,它们默认创建为浮点数。张量中的每个值都称为张量的 元素(element)。例如,张量 x 中有 12 个元素。除非额外指定,新的张量将存储在内存中,并采用基于CPU的计算。

MXNET
PYTORCH
TENSORFLOW
x = torch.arange(12)
x
Copy to clipboard
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
我们可以通过张量的 shape 属性来访问张量的 形状 (沿每个轴的长度)。

MXNET
PYTORCH
TENSORFLOW
x.shape
Copy to clipboard
torch.Size([12])
如果我们只想知道张量中元素的总数,即形状的所有元素乘积,我们可以检查它的大小(size)。 因为这里在处理的是一个向量,所以它的 shape 与它的 size 相同。

MXNET
PYTORCH
TENSORFLOW
x.numel()
Copy to clipboard
12
要改变一个张量的形状而不改变元素数量和元素值,我们可以调用 reshape 函数。 例如,我们可以把张量 x 从形状为 (12, ) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。

MXNET
PYTORCH
TENSORFLOW
X = x.reshape(3, 4)
X
Copy to clipboard
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
不需要通过手动指定每个维度来改变形状。 如果我们的目标形状是 (高度, 宽度) ,那么在知道宽度后,高度应当会隐式得出,我们不必自己做除法。在上面的例子中,要获得一个有3行的矩阵,我们手动指定了它有3行和4列。幸运的是,张量在给出其他部分后可以自动计算出一个维度。我们可以通过将希望张量自动推断的维度放置 -1 来调用此功能。在上面的例子中,我们可以用 x.reshape(-1, 4) 或 x.reshape(3, -1)来取代x.reshape(3, 4)。

有时,我们希望使用全0、全1、其他常量或者从特定分布中随机采样的数字,来初始化矩阵。我们可以创建一个形状为 (2, 3, 4) 的张量,其中所有元素都设置为0。代码如下:

MXNET
PYTORCH
TENSORFLOW
torch.zeros((2, 3, 4))
Copy to clipboard
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],

    [[0., 0., 0., 0.],
     [0., 0., 0., 0.],
     [0., 0., 0., 0.]]])

同样的,我们可以创建一个张量,其中所有元素都设置为1。代码如下:

MXNET
PYTORCH
TENSORFLOW
torch.ones((2, 3, 4))
Copy to clipboard
tensor([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],

    [[1., 1., 1., 1.],
     [1., 1., 1., 1.],
     [1., 1., 1., 1.]]])

有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为 (3, 4) 的张量。其中的每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样。

MXNET
PYTORCH
TENSORFLOW
torch.randn(3, 4)
Copy to clipboard
tensor([[ 0.6624, 0.6089, 2.1315, -0.4236],
[ 0.2953, -0.0027, -1.6279, -1.0125],
[-0.2773, 0.5857, 0.2215, 1.7032]])
我们还可以通过提供包含数值的 Python 列表(或嵌套列表)来为所需张量中的每个元素赋予确定值。在这里,最外层的列表对应于轴 0,内层的列表对应于轴 1。

MXNET
PYTORCH
TENSORFLOW
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
Copy to clipboard
tensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
2.1.2. 运算
这本书不是关于软件工程的。我们的兴趣不仅仅限于从数组读取和写入数据。我们想在这些数组上执行数学运算。一些最简单且最有用的操作是 按元素(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)。

对于任意具有相同形状的张量,常见的标准算术运算符(+、-、*、/ 和 **)都可以被升级为按元素运算。我们可以在同一形状的任意两个张量上调用按元素操作。在下面的例子中,我们使用逗号来表示一个具有5个元素的元组,其中每个元素都是按元素操作的结果。

MXNET
PYTORCH
TENSORFLOW
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x**y # **运算符是求幂运算
Copy to clipboard
(tensor([ 3., 4., 6., 10.]),
tensor([-1., 0., 2., 6.]),
tensor([ 2., 4., 8., 16.]),
tensor([0.5000, 1.0000, 2.0000, 4.0000]),
tensor([ 1., 4., 16., 64.]))
可以按按元素方式应用更多的计算,包括像求幂这样的一元运算符。

MXNET
PYTORCH
TENSORFLOW
torch.exp(x)
Copy to clipboard
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
除了按元素计算外,我们还可以执行线性代数运算,包括向量点积和矩阵乘法。我们将在 2.3节 中解释线性代数的重点内容(不需要先修知识)。

我们也可以把多个张量连结在一起,把它们端对端地叠起来形成一个更大的张量。 我们也可以 连结(concatenate) 多个张量在一起,将它们端到端堆叠以形成更大的张量。我们只需要提供张量列表,并给出沿哪个轴连结。下面的例子分别演示了当我们沿行(轴-0,形状的第一个元素)和按列(轴-1,形状的第二个元素)连结两个矩阵时会发生什么情况。我们可以看到,第一个输出张量的轴-0长度 ((6)) 是两个输入张量轴-0长度的总和 ((3 + 3));第二个输出张量的轴-1长度 ((8)) 是两个输入张量轴-1长度的总和 ((4 + 4))。

MXNET
PYTORCH
TENSORFLOW
X = torch.arange(12, dtype=torch.float32).reshape((3, 4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
Copy to clipboard
(tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]]),
tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]]))
有时,我们想通过 逻辑运算符 构建二元张量。以 X == Y 为例子。 对于每个位置,如果 X 和 Y 在该位置相等,则新张量中相应项的值为1,这意味着逻辑语句 X == Y 在该位置处为真,否则该位置为 0。

MXNET
PYTORCH
TENSORFLOW
X == Y
Copy to clipboard
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
对张量中的所有元素进行求和会产生一个只有一个元素的张量。

MXNET
PYTORCH
TENSORFLOW
X.sum()
Copy to clipboard
tensor(66.)
2.1.3. 广播机制
在上面的部分中,我们看到了如何在相同形状的两个张量上执行按元素操作。在某些情况下,即使形状不同,我们仍然可以通过调用 广播机制 (broadcasting mechanism) 来执行按元素操作。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行按元素操作。

在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下例子:

MXNET
PYTORCH
TENSORFLOW
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
Copy to clipboard
(tensor([[0],
[1],
[2]]),
tensor([[0, 1]]))
由于 a 和 b 分别是 (3\times1) 和 (1\times2) 矩阵,如果我们让它们相加,它们的形状不匹配。我们将两个矩阵广播为一个更大的 (3\times2) 矩阵,如下所示:矩阵 a将复制列,矩阵 b将复制行,然后再按元素相加。

MXNET
PYTORCH
TENSORFLOW
a + b
Copy to clipboard
tensor([[0, 1],
[1, 2],
[2, 3]])
2.1.4. 索引和切片
就像在任何其他 Python 数组中一样,张量中的元素可以通过索引访问。与任何 Python 数组一样:第一个元素的索引是 0;可以指定范围以包含第一个元素和最后一个之前的元素。与标准 Python 列表一样,我们可以通过使用负索引根据元素到列表尾部的相对位置访问元素。

因此,我们可以用 [-1] 选择最后一个元素,可以用 [1:3] 选择第二个和第三个元素,如下所示:

MXNET
PYTORCH
TENSORFLOW
X[-1], X[1:3]
Copy to clipboard
(tensor([ 8., 9., 10., 11.]),
tensor([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]))
除读取外,我们还可以通过指定索引来将元素写入矩阵。

X[1, 2] = 9
X
Copy to clipboard
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 9., 7.],
[ 8., 9., 10., 11.]])
如果我们想为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。 例如,[0:2, :] 访问第1行和第2行,其中 “:” 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。

MXNET
PYTORCH
TENSORFLOW
X[0:2, :] = 12
X
Copy to clipboard
tensor([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]])
2.1.5. 节省内存
运行一些操作可能会导致为新结果分配内存。例如,如果我们用 Y = X + Y,我们将取消引用 Y 指向的张量,而是指向新分配的内存处的张量。

在下面的例子中,我们用 Python 的 id() 函数演示了这一点,它给我们提供了内存中引用对象的确切地址。运行 Y = Y + X 后,我们会发现 id(Y) 指向另一个位置。这是因为 Python 首先计算 Y + X,为结果分配新的内存,然后使 Y 指向内存中的这个新位置。

MXNET
PYTORCH
TENSORFLOW
before = id(Y)
Y = Y + X
id(Y) == before
Copy to clipboard
False
这可能是不可取的,原因有两个:首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。

MXNET
PYTORCH
TENSORFLOW
幸运的是,执行原地操作非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 Y[:] = 。为了说明这一点,我们首先创建一个新的矩阵 Z,其形状与另一个 Y 相同,使用 zeros_like 来分配一个全(0)的块。

Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
Copy to clipboard
id(Z): 139621644254592
id(Z): 139621644254592
如果在后续计算中没有重复使用 X,我们也可以使用 X[:] = X + Y 或 X += Y 来减少操作的内存开销。

before = id(X)
X += Y
id(X) == before
Copy to clipboard
True
2.1.6. 转换为其他 Python 对象
转换为 NumPy 张量很容易,反之也很容易。转换后的结果不共享内存。 这个小的不便实际上是非常重要的:当你在 CPU 或 GPU 上执行操作的时候,此时Python的NumPy包也希望使用相同的内存块执行其他操作时,你不希望停止计算。

MXNET
PYTORCH
TENSORFLOW
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
Copy to clipboard
(numpy.ndarray, torch.Tensor)
要将大小为1的张量转换为 Python 标量,我们可以调用 item 函数或 Python 的内置函数。

MXNET
PYTORCH
TENSORFLOW
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)
Copy to clipboard
(tensor([3.5000]), 3.5, 3.5, 3)
2.1.7. 小结
深度学习存储和操作数据的主要接口是张量((n)维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他 Python 对象。

2.1.8. 练习
运行本节中的代码。将本节中的条件语句 X == Y 更改为 X < Y 或 X > Y,然后看看你可以得到什么样的张量。

用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同?

标签:tensor,元素,张量,学习,动手,PYTORCH,clipboard,深度,Copy
来源: https://www.cnblogs.com/Carrawayang/p/14729691.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有