pytorch 向量操作
pytorch
本文字数:2.8k 字 | 阅读时长 ≈ 13 min

pytorch 向量操作

pytorch
本文字数:2.8k 字 | 阅读时长 ≈ 13 min

1. torch.max

pytorch 官方文档
pytorch 的 torch.max 函数有两种用法: 一种是不带任何参数的,他返回的是 tensor 中所有元素的最大值;第二种是带参数的,他返回最大值和对应的索引,这里分别介绍

  1. 第一种 torch.max(input)
    返回所有元素的最大值
a = torch.rand((2, 3, 4))
b = torch.max(a)

'''
tensor([[[0.0615, 0.7280, 0.3775, 0.9397],
         [0.4438, 0.1904, 0.1330, 0.5213],
         [0.5054, 0.9993, 0.3916, 0.7125]],

        [[0.2660, 0.9682, 0.8774, 0.0991],
         [0.6073, 0.2710, 0.8681, 0.8080],
         [0.4416, 0.5851, 0.0409, 0.3030]]])
tensor(0.9993)
'''
  1. *第二种 torch.max(input, dim, keepdim=False, , out=None)
    返回对应维度元素的最大值以及对应的索引
a = torch.rand((2, 3, 4))
b = torch.max(a, dim=1)

'''
tensor([[[0.9463, 0.7360, 0.0537, 0.5537],
         [0.0405, 0.5534, 0.4716, 0.0500],
         [0.2060, 0.6482, 0.8448, 0.0171]],

        [[0.7581, 0.5042, 0.1960, 0.0650],
         [0.2035, 0.8434, 0.2853, 0.1112],
         [0.9866, 0.3353, 0.2400, 0.5643]]])

torch.return_types.max(
values=tensor([[0.9463, 0.7360, 0.8448, 0.5537],
               [0.9866, 0.8434, 0.2853, 0.5643]]),
indices=tensor([[0, 0, 2, 0],
                [2, 1, 1, 2]]))
'''

这个例子可以看出,dim=1 计算的是 3 那一维的最大值,可以看出 0.9463=max(0.9463, 0.0405, 0.2060)
然后我们通过下面这个例子看一下 keepdim 的作用

c = torch.max(a, dim=1, keepdim=True)
'''
torch.return_types.max(
values=tensor([[[0.9463, 0.7360, 0.8448, 0.5537]],
                [[0.9866, 0.8434, 0.2853, 0.5643]]]),
indices=tensor([[[0, 0, 2, 0]],
                [[2, 1, 1, 2]]]))
torch.Size([2, 1, 4])  # c[0].size()
'''

可以发现最后 c 的维度还是三维,不过求 max 的那一维度从 3 变成了 1

2. torch.mean

pytorch 官方文档
pytorch 的 torch.mean 函数有两种用法: 一种是不带任何参数的,他返回的是 tensor 中所有元素的均值;第二种是带参数的,他返回某一维度的均值,这里分别介绍

  1. 第一种 torch.mean(input)
    返回所有元素的均值
a = torch.rand(2,2)
b = torch.mean(a)
'''
tensor([[0.8782, 0.3101],
        [0.9752, 0.9772]])
tensor(0.7852)
'''
  1. *torch.mean(input, dim, keepdim=False, , out=None)
    返回对应维度元素的均值
a = torch.rand((2,3,4))
b = torch.mean(a, dim=1)
'''
tensor([[[0.9809, 0.6421, 0.6771, 0.9645],
         [0.5214, 0.8376, 0.8131, 0.7947],
         [0.1607, 0.3469, 0.9644, 0.9500]],

        [[0.1877, 0.3958, 0.1021, 0.7560],
         [0.4673, 0.8111, 0.9186, 0.6773],
         [0.4850, 0.8042, 0.1683, 0.2345]]])
tensor([[0.5543, 0.6088, 0.8182, 0.9031],
        [0.3800, 0.6704, 0.3963, 0.5559]])
'''

这个例子可以看出,dim=1 计算的是 3 那一维的最大值,可以看出 0.5543=mean(0.9809, 0.5214, 0.1607),此时维度从(2,3,4)变为了(2,4)
然后我们通过下面这个例子看一下 keepdim 的作用

c = torch.max(a, dim=1, keepdim=True)
'''
tensor([[[0.5543, 0.6088, 0.8182, 0.9031]],
        [[0.3800, 0.6704, 0.3963, 0.5559]]])
torch.Size([2, 1, 4])  # c[0].size()
'''

发现最后 c 的维度还是三维,不过求 mean 的那一维度从 3 变成了 1

3. torch.meshgrid

创建网格坐标 torch.meshgrid(*tensors)

返回:两个矩阵

直接看两个例子理解,第一个展示输入输出,第二个便于理解为什么可以创建网格坐标

  1. 第一个
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6, 7])
grid_x, grid_y = torch.meshgrid(x, y)
print("grid_x: ", grid_x)
print("grid_y: ", grid_y)
print(torch.equal(torch.cat(tuple(torch.dstack([grid_x, grid_y]))), torch.cartesian_prod(x, y)))
'''
grid_x:  
tensor([[1, 1, 1, 1],
        [2, 2, 2, 2],
        [3, 3, 3, 3]])
grid_y:  
tensor([[4, 5, 6, 7],
        [4, 5, 6, 7],
        [4, 5, 6, 7]])
True
'''
  1. 第二个演示绘图
    可以看到x,y就直接定义了其横纵坐标,下面的x,y,z均为 2 维
xs = torch.linspace(-5, 5, steps=100)
ys = torch.linspace(-5, 5, steps=100)
x, y = torch.meshgrid(xs, ys)
z = torch.sin(torch.sqrt(x * x + y * y))
ax = plt.axes(projection='3d')
ax.plot_surface(x.numpy(), y.numpy(), z.numpy())
plt.show()

4. torch.numel/nelement

返回输入向量的总的元素个数。有两种使用方法,一种是 Tensor 的内置属性 nelement,一种是 torch.numel 方法

  1. nelement
>>> import torch
>>> a = torch.zeros(4,4)
>>> a.nelement()
16
  1. torch.numel
>>> import torch
>>> a = torch.zeros(4,4)
>>> torch.numel(a)
16

5. torch.topk

求最大概率的值 torch.topk(input, k, dim=None, largest=True, sorted=True, *, out=None)
topk 最适合的场合是在分类场合,即网络输出多个概率,求哪个概率最大

  1. 求概率值最大的一个
pred = torch.randn((4, 5))
print(pred)
values, indices = torch.topk(pred, 1, dim=1, largest=True, sorted=True)
print(values)
print(indices)

'''
tensor([[ 0.2613,  0.5201, -0.4399,  0.4685, -0.4480],
        [ 3.1005,  0.9732,  1.3342,  0.2227,  0.7779],
        [-0.0579, -0.6568, -0.0449, -0.9981, -0.5214],
        [ 1.0117, -1.8550, -0.3959, -0.2788,  0.0235]])
tensor([[ 0.5201],
        [ 3.1005],
        [-0.0449],
        [ 1.0117]])
tensor([[1],
        [0],
        [2],
        [0]])
'''
  1. 求概率值最大的前两个
pred = torch.randn((4, 5))
print(pred)
values, indices = torch.topk(pred, 2, dim=1, largest=True, sorted=True)  # k=2
print(values)
print(indices)

'''
tensor([[ 0.0563,  0.3252, -1.0762, -0.7007, -1.1439],
        [-1.2144,  0.5950,  0.9980, -1.5938, -0.0694],
        [ 0.3070, -0.6079, -1.6469,  1.6252,  1.3092],
        [-0.8918, -0.5781, -0.9604,  0.1942,  1.2415]])
tensor([[0.3252, 0.0563],
        [0.9980, 0.5950],
        [1.6252, 1.3092],
        [1.2415, 0.1942]])
tensor([[1, 0],
        [2, 1],
        [3, 4],
        [4, 3]])
'''

6. torch.squeeze/unsqueeze

torch.squeeze() 以及 torch.unsqueeze() 函数分别是给目标 tensor 去掉维度只有 1 的那一维或者给目标的某一维度添加一维

  1. torch.squeeze
    将输入的 tensor 中维度为 1 的那一维去除 torch.squeeze(input, dim=None)
>>> x = torch.zeros(2, 1, 2, 1, 2)
torch.Size([2, 1, 2, 1, 2])  # x.size()
>>> y = torch.squeeze(x)
torch.Size([2, 2, 2])  # y.size()
>>> y = torch.squeeze(x, 0)
torch.Size([2, 1, 2, 1, 2])  # y.size()
>>> y = torch.squeeze(x, 1)
torch.Size([2, 2, 1, 2])  # y.size()

''' in-place version '''
>>> x.squeeze_()
  1. torch.unsqueeze
    将 tensor 的某一维增加 1torch.unsqueeze(input, dim=None)
>>> x = torch.tensor([1, 2, 3, 4])
torch.Size([4])  # x.size()
>>> y1 = torch.unsqueeze(x, 0)
torch.Size([1, 4])  # y1.size()
>>> y2 = torch.unsqueeze(x, 1)
torch.Size([4, 1])  # y2.size()

''' in-place version '''
x.unsqueeze_(0)

7. torch.repeat_interleave

pytorch 官方文档

torch.repeat_interleave(input, repeats, dim=None, *, output_size=None)

  1. 默认的,不给 dim 参数,将 tensor 展平
>>> x = torch.tensor([1, 2, 3])
>>> torch.repeat_interleave(x, 2)
tensor([1, 1, 2, 2, 3, 3])
>>> y = torch.tensor([[1, 2], [3, 4]])
>>> torch.repeat_interleave(y, 2)
tensor([1, 1, 2, 2, 3, 3, 4, 4])
  1. 给定 dim,会在给定的维度将其展平重复,元素是逐个重复的,如下,对 1 重复三次,2 重复三次,以此类推
>>> y = torch.tensor([[1, 2], [3, 4]])
>>> torch.repeat_interleave(y, 3, dim=1)
tensor([[1, 1, 1, 2, 2, 2],
        [3, 3, 3, 4, 4, 4]])
  1. 对不同元素指定重复次数
>>> y = torch.tensor([[1, 2], [3, 4]])
>>> torch.repeat_interleave(y, torch.tensor([1, 2]), dim=0)
tensor([[1, 2],
        [3, 4],
        [3, 4]])
  1. 此函数也支持 tensor.repeat_interleave()的形式
>>> x = torch.tensor([1, 2, 3])
>>> x.repeat_interleave(2)
tensor([1, 1, 2, 2, 3, 3])

8. torch.scatter

torch.scatter(input, dim, index, src)src 中的数据根据 index 中的索引按照 dim 的方向填入到 input 中

看了上述的官方文档还是不理解,我们继续看官方的例子,这里官方只给了三维,我在这里又加入了二维,在这之前有一个规定

  1. 二维举例
    self[index[i][j]][j] = src[i][j] # if dim == 0
    self[i][index[i][j]] = src[i][j] # if dim == 1
>>> torch.manual_seed(0)
>>> x = torch.arange(0, 12).reshape(2, 6)
>>> x= x.type(torch.float32)
tensor([[ 0.,  1.,  2.,  3.,  4.,  5.],
        [ 6.,  7.,  8.,  9., 10., 11.]])

>>> index = torch.tensor([[0, 1, 2, 0, 0], [2, 0, 0, 1, 2]])
tensor([[0, 1, 2, 0, 0],
        [2, 0, 0, 1, 2]])

>>> y = torch.zeros(3, 6)
>>> y = torch.scatter(y, 0, index, x)
tensor([[ 0.,  7.,  8.,  3.,  4.,  0.],
        [ 0.,  1.,  0.,  9.,  0.,  0.],
        [ 6.,  0.,  2.,  0., 10.,  0.]])

'''in-place operation'''
>>> yy = torch.zeros(3, 6)
>>> yy.scatter_(0, index, x)
tensor([[ 0.,  7.,  8.,  3.,  4.,  0.],
        [ 0.,  1.,  0.,  9.,  0.,  0.],
        [ 6.,  0.,  2.,  0., 10.,  0.]])

下面将上述的执行过程绘制出来

9月 09, 2024
9月 06, 2024