0%

Python数据科学_33_Pytorch深度学习基础

什么是张量?

  1. “Tensor”(张量)是一个数学和计算机科学术语,用于表示多维数组的数据结构。在深度学习和机器学习中,张量是一种常见的数据结构,用于存储和表示多维的数据,如标量(0维张量,即单个数值)、向量(1维张量,如一维数组)、矩阵(2维张量,如二维数组)以及更高维度的数据。张量可以包含整数、浮点数或其他数据类型,具体取决于应用的需要。
  2. 在深度学习中,张量是神经网络的核心数据结构。神经网络的层、权重、激活函数和输入都表示为张量。张量的多维性使其适用于处理各种复杂的数据,如图像、文本、音频等,并且能够在GPU和TPU等计算资源上执行并行式计算,大大提高资源利用率。
1
import torch
1
torch.__version__
'2.1.0+cu121'

创建张量

参考:https://pytorch.org/docs/stable/torch.html#creation-ops

创建简单张量

创建简单张量

1
2
tensor1 = torch.tensor([[1, 2, 3], [2, 3, 6]])
tensor1
1
2
tensor([[1, 2, 3],
[2, 3, 6]])

创建未初始化张量

1
2
3
# 已知生成张量维度
tensor2 = torch.empty(size=(2, 3)) # 创建出一个未初始化的张量,张量的值会取决于内存中的随机初始化值或者取决于之前内存中的内容
tensor2
1
2
tensor([[-1.0717e+37,  1.3410e-42,  0.0000e+00],
[ 0.0000e+00, 0.0000e+00, 0.0000e+00]])
1
2
# 已知与某个张量维度一致
torch.empty_like(tensor1)
tensor([[0, 0, 0],
        [0, 0, 0]])
1
2
tensor3 = torch.Tensor(2, 3)  # 直接传入生成张量的维度到torch.Tensor()时与torch.empty()效果等价
tensor3
tensor([[-1.0718e+37,  1.3410e-42,  0.0000e+00],
        [ 0.0000e+00,  0.0000e+00,  0.0000e+00]])

查看张量的基本属性与方法

每个张量都具有以下基本属性:

  1. 张量尺寸
  2. 张量元素类型
  3. 张量维度
  4. 张量中元素个数
  5. 张量的转置
  6. 获取张量中非零元素所在位置
  7. 打印张量所在设备
  8. 查看梯度

张量尺寸

1
tensor1.shape
torch.Size([2, 3])
1
tensor1.size()  # 效果同shape属性
torch.Size([2, 3])

张量元素类型

1
tensor1.dtype
torch.int64

张量维度

1
tensor1.ndim
2

张量元素个数

1
tensor1.numel()
6
1
torch.numel(tensor1)  # 效果等于与tensor1.numel()
6

对张量进行转置

1
tensor1.T
tensor([[1, 2],
        [2, 3],
        [3, 6]])
1
tensor1.t()
tensor([[1, 2],
        [2, 3],
        [3, 6]])

获取张量中非零元素所在位置

1
tensor2.nonzero()   # 返回一个二维张量,第一列表示行数,第二列表示列数
tensor([[0, 0],
        [0, 1]])

张量所在设备

1
tensor2.device
device(type='cpu')

查看梯度

1
2
# 该属性只有在反向传播计算梯度后才会有具体的值
print(tensor2.grad)
None

张量与数组的相互转化

将数组转化为张量

1
import numpy as np
1
2
array1 = np.random.randint(20, size=(3, 4))
array1
array([[13, 13,  8,  0],
       [18,  3,  7,  4],
       [16,  8, 14, 18]])
1
2
# 方法1
torch.Tensor(array1)
tensor([[13., 13.,  8.,  0.],
        [18.,  3.,  7.,  4.],
        [16.,  8., 14., 18.]])
1
2
# 方法2
torch.from_numpy(array1)
1
2
3
tensor([[13, 13,  8,  0],
[18, 3, 7, 4],
[16, 8, 14, 18]], dtype=torch.int32)
1
2
# 方法3
torch.asarray(array1)
1
2
3
tensor([[13, 13,  8,  0],
[18, 3, 7, 4],
[16, 8, 14, 18]], dtype=torch.int32)

第二个函数asarray()的功能更多,不仅可以将数组转化为张量,还可以将其他数据类型转化为张量,例如:标量,列表,元组等等。而from_numpy()函数只能将数组转化为张量,如果是其他类型的数据则会报错。

1
torch.from_numpy([1, 2, 3, 4])
1
2
3
4
5
6
7
8
9
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

Cell In[25], line 1
----> 1 torch.from_numpy([1, 2, 3, 4])


TypeError: expected np.ndarray (got list)
1
torch.asarray([1, 2, 3, 4])
tensor([1, 2, 3, 4])

将张量转化为数组

1
2
# 方法1
np.array(tensor1)
array([[1, 2, 3],
       [2, 3, 6]], dtype=int64)
1
2
# 方法2
tensor1.numpy()
array([[1, 2, 3],
       [2, 3, 6]], dtype=int64)

创建特殊张量

创建等差张量

1
torch.range(1, 10, 2)  # 该方法即将淘汰与torch.arange()等价
1
2
3
C:\Users\ming\AppData\Local\Temp\ipykernel_4696\262098997.py:1: UserWarning: torch.range is deprecated and will be removed in a future release because its behavior is inconsistent with Python's range builtin. Instead, use torch.arange, which produces values in [start, end).
torch.range(1, 10, 2) # 该方法即将淘汰与torch.arange()等价
tensor([1., 3., 5., 7., 9.])
1
torch.arange(1, 10, 2)
tensor([1, 3, 5, 7, 9])
1
torch.linspace(1, 10, 5)
1
tensor([ 1.0000,  3.2500,  5.5000,  7.7500, 10.0000])

创建等比张量

1
torch.logspace(1, 10, 6, base=2)
1
tensor([   2.0000,    6.9644,   24.2515,   84.4485,  294.0668, 1024.0000])

创建全0张量

1
2
# 已知张量维度
torch.zeros(size=(3, 3))
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
1
2
# 已知与某个张量尺寸一致
torch.zeros_like(tensor1)
tensor([[0, 0, 0],
        [0, 0, 0]])

创建全1张量

1
2
# 已知张量维度
torch.ones(size=(3, 3))
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
1
2
# 已知与某个张量尺寸一致
torch.ones_like(tensor1)
tensor([[1, 1, 1],
        [1, 1, 1]])

创建相同元素的张量

1
2
# 已知张量维度
torch.full(size=(3, 3), fill_value=2.3) # 创建元素值相同的张量 <==> torch.ones(size=(3, 3)) * 2.3
tensor([[2.3000, 2.3000, 2.3000],
        [2.3000, 2.3000, 2.3000],
        [2.3000, 2.3000, 2.3000]])
1
2
# 已知与某个张量尺寸一致
torch.full_like(input=tensor1, fill_value=2.3)
tensor([[2, 2, 2],
        [2, 2, 2]])

创建对角线元素为1的二维张量(单位矩阵)

1
torch.eye(3)
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])

随机抽样

设置随机种子数

设定随机种子数后,在Pytorch中使用“随机系列”方法生成的随机张量值就会固定下来,不会每次运行时更新,这对于复现某些模型的结果非常有用

1
torch.manual_seed(1000)
1
<torch._C.Generator at 0x22e5ae63750>
1
2
# 返回生成随机数的种子值
torch.initial_seed()
1000

创建从0~n-1的随机整数序列

该方法得到的结果可以理解为将torch.arange()方法得到的结果进行打乱输出

1
2
tensor3 = torch.randperm(5)
tensor3
tensor([2, 4, 0, 3, 1])

均匀分布

返回[0, 1)上的均匀分布随机数

1
2
# 已知尺寸
torch.rand(size=(3, 4))
1
2
3
tensor([[0.2724, 0.6261, 0.4410, 0.3653],
[0.3535, 0.5971, 0.3572, 0.4807],
[0.4217, 0.1254, 0.6818, 0.0571]])
1
2
# 已知和某个张量维度相同
torch.rand_like(tensor2)
tensor([[0.6818, 0.0473, 0.4856],
        [0.0260, 0.0131, 0.7607]])
1
tensor2.uniform_(0, 1)  # 使用均匀分布随机数对张量中的值进行填充,该方法会直接修改tensor中的值,该方法可以指定均匀分布范围[low, high)
tensor([[0.0722, 0.1026, 0.3915],
        [0.4430, 0.6577, 0.4261]])

伯努利分布

1
2
# 以上方的tensor2的结果作为概率进行伯努利采样
torch.bernoulli(tensor2) # 结果为0和1构成的张量,1表示该位置元素被取出
tensor([[0., 0., 0.],
        [1., 1., 0.]])

多项式分布

1
2
3
weight = torch.Tensor([5, 3, 1, 9])  # 定义多项式分布权重
# replacement: 表示是否是有放回采样,默认的情况下是有放回采样
torch.multinomial(weight, 40, replacement=True) # 3这个位置的权重最大,那么3肯定取出的次数最多
1
2
tensor([0, 3, 3, 1, 0, 3, 1, 0, 3, 0, 0, 0, 3, 3, 3, 1, 3, 0, 0, 1, 3, 3, 3, 3,
0, 0, 3, 3, 2, 2, 3, 0, 0, 1, 1, 3, 0, 0, 0, 3])

泊松分布

image-20231019141752523

1
2
rates = torch.rand(4, 4) * 5  # rate parameter between 0 and 5
torch.poisson(rates)
tensor([[0., 1., 4., 4.],
        [0., 5., 5., 3.],
        [5., 0., 0., 2.],
        [5., 2., 3., 1.]])

随机整数

1
2
# 已知尺寸
torch.randint(20, 50, size=(5, 5))
tensor([[20, 46, 22, 42, 22],
        [33, 22, 22, 35, 45],
        [30, 41, 24, 41, 21],
        [28, 48, 23, 27, 45],
        [20, 38, 39, 20, 47]])
1
2
# 已知和某个张量维度相同
torch.randint_like(tensor2, 20, 50)
tensor([[39., 47., 49.],
        [32., 45., 31.]])

正态分布

标准正态分布

1
2
# 已知尺寸
torch.randn(size=(5, 5))
1
2
3
4
5
tensor([[-0.9138, -0.3769, -0.3745,  1.7369, -1.5996],
[-0.5251, -1.9600, -0.1617, 0.3721, 1.0565],
[-0.1531, -0.7231, 1.5471, 0.6138, -1.9954],
[-0.7167, 0.2939, -1.1686, -0.7682, -1.0757],
[-0.7147, 0.4852, 1.0869, -0.2248, -0.8522]])
1
2
# 已知和某个张量维度相同
torch.randn_like(tensor2)
1
2
tensor([[-0.2276,  0.5628,  0.2006],
[ 0.8952, 1.3668, 0.6112]])

一般正态分布

1
2
3
# 多个均值,多个标准差
# 此时生成的每个元素都有对应一个正态分布
torch.normal(mean=torch.arange(1, 11, 1.0), std=torch.arange(1, 0, -0.1))
1
2
tensor([1.1280, 2.4969, 4.2895, 3.8980, 3.6548, 5.6770, 6.6576, 8.1910, 9.0875,
9.9736])
1
2
3
# 一个均值,多个标准差
# 此时生成的元素均值相同,标准差不同
torch.normal(mean=torch.Tensor([1.0,]), std=torch.arange(1, 0, -0.1))
1
2
tensor([ 2.1430, -0.1413,  0.3334,  1.0870,  0.0081,  1.1751,  0.6992,  1.5841,
0.8683, 1.1521])
1
2
3
# 多个均值,一个标准差
# 此时生成的元素均值不同,标准差相同
torch.normal(mean=torch.arange(1, 11, 1.0), std=torch.Tensor([1.0,]))
1
2
tensor([ 0.2791,  0.9233,  1.1594,  3.5136,  5.8334,  7.4911,  6.7038,  9.4591,
9.6741, 11.2492])
1
2
3
# 一个均值一个标准差
# 此时就需要去指定生成的张量尺寸
torch.normal(mean=0, std=1, size=(3, 3))
1
2
3
tensor([[ 0.8146,  0.1963,  2.1625],
[-0.2048, -0.8331, 0.0816],
[-0.5588, 0.5525, 0.3279]])

张量的序列化与反序列化

将tensor保存到硬盘

1
torch.save(tensor2, 'tensor2.pt')

将硬盘上的张量读取到内存

此时需要注意一个一个问题,默认的情况下张量存储到硬盘中会记录张量保存前的设备位置,在导入的时候也会自动导入到相应的设备。这个时候会存在一个问题,如果我在服务器中保存了cuda:2设备中的某个张量到硬盘,然后再将硬盘读取到我本机的电脑中,我本机电脑有没有cuda:2设备,这个时候就会报错。

我们可以在读取张量文件时,通过指定map_location参数将张量读取到某个设备内存中。

1
2
tensor_read = torch.load('tensor2.pt', map_location='cuda:0')  # 前面保存的时候存储到cpu中,在这里将其读取到cuda:0设备中
tensor_read
1
2
tensor([[0.0722, 0.1026, 0.3915],
[0.4430, 0.6577, 0.4261]], device='cuda:0')

张量元素操作

1
2
3
# 创建待处理张量
tensor4 = torch.randint(10, size=(3, 4))
tensor5 = torch.randint(10, 20, size=(3, 4))
1
tensor4
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [3, 2, 0, 6]])
1
tensor5
tensor([[12, 13, 19, 12],
        [11, 10, 19, 10],
        [17, 17, 13, 17]])

张量的索引和切片

首先,张量支持类似于Numpy中的元素索引和切片,例如:取出部分元素,按照条件对元素进行筛选等等。

1
2
# 获取tensor4中第2行第3列的值
tensor4[1, 2]
tensor(2)
1
2
# 切片出tensor4中行下标值为1, 2;列下标值2, 3, 4的部分元素值
tensor4[1:, 2:]
tensor([[2, 0],
        [0, 6]])
1
2
# 筛选出tensor4中大于5的元素
tensor4[tensor4 > 5]
tensor([8, 6, 7, 6])

张量尺寸修改

1
tensor4.reshape(shape=(4, 3))
tensor([[2, 0, 2],
        [8, 6, 7],
        [2, 0, 3],
        [2, 0, 6]])
1
tensor4.view(4, 3)
tensor([[2, 0, 2],
        [8, 6, 7],
        [2, 0, 3],
        [2, 0, 6]])

张量的拼接

不生成新维度

  • torch.cat()
  • torch.concat()
  • torch.concatenate()
1
2
# 横向拼接
torch.cat([tensor4, tensor5], dim=1)
1
2
3
tensor([[ 2,  0,  2,  8, 12, 13, 19, 12],
[ 6, 7, 2, 0, 11, 10, 19, 10],
[ 3, 2, 0, 6, 17, 17, 13, 17]])
1
2
# 纵向拼接
torch.cat([tensor4, tensor5], dim=0)
tensor([[ 2,  0,  2,  8],
        [ 6,  7,  2,  0],
        [ 3,  2,  0,  6],
        [12, 13, 19, 12],
        [11, 10, 19, 10],
        [17, 17, 13, 17]])

生成新维度

1
torch.stack([tensor4, tensor5], dim=0)  # 堆叠到第一个维度
tensor([[[ 2,  0,  2,  8],
         [ 6,  7,  2,  0],
         [ 3,  2,  0,  6]],

        [[12, 13, 19, 12],
         [11, 10, 19, 10],
         [17, 17, 13, 17]]])
1
torch.stack([tensor4, tensor5], dim=1)  # 堆叠到第二个维度
tensor([[[ 2,  0,  2,  8],
         [12, 13, 19, 12]],

        [[ 6,  7,  2,  0],
         [11, 10, 19, 10]],

        [[ 3,  2,  0,  6],
         [17, 17, 13, 17]]])

张量的切分

指定切分的份数

1
2
# 横向切分
torch.chunk(tensor4, 2, dim=0) # 如果不能整切,那么最后一个不足的行数/列数会单独作为一个张量
(tensor([[2, 0, 2, 8],
         [6, 7, 2, 0]]),
 tensor([[3, 2, 0, 6]]))
1
2
# 纵向切分
torch.chunk(tensor4, 2, dim=1)
(tensor([[2, 0],
         [6, 7],
         [3, 2]]),
 tensor([[2, 8],
         [2, 0],
         [0, 6]]))

指定切分的大小

1
2
3
# 指定某个维度的切分大小
torch.split(tensor4, 2, dim=0) # 将tensor4以2行作为一个张量进行切分
# 如果不能整切,那么最后一个不足的维度会单独作为一个张量
(tensor([[2, 0, 2, 8],
         [6, 7, 2, 0]]),
 tensor([[3, 2, 0, 6]]))

汇聚操作(选讲)

image-20231019164217901

1
2
3
4
5
6
7
8
9
10
11
12
13
# 相当于是对tensor4的元素进行重采样,dim=0说明是对tensor4的0维度下标进行修改为index
# 例如:
# 原始:
# [[0, 0], [0, 1], [0, 2], [0, 3]]
# [[1, 0], [1, 1], [1, 2], [1, 3]]
# [[2, 0], [2, 1], [2, 2], [2, 3]]
# 修改后:
# [[0, 0], [1, 1], [0, 2], [1, 3]]
# [[1, 0], [0, 1], [1, 2], [0, 3]]
# [[0, 0], [0, 1], [0, 2], [1, 3]]
# 使用修改后的每个元素索引在原始张量中重采样即可得到最终结果
tensor6 = torch.gather(input=tensor4, dim=0, index=torch.LongTensor([[0, 1, 0, 1], [1, 0, 1, 0], [0, 0, 0, 1]]))
tensor6
tensor([[2, 7, 2, 0],
        [6, 0, 2, 8],
        [2, 0, 2, 0]])

散射操作(选讲)

散射操作和汇聚操作可以看成是一组逆运算操作

image-20231019161614782

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 原来的结果
# t = torch.zeors(4, 4)
# [[0, 0, 0, 0]]
# [[0, 0, 0, 0]]
# [[0, 0, 0, 0]]
# [[0, 0, 0, 0]]
# 如何使用src修改赋值呢?
# tensor6原始值规则
# t[0, 0] = 2;t[0, 1]=7;t[0, 2]=4;t[0, 3]=1
# t[1, 0] = 9;t[1, 1]=2;t[1, 2]=2;t[1, 3]=2
# t[2, 0] = 2;t[2, 1]=2;t[2, 2]=4;t[2, 3]=1
# 由于dim=0,所以将0维度对应的值修改为index
# t[0, 0] = 2;t[1, 1]=7;t[0, 2]=4;t[1, 3]=1
# t[1, 0] = 9;t[0, 1]=2;t[1, 2]=2;t[0, 3]=2
# t[0, 0] = 2;t[0, 1]=2;t[0, 2]=4;t[1, 3]=1
torch.zeros(tensor6.shape, dtype=torch.int64).scatter_(dim=0, index=torch.LongTensor([[0, 1, 0, 1], [1, 0, 1, 0], [0, 0, 0, 1]]), src=tensor6)
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [0, 0, 0, 0]])

获取指定的行和列

1
tensor4
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [3, 2, 0, 6]])
1
2
# 获取指定的行
torch.index_select(tensor4, 0, torch.LongTensor([0, 2])) # <==> tensor4[[0, 2], :]
tensor([[2, 0, 2, 8],
        [3, 2, 0, 6]])
1
2
# 获取指定的列
torch.index_select(tensor4, 1, torch.LongTensor([1, 3])) # <==> tensor4[:, [1, 3]]
tensor([[0, 8],
        [7, 0],
        [2, 6]])

使用掩膜获取指定元素

1
tensor4
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [3, 2, 0, 6]])
1
2
3
# 生成掩膜
mask = torch.BoolTensor((tensor4>4).bool())
mask
1
2
3
tensor([[False, False, False,  True],
[ True, True, False, False],
[False, False, False, True]])
1
2
# 使用掩膜提取tensor4中数据
torch.masked_select(tensor4, mask)
tensor([8, 6, 7, 6])

维度修改

维度交换

1
tensor4
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [3, 2, 0, 6]])
1
tensor4.shape
torch.Size([3, 4])
1
tensor4 = tensor4.transpose(0, 1)
1
tensor4.shape
torch.Size([4, 3])

维度重排

1
2
3
# 维度重排,该方法支持对张量多个维度进行重新排列
tensor4 = tensor4.permute(1, 0)
tensor4
tensor([[2, 0, 2, 8],
        [6, 7, 2, 0],
        [3, 2, 0, 6]])
1
2
3
4
5
6

[3, 4, 2] -> [4, 2, 3]
transpose(0, 1) transpose(1, 2)
transpose:[3 ,4 ,2] -> [4, 3, 2] -> [4, 2, 3]
permute(1, 2, 0)
permute: [3, 4, 2] -> [4, 2, 3]

增加维度

1
tensor4.shape
torch.Size([3, 4])
1
2
tensor41 = tensor4.unsqueeze(1).unsqueeze(-1)  # 增加维度
tensor41.shape
torch.Size([3, 1, 4, 1])

降低维度

1
tensor41.squeeze(dim=1).shape  # dim指定删除的维度位置
torch.Size([3, 4, 1])
1
tensor41.shape
torch.Size([3, 1, 4, 1])
1
tensor41.squeeze().shape  # 当不指定具体维度时会将所有维度为1的维度删除
torch.Size([3, 4])

删除维度

删除维度与降低维度的不同点在于,降低维度只能够将维度为1的维度删除,而删除维度会强制删除某个维度,如果维度不为1,那么会沿着该维度进行切分

1
tensor4.unbind(0)  # 例如将dim=0的维度删除,而tensor4原始有3行,所以最后删除该维度时会生成3个张量,每个张量就是一行。
1
(tensor([2, 0, 2, 8]), tensor([6, 7, 2, 0]), tensor([3, 2, 0, 6]))

张量计算操作

张量简单计算

1
2
# 尺寸相同时可以直接对应元素相运算
tensor5 - tensor4
tensor([[10, 13, 17,  4],
        [ 5,  3, 17, 10],
        [14, 15, 13, 11]])
1
2
# 维度不同时,支持广播计算操作
tensor7 = torch.randn(size=(4,))
1
2
3
print("tensor4:", tensor4.shape)
print("tensor7:", tensor7.shape)
print("tensor4 - tensor7:\n", tensor4 - tensor7)
1
2
3
4
5
6
tensor4: torch.Size([3, 4])
tensor7: torch.Size([4])
tensor4 - tensor7:
tensor([[ 1.9346, 0.1155, 1.3009, 7.8812],
[ 5.9346, 7.1155, 1.3009, -0.1188],
[ 2.9346, 2.1155, -0.6991, 5.8812]])
1
2
3
4
# 查看广播计算张量的变化结果
tensor4b, tensor7b = torch.broadcast_tensors(tensor4, tensor7)
print("tensor4b:", tensor4b.shape)
print("tensor7b:", tensor7b.shape)
tensor4b: torch.Size([3, 4])
tensor7b: torch.Size([3, 4])
1
2
3
# 在计算的时候必须保证所有的张量位于同一设备
tensor42 = tensor4.to('cuda:0')
tensor42.device
device(type='cuda', index=0)
1
tensor4 - tensor42  # 不在同一个设备在进行计算时会发生报错
1
2
3
4
5
6
7
8
9
---------------------------------------------------------------------------

RuntimeError Traceback (most recent call last)

Cell In[98], line 1
----> 1 tensor4 - tensor42 # 不在同一个设备在进行计算时会发生报错


RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

矩阵乘法

1
2
3
tensor81 = torch.randn(size=(5, 2))
tensor82 = torch.randn(size=(2, 10))
(tensor81 @ tensor82).shape
torch.Size([5, 10])

限定张量元素值范围

将输入input张量每个元素的夹紧到区间 [min,max],并返回结果到一个新张量

1
2
3
a = torch.randn(2, 4)
print(a)
torch.clamp(a, -0.5, 0.5)
1
2
3
4
5
tensor([[ 1.6036,  0.6247,  0.4567, -0.4334],
[ 0.4349, 0.7140, -1.7777, -1.5939]])

tensor([[ 0.5000, 0.5000, 0.4567, -0.4334],
[ 0.4349, 0.5000, -0.5000, -0.5000]])

向下取整

1
2
3
a = torch.randn(4)
print(a)
torch.floor(a)
1
2
tensor([ 0.3045, -0.6240, -2.2791, -0.5166])
tensor([ 0., -1., -3., -1.])

向上取整

1
torch.ceil(a)
tensor([ 1., -0., -2., -0.])

计算除法并获取余数

1
torch.fmod(torch.Tensor([-3, -2, -1, 1, 2, 3]), 2)
1
tensor([-1., -0., -1.,  1.,  0.,  1.])

获取浮点数小数部分

1
torch.frac(torch.Tensor([1., 2.5, -3.2]))
tensor([ 0.0000,  0.5000, -0.2000])

线性插值

1
2
3
4
start = torch.arange(1., 5.)
end = torch.ones((4,)) * 10
print(start)
print(end)
tensor([1., 2., 3., 4.])
tensor([10., 10., 10., 10.])
1
torch.lerp(start, end, 0.5)
tensor([5.5000, 6.0000, 6.5000, 7.0000])

Pytorch自动求导机制

在Pytorch中每个张量都有一个requires_grad属性去控制该张量在进行计算的时候是否需要求出计算梯度。当我们需要求某个张量在计算过程中的梯度,只需将requires_grad设置为True即可。

在进行相关计算后,调用结果张量的backward()方法即可将在计算过程中涉及到的所有张量的梯度计算出来。

要查看某个张量对于结果张量的梯度,只需调用张量的grad属性即可。

1
2
x = torch.tensor([2.0], requires_grad=True)
a = torch.tensor([4.0], requires_grad = True)
1
2
3
# 初始状态下grad参数值为None
print(x.grad)
print(a.grad)
None
None
1
2
# 执行计算
y = x * a
1
2
# 反向传播,计算梯度
y.backward()
1
2
3
# 查看执行计算后的梯度
print(x.grad)
print(a.grad)
tensor([4.])
tensor([2.])
1
2
# 再次计算,会发生梯度累加,变量的梯度不会自动归零
y = x * a
1
2
3
4
5
# 反向传播,计算梯度
y.backward()
# 查看执行计算后的梯度
print(x.grad)
print(a.grad)
tensor([8.])
tensor([4.])

其他

GPU相关

1
torch.cuda.current_device()  # 查看当前GPU编号
0
1
torch.cuda.is_available()  # 查看当前GPU是否可用
True
1
torch.cuda.device_count()  # 查看可用GPU数量
1
1
torch.cuda.get_device_name(0)  # 查看当前GPU型号
'NVIDIA GeForce MX450'
1
torch.cuda.set_device(0)  # 设置当前使用的GPU,只有在有多张显卡时才使用
1
2
3
# 设置GPU可见性,当有多个GPU时,只想要程序访问其中某几个GPU这个时候可以设置环境变量
import os
os.environ['CUDA_VISIBLE_DEVICES'] = "0,1" # 设备之间使用,进行隔开

CPU并行化线程数设置

1
2
# 默认情况下,OpenMP 线程数通常设置为系统上可用的 CPU 核心数
torch.get_num_threads() # 查看当前OpenMP线程数
4
1
torch.set_num_threads(8)  # 设置当前OpenMP线程数
-------------本文结束感谢您的阅读-------------