购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 PyTorch张量

张量是PyTorch的基本数据类型。张量是一个多维矩阵,类似于NumPy的ndarrays:

❍ 标量可以表示为零维张量;

❍ 向量可以表示为一维张量;

❍ 二维矩阵可以表示为二维张量;

❍ 多维矩阵可以表示为多维张量。

这些张量如图2-4所示。

图2-4

例如,可以将一幅彩色图像看作像素值的三维张量,因为一幅彩色图像由height×width×3像素组成——其中这三个通道对应于RGB通道。类似地,可以将灰度图像看成二维张量,因为它由height×width像素组成。

在本节的最后,将学习为什么张量那么有用、如何初始化张量,以及如何在张量上执行各种运算。这将为下一节研究如何利用张量来构建神经网络模型打下良好基础。

2.2.1 初始化张量

张量在很多方面都很有用,除了可以作为图像的基本数据结构之外,还有一个更加突出的用途,就是可以利用张量来初始化连接神经网络不同层的权重。

在本节中,将学习初始化张量对象的不同方法。

下列代码可以从本书的GitHub存储库(https://tinyurl.com/mcvp-packt)Chapter02文件夹的Initializing_a_tensor.ipynb获得。

1.导入PyTorch并通过调用torch.tensor在列表中初始化一个张量:

2.接下来,访问张量对象的形状和数据类型:

张量内所有元素的数据类型是相同的。这就意味着如果一个张量包含不同数据类型的数据(比如布尔、整数和浮点数),那么整个张量被强制转换为一种最为通用的数据类型:

正如你在上述代码的输出中所看到的,False(布尔)和1(整数)被转换为浮点数。

或者,类似于NumPy,可以使用内置函数初始化张量对象。注意,这里画出的张量和神经网络权重之间的相似之处现在开始显现了:这里初始化张量,使它们能够表示神经网络的权重初始化。

3.生成一个张量对象,它有三行四列,填充0:

4.生成一个张量对象,它有三行四列,填充1:

5.生成值介于0和10之间(包括小值但不包括大值)的三行四列:

6.生成具有0和1之间随机数的三行四列:

7.生成数值服从正态分布的三行四列:

8.最后,可以直接使用torch.tensor(< NumPy-array>)将NumPy数组转换为Torch张量:

在学习了如何初始化张量对象的基础上,我们将在下一节学习如何在张量之上执行各种矩阵运算。

2.2.2 张量运算

与NumPy类似,你可以在张量对象上执行各种基本运算。与神经网络运算类似的是输入数据与权重之间的矩阵乘法,添加偏置项,并在需要的时候重塑输入数据或权重值。下面给出这些运算和其他运算的实现代码。

下列代码可以从本书的GitHub存储库(https://tinyurl.com/mcvp-packt)Chapter02文件夹中的Operations_on_tensors.ipynb获得。

❍ 可以使用下列代码将x中所有元素乘以10:

❍ 可以使用下列代码将10加到x中的元素,并将得到的张量存储到y中:

❍ 可以使用下列代码重塑一个张量:

❍ 重塑张量的另一种方法是使用squeeze方法,提供我们想要移除的指标轴。注意,这只适用于要删除的轴在该维度中只有一个项的场合:

❍ 与squeeze相反的是unsqueeze,这意味着给矩阵增加一个维度,可以使用下列代码实现:

使用None进行索引是一种很别致的unsqueeze方式,本书经常使用这种方式创建虚拟的通道/批维度。

❍ 可以使用下列代码实现两个不同张量的矩阵乘法:

❍ 或者,也可以使用@运算符实现矩阵乘法:

❍ 类似于NumPy中的concatenate,可以使用cat方法实现张量的连接:

❍ 可以使用下列代码提取张量中的最大值:

❍ 可以从存在最大值的行索引中提取最大值:

注意,在前面的输出中,获取的是第0号维度上的最大值,即张量在行上的最大值。因此,所有行上的最大值都是第4个索引中出现的值,所以indices的输出也都是4。此外,.max返回最大值和最大值的位置(argmax)。

类似地,跨列取最大值时的输出如下所示:

min运算与max运算完全相同,但在适合的情况下返回最小值和最小值的位置(arg-minimum)。

❍ 置换一个张量对象的维数:

注意当对原始张量进行排列时,张量的形状就会发生改变。

永远不要通过重塑(即使用tensor.view)一个张量来交换维数。虽然Torch不会抛出一条错误信息,但这是错误的,并将在训练期间产生不可预见的结果。如果需要交换维数,请始终使用permute。

因为本书很难涵盖所有可用的运算,所以重要的是要知道,你可以使用几乎与NumPy相同的语法在PyTorch中执行几乎所有的NumPy运算。标准的数学运算,如abs、add、argsort、ceil、floo、sin、cos、tan、sum、cumprod、diag、eig、exp、log、log2、log10、mean、median、mode、resize、round、sigmoid、softmax、square、sqrt、svd和transpose等,均可以直接在任何有轴或没有轴的张量上被调用。你总是可以运行dir(torch.Tensor)来查看所有可能的Torch张量方法,并通过help(torch.tensor.<method>)来查看关于该方法的官方帮助和相关文档。

接下来,我们将学习如何利用张量在数据上执行梯度计算,这是神经网络执行反向传播的一个关键点。

2.2.3 张量对象的自动梯度

微分和计算梯度在更新神经网络的权重中起着关键的作用。PyTorch的张量对象自带了计算梯度的内置功能。

在本节中,我们将了解如何使用PyTorch计算张量对象的梯度。

下列代码可以从本书的GitHub存储库(https://tinyurl.com/mcvp-packt)Chapter02文件夹中的Auto_gradient_of_tensors.ipynb获得。

1.定义一个张量对象,并指定要为张量对象计算梯度:

在上述代码中,requires_grad参数指定要为张量对象计算梯度。

2.接下来,定义计算输出的方式,在这个特定的例子中,输出是所有输入的平方和:

相应的代码如下:

我们知道前一个函数的梯度是2× x ,下面使用PyTorch提供的内置函数来验证这一点。

3.可以通过对某个值调用backward()方法来计算该值的梯度。在这个例子中,计算梯度——对于x(输入)的一个小变化,out(输出)的变化——如下所示:

4.现在可以得到out关于x的梯度,如下所示:

结果如图2-5所示。

图2-5

注意,上述梯度值与直观的梯度值(即x值的2倍)是匹配的。

作为练习,可以试着使用PyTorch重现第1章中chain rule.ipynb的场景。在一次前向传播之后计算梯度,并做出一次权重更新。然后,验证更新的权重与在notebook中计算的值匹配。

到目前为止,我们已经学习了在张量对象上的初始化、运算和梯度计算——它们共同构成了神经网络的基本构建模块。除了计算自动梯度,初始化和数据运算也可以使用NumPy数组完成。这就需要我们理解为什么在构建神经网络的时候,应该使用张量对象而不是使用NumPy数组,这将在下一节进行讨论。

2.2.4 PyTorch的张量较NumPy的ndarrays的优势

在前文计算权重值的时候,对每个权重都进行了少量的改变,并考察其对减少总损失值的影响。注意到,在同一次迭代中,基于某个权重更新的损失计算并不影响其他权重更新的损失计算。因此,如果每个权重更新分别由不同的内核并行完成,而不是按顺序更新权重,则可以优化这个计算过程。在这种情况下,GPU非常有用,因为与CPU(通常情况下,CPU可能有≤64个内核)相比,GPU由数千个内核组成。

与NumPy相比,Torch张量对象被优化为与GPU一起工作。为了进一步理解这一点,让我们来做一个小实验,在一个场景中使用NumPy数组执行矩阵乘法运算,在另一个场景中使用张量对象,并比较两个场景中执行矩阵乘法所花费的时间。

下列代码可以从本书的GitHub存储库(https://tinyurl.com/mcvp-packt)Chapter02文件夹中的Numpy_Vs_Torch_object_computation_speed_comparison.ipynb获得。

1.生成两个不同的torch对象:

2.定义存储第1步中所创建的张量对象的设备:

请注意,如果你没有GPU设备,则设备将是cpu(而且,你不会注意到使用CPU时执行时间的巨大差异)。

3.将第1步中创建的张量对象注册到设备中。注册张量对象意味着在设备中存储信息:

4.执行Torch对象的矩阵乘法并计时,以便比较在NumPy数组上执行矩阵乘法的计算速度:

5.在cpu上执行相同张量的矩阵乘法:

6.在NumPy数组上执行同样的矩阵乘法:

你会注意到,在GPU上执行Torch对象的矩阵乘法比在CPU上执行快约18倍,比在NumPy数组上执行矩阵乘法快约40倍。一般来说,在CPU上使用Torch张量的matmul运算仍然比NumPy快。注意,你会注意到这种加速需要你有一个GPU设备。如果你使用的是CPU设备,就不会注意到速度的显著提高。因此,如果你没有GPU,我们推荐使用谷歌Colab notebook,因为该服务提供免费的GPU。

现在我们已经学习了张量对象是如何在神经网络的各个单独组件/运算中发挥作用的,以及如何使用GPU实现加速计算。在下一节中,我们将学习如何将所有这些结合起来,使用PyTorch构建神经网络。 JzeS3c0uWnNLIiBmnyoRHFq3q9bSTe4UkJgOolWTT9qoHr+mOZGf5D7guOukZUkN

点击中间区域
呼出菜单
上一章
目录
下一章
×