张量
- 在深度学习中,数据通常以张量的形式进行表示。比如0维张量表示标量,也可以认为是一个数字;1维张量代表向量;2维张量代表矩阵;3维张量可以代表rgb图片;四维张量代表多张rgb图片;5维张量可以代表视频。在pytorch中,torch.Tensor是存储和变换数据的主要工具,与NumPy的多维数组类似。
- 创建tensor
- 随机初始化矩阵 torch.rand()方法
import torch
x = torch.rand(4,3)
print(x)
tensor([[0.5612, 0.1603, 0.6231],
[0.4623, 0.6435, 0.6361],
[0.2554, 0.5641, 0.5121],
[0.6984, 0.4933, 0.3612]])
-
创建全0的矩阵 torch.zeros()
-
创建全1矩阵 torch.ones()
-
常见构造tensor的方法
-
维度变换 张量的维度变换 torch.view()和torch.reshape()
-
pytorch中的tensor支持超过一百种操作,包括装置,索引,切片等,具体的使用方法可参考官网文档。
-
广播机制
当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。自动求导
-
pytorch中,所有的神经网络的核心是autograd包。它为张量上的所有的操作提供了自动求导机制。
Autograd简介 -
torch.Tensor是autogard的核心类,如果设置它的属性.requires_grad为True,那么它将会追踪对于该张量的所有操作。当完成计算后可以通过调用
.backward(),来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad属性。 -
如果需要计算导数,可以在 Tensor 上调用 .backward()。如果 Tensor
是一个标量(即它包含一个元素的数据),则不需要为 backward()
指定任何参数,但是如果它有更多的元素,则需要指定一个gradient参数,该参数是形状匹配的张量。
并行计算简介
在利用PyTorch做深度学习的过程中,可能会遇到数据量较大无法在单块GPU上完成,或者需要提升计算速度的场景,这时就需要用到并行计算。
做并行计算的目的
- 目的:可以让我们的模型训练的更快更好。让多个GPU来参与训练,减少训练时间。
为什么需要CUDA
- CUDA是我们使用GPU的提供商——NVIDIA提供的GPU并行计算框架。对于GPU本身的编程,使用的是CUDA语言来实现的。
- 在编写程序中,当我们使用了 .cuda() 时,其功能是让我们的模型或者数据从CPU迁移到GPU(0)当中,通过GPU开始计算。
- 注意事项:
1.我们使用GPU时使用的是.cuda()而不是使用.gpu()。这是因为当前GPU的编程接口采用CUDA,但是市面上的GPU并不是都支持CUDA,只有部分NVIDIA的GPU才支持,AMD的GPU编程接口采用的是OpenCL,在现阶段PyTorch并不支持。
2.数据在GPU和CPU之间进行传递时会比较耗时,我们应当尽量避免数据的切换。
3.GPU运算很快,但是在使用简单的操作时,我们应该尽量使用CPU去完成。
4.当我们的服务器上有多个GPU,我们应该指明我们使用的GPU是哪一块,如果我们不设置的话,tensor.cuda()方法会默认将tensor保存到第一块GPU上,等价于tensor.cuda(0),这将会导致爆出out of memory的错误。我们可以通过以下两种方式继续设置。
#设置在文件最开始部分
import os
os.environ["CUDA_VISIBLE_DEVICE"] = "2" # 设置默认的显卡
CUDA_VISBLE_DEVICE=0,1 python train.py # 使用0,1两块GPU
常见的并行的方法
- 将网络结构分布到不同的设备中,主要的思路是,将一个模型的各个部分拆分,然后将不同的部分放入到GPU来做不同任务的计算。这里遇到的问题就是,不同模型组件在不同的GPU上时,GPU之间的传输就很重要,对于GPU之间的通信是一个考验。但是GPU的通信在这种密集任务中很难办到,所以这个方式慢慢淡出了视野。
- 将同一层的任务分布到不同数据中,同一层的模型做一个拆分,让不同的GPU去训练同一层模型的部分任务。这样可以保证在不同组件之间传输的问题,但是在我们需要大量的训练,同步任务加重的情况下,会出现和第一种方式一样的问题。
- 将不同的数据分布到不同的设备中,执行相同的任务,它的逻辑是,我不再拆分模型,我训练的时候模型都是一整个模型。但是我将输入的数据拆分。所谓的拆分数据就是,同一个模型在不同GPU中训练一部分数据,然后再分别计算一部分数据之后,只需要将输出的数据做一个汇总,然后再反传。这种方式可以解决之前模式遇到的通讯问题。现在的主流方式是数据并行的方式(Data parallelism)。