Pytorch——基础API用法总结

文章目录

  • Tensor
    • 一、Tensor维度等变换操作
      • 不同Tensor之间的合并与分离
        • 高级操作:将两个batch size>1的Tensor中的每一层对应组合在一起
      • 单个Tensor的维度变换
      • Tensor内存优化
    • 二、Tensor计算
      • Tensor乘法
      • Tensor 的归并运算
    • 三、Tensor条件索引等操作
      • Tensor排序
      • Tensor反转顺序
      • Tensor取最大值和最小值并返回索引
      • 对矩阵指定idx内容进行操作
      • idx索引矩阵
      • 条件对比,返回等大小的Bool矩阵
      • 统计tensor中满足条件元素的个数
        • 高级操作:将矩阵中大于某个阈值的元素index返回并取出对应元素组成新的矩阵(适用于深度学习检测类任务后处理)
    • 四、按照规则生成新的Tensor
    • 五、Tensor类型转换(与numpy、list、转换float、四舍五入等)
    • 六、Tensor平移和旋转
    • 七、Tensor训练
  • Module
    • 一、nn子模块
      • 计算坐标点距离(欧式距离)
    • 二、nn.functional
      • 线性插值
    • Pytorch数据相关操作
      • 生成随机数
  • 话外
    • Numpy中的ndarrays和Torch中的tensor有什么区别?

Pytorch Documentation

Tensor

一、Tensor维度等变换操作

不同Tensor之间的合并与分离

PyTorch常用张量切割和拼接方法

  • Tensor.cat()(指定维度进行合并)
x = torch.randn(B, C, W, H)
y = torch.cat([x, x],dim=-1)
y.shape # [B, C, W, 2H]
  • Tensor.stack()(指定并创建一个新维度进行合并)
x = torch.randn(B, C, W, H)
y = torch.stack([x, x],dim=0)
y.shape # [2, B, C, W, 2H]
  • Tensor.split()(指定并创建一个新维度进行合并)
x = torch.randn(B, C, 400, 200)
out = torch.split(x, split_size_or_sections=[200,200], dim=-2)
out # 是一个tuple,存储了分割后的tensor
out[0].shape # [B, C, 200, 200]
out[1].shape # [B, C, 200, 200]

高级操作:将两个batch size>1的Tensor中的每一层对应组合在一起

应用示例:B>1
Tensor A: [B, C, H, W]a为每个Tensor的每个batch:[1, C, H, W]
Tensor B: [B, C, H, W]b为每个Tensor的每个batch:[1, C, H, W]
目标 Tensor C: [2*B, C, H, W]
我们需要让Tensor AB组成新的Tensor C,但是Tensor C中每两个Batch中,第一个必须是Tensor A,第二个是Tensor B,即Tensor C的内容应为:[[a_1,b_1], [a_2, b_2], ... [a_n, b_n]]

Bs, Ch, H, W = 2, 1, 1, 1
A = torch.randn((Bs, Ch, H, W))
B = torch.randn((Bs, Ch, H, W))
C = torch.stack([A, B], dim=1).reshape(2*Bs, Ch, H,W)
'''
A: tensor([[[[0.1900]]], 		# a1
        [[[0.1169]]]])			# a2
B: tensor([[[[-0.1072]]],		# b1
        [[[-1.4745]]]])			# b2
C: tensor([[[[ 0.1900]]],		# a1
        [[[-0.1072]]],			# b1
        [[[ 0.1169]]],			# a2
        [[[-1.4745]]]])			# b2
'''

单个Tensor的维度变换

  • Tensor.view()(维度合并)
B, N, C, H, W = feat.shape
feat = feat.view(B, N, C, H*W)

其他小用法:

feat = torch.randn(3, 5)
feat1 = feat.view(3*5)
feat2 = feat1.view(3, 5)
print(feat == feat2)
# tensor([[True, True, True, True, True],
#         [True, True, True, True, True],
#         [True, True, True, True, True]])
  • Tensor.reshape()(交换 / 合并 / 扩展 维度)
B, C, H, W = feat.shape	# torch.Size([4, 256, 50, 100])
# 使用-1快速合并所有未指定维度
feat.reshape(B, C, -1)	# # torch.Size([4, 256, 5000])

  • Tensor.permute()(维度交换)
B, N, C, H, W = feat.shape
feat = feat.permute(1, 0, 3, 4, 2)
feat.shape # [N, B, H, W, C]
  • Tensor.unsqueeze()(扩展维度)
C, H, W = feat.shape
feat = feat.unsqueeze(0) # 在第0维扩展一个维度
feat.shape # [1, C, H, W]
  • Tensor.squeeze()(删除一个空维度)
1, C, H, W = feat.shape
feat = feat.squeeze(0) # 在第0维删除一个空维度
feat.shape # [C, H, W]
  • Tensor.repeat()(在某一维进行重复扩充)
x = torch.randn(1, 3, 224, 224)
y = x.repeat(3, 1, 1, 1)
y.shape # [3, 3, 224, 224]
  • Tensor.range()Tensor.arange()(产生一维数组)
    • torch.range(1,10)torch.arange(10)都产生了一个1维的数组,类型是
    • 二者不同的是:
      • range产生的长度是10-1+1=10 是由1到10组成的1维张量,类型float
      • arange产生的是10-1=9 由1-9组成的1维度张量 ,类型int
x = torch.range(1,10)	# 从1到10
y = torch.arange(1,10) 
x # tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.]) 
y # tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])

z = torch.arange(10)
z # tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Tensor内存优化

  • Tensor.contiguous()
    • 功能:Tensor.contiguous()函数不会对原始数据进行任何修改,而仅仅对其进行复制,并在内存空间上进行对齐,即在内存空间上,tensor元素的内存地址保持连续。
    • 意义: 这么做的目的是,在对tensor元素进行转换和维度变换等操作之后,元素地址在内存空间中保证连续性,在后续利用指针对tensor元素进行读取时,能够减少读取便利,提高内存空间优化。

二、Tensor计算

Tensor乘法

  • torch.matmul()
x = torch.randn(1, 3, 4, 3)
y = torch.randn(1, 3, 3, 1)
out = torch.matmul(x, y)
out.shape # [1, 3, 4, 1]

Tensor 的归并运算

Tensor 的归并运算(torch.mean、sum、median、mode、norm、dist、std、var、cumsum、cumprod)

  • Tensor.max()(指定某一维取最大值并合并)
B, N, C, H, W = feat.shape
feat = feat.max(dim=1)
feat.shape # [B, 1, C, H, W]
  • torch.sum()
  • torch.mean()
  • torch.median()
  • torch.mode()
  • torch.norm()
  • torch.dist()
  • torch.std()
  • torch.var()
  • torch.cumsum()
  • torch.cumprod()

三、Tensor条件索引等操作

Tensor排序

  • torch.topk()(可以指定获取前k个最大值的valueindex
    • input:tensor数据;
    • k:指明是得到前k个数据以及其index;
    • dim: 指定在哪个维度上排序, 默认是最后一个维度;
    • largest:如果为True,按照大到小排序; 如果为False,按照小到大排序;
input = torch.rand((20))	# [20]
# 获取前三最大值
>>> torch.topk(input, k=3)
torch.return_types.topk(
values=tensor([1.2594, 1.0634, 0.9596]),
indices=tensor([18,  1, 17]))
# 获取前三最小值
>>> torch.topk(a, k=3, largest=False)
torch.return_types.topk(
values=tensor([0.1799, 0.2691, 0.3302]),
indices=tensor([15, 13, 12]))
  • torch.sort()
>>> a = torch.Tensor([[5,4,1],[6,3,2]])  
>>> torch.sort(a)
torch.return_types.sort(
	values=tensor([[1., 4., 5.],
	        [2., 3., 6.]]),
	indices=tensor([[2, 1, 0],
	        [2, 1, 0]]))
  • 张量Tensor元素的排序

Tensor反转顺序

  • torch.flip()
>>> x = torch.arange(10).view(2, 5)
>>> x
tensor([[0, 1, 2, 3, 4],
        [5, 6, 7, 8, 9]])
>>> torch.flip(x, dims=[0])	# 对第0维进行反转
tensor([[5, 6, 7, 8, 9],
        [0, 1, 2, 3, 4]])

Tensor取最大值和最小值并返回索引

  • torch.max()torch.min()
    • input:表示输入的张量
    • dim:表示的是索引的维度,0和1分别表示列和行
    • 返回两个tensor,第一个tensor表示对应维度的最大/小值;第二个tensor表示最大/小值的索引

对矩阵指定idx内容进行操作

  • torch.tensor.index_put()
x = torch.ones((3, 3))
# index为列表, 存放[x_idx, y_idx]
index = [torch.LongTensor([0, 1, 0, 2]),
       	torch.LongTensor([0, 2, 2, 1])] # 生成索引
value = torch.Tensor([0, 3, 0, 0])
x1 = x.index_put(index, value)
>>> print(x1)
tensor([[0., 1., 0.],
        [1., 1., 3.],
        [1., 0., 1.]])

idx索引矩阵

  • torch.index_select()
>>> import torch
>>> a = torch.linspace(1, 12, steps=12).view((4, 3))
>>> print(a)
tensor([[ 1.,  2.,  3.],
        [ 4.,  5.,  6.],
        [ 7.,  8.,  9.],
        [10., 11., 12.]])
>>> print(torch.index_select(a, dim=0, torch.tensor([0, 3])))  # 提取第0个维度中的0和3
tensor([[ 1.,  2.,  3.],
       	[10., 11., 12.]])

条件对比,返回等大小的Bool矩阵

  • torch.gt()
  • torch.lt()
  • torch.eq()

参考文章:pytorch中torch.gt(),torch.lt(),torch.eq()

  • torch.where(condition, a, b)
    • 作用:按照一定的规则合并两个tensor类型
    • 输入参数:
      • condition:条件限制;如果满足条件,则选择a对应的值,否则选择b对应的值作为输出。
import torch
>>> a = torch.tensor([[0.0349,  0.0670],
         			  [-1.6719,  0.1242]])
>>> b = torch.tensor([[1,1],
         			 [1,1]])
>>> c = torch.where(a>0, a, b)     #合并a,b两个tensor,如果a中元素大于0,则c中与a对应的位置取a的值,否则取b的值
tensor([[0.0349, 0.0670],
        [1.0000, 0.1242]])

参考文章:Pytorch:Tensor的高阶操作【where(按条件取元素)、gather(查表取元素)、scatter_(查表取元素)】【可并行计算,提高速度】

统计tensor中满足条件元素的个数

  • torch.nonzero()+torch.numel()
    • 需要注意的是,统计时需要将tensor转换为一维向量,否则给出的结果是所有元素的个数,并不是满足条件的元素!
>>> a = torch.tensor([[0.0349,  0.0670],
         			  [-1.6719,  0.1242]])
>>> (a>0).reshape(-1).nonzero().numel()
3
# 错误示例:		没有reshape成一维向量导致输出为所有元素个数。
>>> (a>0).nonzero()
tensor([[0, 0],
        [0, 1],
        [1, 1]])
>>> (a>0).nonzero().numel()	
6

高级操作:将矩阵中大于某个阈值的元素index返回并取出对应元素组成新的矩阵(适用于深度学习检测类任务后处理)

一般在检测任务中,模型预测的输出都为(N, 4+1),N为预测box数,4为x,y,w,h,还有一个为类别。
本次我的点集预测任务中,我的预测结果为(N, 40+1),N为预测instance数,40为20组x,y点,还有一个为类别。
我需要通过confidence滤除掉小于阈值threshold的instance,然后再将其他符合要求的元素组成新的矩阵。

threshold = 0.5
pred_insts.shape # [6, 41]
pred_insts = torch.tensor(pred_insts[:,:-1], dtype=torch.float32)	# [6, 40]
pred_confidence = torch.tensor(pred_insts[:,-1:], dtype=torch.float32)   # [6, 1]
# 1.与阈值判断大小返回TrueFalse
pred_conf_index = pred_confidence[:,0] > threshold  #  shape: [6] 
# pred_conf_index: tensor([ True,  True, False, False,  True, False])
# 2.再通过nonzero并返回索引
pred_conf_index = pred_conf_index.nonzero()    # shape: [3, 1]
# pred_conf_index: tensor([[0], [1], [4]])
# 3.将其转化为一个一维tensor,方便索引
pred_conf_index = pred_conf_index.squeeze(-1)	# shape: [3]
# pred_conf_index: tensor([0, 1, 4])
# 4.利用索引获取符合要求的tensor
pred_insts = pred_insts.index_select(dim=0,index=pred_conf_index)	# [3, 40]

四、按照规则生成新的Tensor

  • Tensor.new_tensor()(生成一个指定大小,全部填充给定值的Tensor)
>>> tensor = torch.ones((2,), dtype=torch.int8)
>>> data = [[0, 1], [2, 3]]
>>> tensor.new_tensor(data)
tensor([[ 0,  1],
        [ 2,  3]], dtype=torch.int8)
  • Tensor.new_ones()(生成一个指定大小,全部填充1的Tensor)
  • Tensor.new_zeros()(生成一个指定大小,全部填充0的Tensor)
>>> tensor = torch.tensor((), dtype=torch.float64)
>>> tensor.new_zeros((2, 3))
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]], dtype=torch.float64)
  • Tensor.new_full()(生成一个指定大小,全部填充给定值的Tensor)
>>> tensor = torch.ones((2,), dtype=torch.float64)
>>> tensor.new_full((3, 4), 3.141592)
tensor([[ 3.1416,  3.1416,  3.1416,  3.1416],
        [ 3.1416,  3.1416,  3.1416,  3.1416],
        [ 3.1416,  3.1416,  3.1416,  3.1416]], dtype=torch.float64)
  • torch.linspace()(生成线性等间距一维数组)
#生成0到10的4个数构成的等差数列
a = torch.linspace(0,10,steps=4)
a # tensor([ 0.0000,  3.3333,  6.6667, 10.0000])

#生成0到10的5个数构成的等差数列
b = torch.linspace(0,10,steps=5)
b # tensor([ 0.0000,  2.5000,  5.0000,  7.5000, 10.0000])

五、Tensor类型转换(与numpy、list、转换float、四舍五入等)

  • torch.tensorPython
    • Tensor变量且只能为包含单个数据
x = torch.tensor([1], dtype=torch.int32)	# torch.int32
>>> x.item()
>>> type(x) 	# int 1

>>>  x.numel() # int 1
  • torch.tensorlist
x = torch.randn(B, C, 400, 200)
y = x.numpy().tolist()  
y.shape # [B, C, 400, 200]
  • numpytorch.tensor
x = numpy.zeros((B, C, 400, 200))
y = torch.from_numpy(x)
y.shape # [B, C, 400, 200]
  • torch.tensornumpy
x = torch.randn(B, C, 400, 200)
y = x.numpy()
y.shape # [B, C, 400, 200]
  • listtorch.tensor
x = list([[1,2], [3,4]])
y = torch.tensor(x) # torch.tensor
y.shape # [2, 2]
  • torch.tensor转换类型
x = torch.tensor([1], dtype=torch.int32)	# torch.int32
x = x.type(torch.float32)
x.dtype 	# torch.float32
  • torch.tensor四舍五入
x = torch.tensor([[0.2, 1.6],
                  [0.4, 3.2],
                  [4.2, 2.4]]).round()
tensor([[0., 2.],
        [0., 3.],
        [4., 2.]])

六、Tensor平移和旋转

Pytorch中的仿射变换(affine_grid)

  • torch.nn.functional.affine_grid()
  • torch.nn.functional.grid_sample()

七、Tensor训练

  • torch.tensor.detach()(截断某个变量的梯度反传,到此为止;只反传此变量相关的前边部分梯度,之后涉及到该变量的梯度均不反传)

    • pytorch函数tensor.detach()

Module

一、nn子模块

  • nn.Embedding

    • 定义Embedding并初始化指定的参数:
reference_points = nn.Embedding(50, 2)	# 生成的reference point的shape为[50,2]

# 初始化参数
reference_points.requires_grad_(False)  # 首先在更改参数前,需要将其的梯度设置为False
# 给reference point的x设置为[0,1]之间的10个量(不包括0,1),并循环复制5份
reference_points.weight[:,0] = torch.linspace(0,1,12)[1:-1].unsqueeze(0).permute(1,0).repeat(1,5).view(self.num_inst_query, 1).squeeze(-1)
# 给reference point的y设置为[0,1]之间的5个量(不包括0,1),并循环复制10份
reference_points.weight[:,1] = torch.linspace(0,1,7)[1:-1].unsqueeze(0).repeat(10,1).view(self.num_inst_query, 1).squeeze(-1)
reference_points.requires_grad_(True)  # 在更改参数之后,需要将其的梯度设置为True,让其可以参数更新

理解:pytorch nn.Embedding的用法和理解

计算坐标点距离(欧式距离)

  • torch.nn.PairwiseDistance()(计算两个tensor中每个点的欧式距离
    • 只需要保证输入的两个Tensor’维度一致,且最后一维为2即可,前边的维度可以无限扩展,例如[bs, num_pts, 2]或者[num_pts, 2]
vec1 # [num_pts, 2]
vec2 # [num_pts, 2]

dist = torch.pairwise_distance(vec1, vec2) # [num_pts]

Pytorch计算距离(例如欧式距离)torch.nn.PairwiseDistance

二、nn.functional

线性插值

  • torch.nn.functional.interpolate()(各种线性插值函数)
    • 其他参考文章:F.interpolate——数组采样操作
    • 插值使用场景:
      • 对于x,y,z等坐标插值:用单线性插值
      • 对图像等2D Tensor插如内容值:用双线性插值
    • 单线性插值示例:
# 对一个[1, N, 2]的坐标序列插值
vec = torch.tensor([
    [1,2],
    [3,4],
    [5,6],
], dtype=torch.float32)	# [1, N, 2] N=3

# 插值方式1: 指定需要插值扩展的倍数
vec = vec.permute(0,2,1)	# [1, N, 2] -> [1, 2, N],对于1-D的坐标Tensor来说,我们需要插值扩展N
new_vec = F.interpolate(vec,
                        scale_factor=2,
                        mode="linear")
new_vec = new_vec.permute(0,2,1)  # [1,2N, 2]
>>> new_vec
tensor([[[1.0000, 2.0000],
         [1.5000, 2.5000],
         [2.5000, 3.5000],
         [3.5000, 4.5000],
         [4.5000, 5.5000],
         [5.0000, 6.0000]]])	# [1,6,2]

# 插值方式2: 
new_vec2 = F.interpolate(vec,
                        size=[10],	# 指定需要插值维度对应的输出维度
                        mode="linear") 
new_vec2 = new_vec2.permute(0,2,1)  # [1,10, 2]
>>> new_vec2 
tensor([[[1.0000, 2.0000],
         [1.0000, 2.0000],
         [1.5000, 2.5000],
         [2.1000, 3.1000],
         [2.7000, 3.7000],
         [3.3000, 4.3000],
         [3.9000, 4.9000],
         [4.5000, 5.5000],
         [5.0000, 6.0000],
         [5.0000, 6.0000]]])

Pytorch数据相关操作

生成随机数

  • torch.randperm:将0~n-1(包括0和n-1)随机打乱后获得的数字序列,函数名是random permutation缩写。
>>> torch.randperm(10)
tensor([2, 3, 6, 7, 8, 9, 1, 5, 0, 4])
  • torch.Generator
    • 通常不用手动实例化 torch.Generator, 当需要随机数时, PyTorch 会自动创建一个默认的 torch.Generator 实例;
    • 也可以手动指定使用 torch.Generator
# 方式一:自动创建
# 直接获取随机数(自动创建torch.Generator)
torch.manual_seed(0) # 设置随机数种子
torch.initial_seed() # 查看随机数种子 结果为 0
g_1 = torch.default_generator # 获取默认的 Generator 实例
g_1.initial_seed() # 通过实例调用 结果也为 0

# 方式二:手动指定
# 手动创建随机数生成器
G = torch.Generator()
G.manual_seed(1)
torch.randperm(5, generator=G)
# 结果也为 tensor([0, 4, 2, 3, 1])

话外

Numpy中的ndarrays和Torch中的tensor有什么区别?

  • 浅谈torch的tensor和Numpy的ndarrays

你可能感兴趣的:(pytorch,python)