PyTorch 知识点总结 -- 第 1 节

第 1 节 PyTorch Fundamentals

本节主要讲解 PyTorch 中的基本单位 Tensor(也称为张量),及一系列与 Tensor 有关的函数。


Tensor、维度与形状

函数 作用 举例 输出结果 结果描述
torch.tensor() 创建一个 Tensor 对象 - torch.tensor(7)
- torch.tensor([7, 7])
- tensor(7)
- tensor([7, 7])
将数值 7 和一维数组 [7, 7] 转换为 Tensor 对象
torch.tensor().item() 将 Tensor 对象转换为 Python 数据类型 - torch.tensor(7).item()
- torch.tensor([7, 7]).item()
- 7
- ERROR
只能转换单个值,不能转换数组
torch.tensor().ndim 获取 Tensor 对象的维度 - torch.tensor(7).ndim
- torch.tensor([7, 7]).ndim
- torch.tensor([7, 8], [9, 10]).ndim
- 0
- 1
- 2
ndim 函数的作用可以看作计算有几对 嵌套 大括号(平级大括号不计入)
torch.tensor().shape 获取 Tensor 对象的形状 - torch.tensor(7).shape
- torch.tensor([7, 7]).shape
- torch.tensor([[1, 2, 3], [4, 5, 6]]).shape
- torch.tensor([
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]
]).shape
- torch.Size([])
- torch.Size([2])
- torch.Size([2, 3])
- torch.Size([1, 4, 3]) # 表示第 1 维长度为 1,第 2 维长度为 4,第 3 维长度为 3。此处第 1 维长度为 1 的原因是最外层的大括号只包含 1 个元素即 [[...]]
shape 实际上是一个长度等于 Tensor 维度数的元组,第 i 个元素表示第 i+1 维的大小
如果 Tensor 对象只包含一个数值而非数组,则没有任何维度, shape 值为空;
如果 Tensor 对象包含一个一维数组,则包含 1 个维度, shape 值为该维度的长度,也就是数组的列数;
如果 Tensor 对象包含一个二维数组,则包含 2 个维度, shape 长度为 2,shape[0] 为该数组的行数,shape[1] 为该数组的列数;
如果 Tensor 对象包含一个多维数组,则包含 N 个维度,shape 长度为 N

随机 Tensor、随机数种子、全 0 和全 1 Tensor

神经网络的学习方法通常是随机生成一些初始 Tensors,然后对其进行拟合,使其更准确地描述数据。

函数 作用 举例 输出结果 结果描述
torch.rand(row, col) 创建形状为 (row, col) 的随机 Tensor torch.rand(3, 4) tensor([
[0.9251, 0.0865, 0.0187, 0.7156],
[0.2475, 0.8762, 0.2020, 0.9959],
[0.6348, 0.5955, 0.9724, 0.3047]
])
每次的输出结果是随机的
torch.rand(size=(width, height, channel)) 创建形状为 (width, height, channel) 的随机 Tensor torch.rand(size=(224, 224, 3)) tensor([[
[0.4218, 0.1902, 0.3915],
[0.2171, 0.5964, 0.5715],
[0.2390, 0.2073, 0.2960], …,
size 参数可以隐性传入。该函数通常用于处理图像,channel 是图像的颜色通道,设置为 3 表示 RGB。channel 也可以置于参数第一位,即 size=(3, 224, 224)
torch.zeros(size=(row, col)) 创建形状为 (row, col) 的全 0 Tensor torch.zeros(size=(3, 4)) tensor([
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]
])
size 参数可以隐性传入。torch.ones() 函数同理创建形状为 (row, col) 的全 1 Tensor
torch.manual_seed(int) 设置随机数种子 torch.manual_seed(42)
torch.rand(3, 4)
tensor([
[0.8823, 0.9150, 0.3829, 0.9593],
[0.3904, 0.6009, 0.2566, 0.7936],
[0.9408, 0.1332, 0.9346, 0.5936]
])
每次生成随机 Tensor 前都需要声明一次该函数

Tensor 数据类型与运算

PyTorch 中的 Tensor 对于整型数组默认使用 torch.int64 类型,对于浮点型数组默认使用 torch.float32 类型,而 Numpy 的数组默认使用 float64 类型,在互相转换时默认类型以转换源为准。

机器学习和深度学习中,使用 Tensor 时有三大易错点:

  1. Tensor 数据类型错误,可使用 tensor.dtype 查看;
  2. Tensor 形状错误,可使用 tensor.shapetensor.size() 查看;
  3. Tensor 设备错误,可使用 tensor.device 查看。
函数 作用 举例 输出结果 结果描述
torch.tensor(data, dtype, device, requires_grad=False) 创建一个 Tensor 对象 torch.tensor([3.0, 6.0, 9.0],
dtype = None,
device = None,
requires_grad = False)
tensor([3., 6., 9.]) dtype 参数指定 Tensor 的数据类型,如 float32float16
device 参数指定处理 Tensor 使用的设备,如 cpucuda
requires_grad 参数设定是否使用该 Tensor 进行梯度跟踪,默认为 False
torch.tensor().type() 设置 Tensor 对象的数据类型 torch.tensor([1., 2., 3.]).type(torch.float16) tensor([1., 2., 3.], dtype=torch.float16) 浮点型 Tensor 可与整型 Tensor 相互运算,最终结果为浮点型
tensor.matmul(tensorA, tensorB)
tensor.mm(tensorA, tensorB)
tensorA @ tensorB
对两个 Tensor 进行矩阵乘法运算 tensor = torch.tensor([1, 2, 3])
torch.matmul(tensor, tensor)
tensor([14]) 矩阵乘法详细描述见表后

矩阵乘法涉及到维度至少为 1 的两个 Tensor,同时需要满足两个条件。设 TensorA = torch.tensor([A1, A2])TensorB = torch.tensor([B1, B2])。使用 torch.tensor().T 可以转置 Tensor 的维度。

  1. 两个 Tensor 的内部维度必须相同。在上述条件中, A2B1 为内部维度,即需要满足 A2 = B1
  2. 结果矩阵的 shape 等于两个 Tensor 的外部维度。在上述条件中,A1B2 为外部维度,则结果矩阵的 shape = (A1, B2)

对于两个一维 Tensor,结果矩阵就是对应项相乘的和;

对于两个二维及以上多维 Tensor,可视化举例如下说明。

tensorA = torch.tensor([[1, 2],
                        [3, 4],
                        [5, 6]])
tensorB = torch.tensor([[7, 8],
                        [9, 10],
                        [11, 12]])
# tensorA.shape = torch.Size([3, 2]), tensorB.shape = torch.Size([3, 2])

# 两个 Tensor 的内部维度不同,不能运算。此时需要对其中一个 Tensor 转置,如 tensorB.T。

tensorB = tensorB.T	# tensorB = torch.tensor([[7, 8, 9],
				  #						 [10, 11, 12]])
				  # tensorB.shape = [2, 3]
        
# 现在做 tensor.matmul(tensorA, tensorB) 运算。可将 tensorB 先逆时针旋转 90° 并置于 tensorA 上方,得到:
# [9, 12] -> tensorB 第一行
# [8, 11] -> tensorB 第二行
# [7, 10] -> tensorB 第三行
# -------
# [1, 2] -> tensorA 第一行
# [3, 4] -> tensorA 第二行
# [5, 6] -> tensorA 第三行

# 第一步,将 tensorB 向下移动一次,使第三行与 tensorA 的第一行相乘,得到 1*7+2*10=27,放入结果矩阵的 [0, 0] 处
# 第二步,将 tensorB 向下移动一次,使第三行与 tensorA 的第二行相乘,得到 3*7+4*10=61,放入结果矩阵的 [1, 0] 处;同时,第二行与 tensorA 的第一行相乘,得到 1*8+2*11=30,放入结果矩阵的 [0, 1] 处
# 第三步,将 tensorB 向下移动一次,使第三行与 tensorA 的第三行相乘,得到 5*7+6*10=95,放入结果矩阵的 [2, 0]处;同时,第二行与 tensorA 的第二行相乘,得到 3*8+4*11=68,放入结果矩阵的 [1, 1] 处;第一行与 tensorA 的第一行相乘,得到 1*9+2*12=33,放入结果矩阵的 [0, 2]处
# 第四步,将 tensorB 向下移动一次,使第二行与 tensorA 的第三行相乘,得到 5*8+6*11=106,放入结果矩阵的 [2, 1]处;同时,第一行与 tensorA 的第二行相乘,得到 3*9+4*12=75,放入结果矩阵的 [1, 2] 处
# 第五步,将 tensorB 向下移动一次,使第一行与 tensorA 的第三行相乘,得到 5*9+6*12=117,放入结果矩阵的 [2, 2] 处
结果矩阵可视化步骤如下:

[ - - - ]    [ 27 - - ]    [ 27 30 - ]    [ 27 30 33 ]    [ 27 30 33 ]    [ 27  30  33 ]
[ - - - ] -> [ - - -  ] -> [ 61 - -  ] -> [ 61 68 -  ] -> [ 61 68 75 ] -> [ 61  68  75 ]
[ - - - ]    [ - - -  ]    [ - - -   ]    [ 95 - -   ]    [ 95 106 - ]    [ 95 106 117 ]

Tensor 最小值、最大值及其索引、平均值、和

函数 作用 举例 输出结果 结果描述
torch.arange(start, end, step) step 为步长创建 [start, end) 序列 torch.arange(0, 100, 10) tensor([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90]) 结果包括 start 端点,不包括 end 端点
torch.min() 获取一个 Tensor 序列中的最小值 torch.min(torch.arange(0, 100, 10)) tensor(0) 也可使用 torch.arange().min() 的形式,torch.max()同理
torch.mean() 获取一个 Tensor 序列中所有值的平均值 torch.mean(torch.arange(0, 100, 10).type(torch.float32)) tensor(45.) 也可使用类似于 torch.arange(int).type(torch.float32).mean()的形式,该函数的参数只能是浮点数类型或复数类型
torch.sum() 获取一个 Tensor 序列中所有值的和 torch.sum(torch.arange(0, 100, 10)) tensor(450) 也可使用 torch.arange().sum() 的形式
argmin() 获取 Tensor 最小值的索引 torch.arange(0, 100, 10).argmin() tensor(0)
argmax() 获取 Tensor 最大值的索引 torch.arange(0, 100, 10).argmax() tensor(9)

Reshape, View, Stack, Squeeze, Unsqueeze 和 Permute

  • Reshape:将一个 Tensor 重塑到定义的 shape,重塑后的 Tensor 与原 Tensor 各自独立。
  • View:返回一个特定形状的 Tensor 的副本,和原 Tensor 共用内存。修改该副本会修改原 Tensor 的值。
  • Stack:将多个 Tensor 拼接,类型包括 vstackhstack。使用 dim 参数指定新维度拼接的位置
  • Squeeze:移除 Tensor 中所有维数为 1 的维度。
  • Unsqueeze:添加一个维数为 1 的维度到指定 Tensor 中,使用 dim 参数指定添加的位置。
  • Permute:返回一个输入 Tensor 的副本,与原 Tensor 共用内存,其中维度以特定方式排列。

示例见如下代码块:

x = torch.arange(1., 10.) 
# -> x = tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.]), x.shape = torch.Size([9]), x.ndim = 1

# Reshape
x_reshaped = x.reshape(1, 9) # 将 x 重塑为一个 size=(1, 9) 的二维张量
# -> x_reshaped = tensor([[1., 2., 3., 4., 5., 6., 7., 8., 9.]]), x_reshaped.shape = torch.Size([1, 9])

# View
z = x.view(1, 9) # -> z = tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.])
z[:, 0] = 5 # 将 z 中所有行第 1 列的值设置为 5
# -> z = tensor([5., 2., 3., 4., 5., 6., 7., 8., 9.]), x = tensor([5., 2., 3., 4., 5., 6., 7., 8., 9.])

# Stack
x_stacked = torch.stack([x, x, x, x], dim=0) # torch.stack 的作用是把一组形状相同的张量沿着一个新的维度拼起来,dim 就是用来指定这个“新维度”要放在哪个位置。此处的 x.shape = [9],将 dim 置 0 等价于 x.unsqueeze(0),x.shape 变为 [1, 9],再将 4 个 x 在第 0 维拼起来,得到 x_stacked.shape = torch.Size([4, 9]);如果置 1,则等价于 x.unsqueeze(1),x.shape 变为 [9, 1],最终结果为 x_stacked.shape = torch.Size([9, 4])。对于一维张量,dim 只能置 0 或 1,更高维度的张量才能使用更大的 dim 值
# -> x_stacked = tensor([[5., 2., 3., 4., 5., 6., 7., 8., 9.],
#                        [5., 2., 3., 4., 5., 6., 7., 8., 9.],
#                        [5., 2., 3., 4., 5., 6., 7., 8., 9.],
#                        [5., 2., 3., 4., 5., 6., 7., 8., 9.]]), x_squeezed.ndim = 2

# Squeeze
x_squeezed = x_reshaped.squeeze()
# -> x_squeezed = tensor([5., 2., 3., 4., 5., 6., 7., 8., 9.]), x_squeezed.shape = torch.Size([9])

# Unsqueeze
x_unsqueezed = x_squeezed.unsqueeze(dim=1) # 此处 dim 的作用与 torch.stack 中的 dim 相同
# -> x_unsqueezed = tensor([[5.],
#                           [2.],
#                           [3.],
#                           [4.],
#                           [5.],
#                           [6.],
#                           [7.],
#                           [8.],
#                           [9.]]), x_unsqueezed.shape = torch.Size([9, 1])

# Permute
x_original = torch.rand(size=(224, 224, 3))
x_permuted = x_original.permute(2, 0, 1) # 将 x_original 的第 0 位,即第 1 个 224 放入置 0 的位,以此类推
# -> x_original.shape = torch.Size([224, 224, 3]), x_permuted = torch.Size([3, 224, 224])

PyTorch 和 Numpy

函数 作用 举例 输出结果 结果描述
torch.from_numpy(ndarray) 将 Numpy 数据转换到 Tensor torch.from_numpy(np.arange(1.0, 8.0)) tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64) Numpy 数组的默认数据类型为 float64,转换为 Tensor 保留类型为 torch.float64
torch.Tensor.numpy() 将 Tensor 转换到 Numpy 数据 torch.ones(7).numpy() array([1., 1., 1., 1., 1., 1.], dtype=float32) Tensor 默认数据类型为 torch.float32,转换为 Numpy 数组保留类型为 float32

CPU 和 GPU

函数 作用 举例 输出结果 结果描述
torch.cuda.is_available() # bool 返回 CUDA 是否可用 device = “cuda” if torch.cuda.is_available() else “cpu”
device
'cuda' 如果环境中 CUDA 可用则输出 cuda,否则输出 cpu
torch.cuda.device_count() 返回当前可用的 CUDA 设备数量 torch.cuda.device_count() 1
torch.tensor().to(device) 将 Tensor 放入 GPU 处理 tensor_on_gpu = torch.tensor([1, 2, 3]).to(device)
tensor_on_gpu
tensor([1, 2, 3], device='cuda:0')
torch.tensor().to(device).cpu() 将工作在 GPU 上的 Tensor 放入 CPU 处理 tensor_on_gpu.cpu().numpy() array([1, 2, 3]) Numpy 工作在 CPU 上,TensorFlow 和 PyTorch 工作在 GPU 上,转换为 Numpy 需要首先将 GPU 中的 Tensor 放回 CPU

你可能感兴趣的:(读书笔记-计算机类,pytorch,人工智能,python)