测试环境版本:
torch1.7.1 + CPU

python 3.6

import torch as t

a = t.randn(3,4)
a
tensor([[-1.0903, -0.1344, -0.5718,  1.2680],
        [ 0.5682, -0.1281,  0.5143, -0.7280],
        [-1.5264,  0.2746,  0.4163, -1.2645]])

一、Tensor的访问与索引

1、整行/整列的访问

a[1] # 第1行
tensor([ 0.5682, -0.1281,  0.5143, -0.7280])
a[:2] # 前两行
tensor([[-1.0903, -0.1344, -0.5718,  1.2680],
        [ 0.5682, -0.1281,  0.5143, -0.7280]])
a[:,0]# 第0列
tensor([-1.0903,  0.5682, -1.5264])
a[:,-1]# 最后一列
tensor([ 1.2680, -0.7280, -1.2645])
a[1:3,0:2]#1、2行,0、1列
tensor([[ 0.5682, -0.1281],
        [-1.5264,  0.2746]])

特别注意下面这两行:两者是有区别的
前者会保持在矩阵中的形状
后者会处理成一维数据

print(a[0:1,:2])
print(a[0,:2])
tensor([[-1.0903, -0.1344]])
tensor([-1.0903, -0.1344])

2、条件筛选

如:筛选出大于1的数据

a>1 # 返回一个byteTensor(布尔型数组)
tensor([[False, False, False,  True],
        [False, False, False, False],
        [False, False, False, False]])
a[a>1] # 筛选出大于1的数据
tensor([1.2680])
a.masked_select(a > 1) # 与前面的写法等效
tensor([1.2680])

选择结果与原tensor不共享内存

3、gather/scatter_

比较复杂:
我比较浅显的理解是:将input矩阵利用index矩阵映射到output矩阵上

'out[i][j] = input[index[i][j]][j] dim=0,此时index[i][j]充当行下标'
'out[i][j] = input[i][index[i][j]] dim=1,此时index[i][j]充当列下标'

a = t.arange(0,16).view(4,4)
a
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15]])

1)取对角线上的元素

# index = t.Tensor([[0,1,2,3]])报错,index必须是长整型(int64)
index = t.LongTensor([[0,1,2,3]])
a.gather(0,index)
tensor([[ 0,  5, 10, 15]])

2)取反对角线上的元素

index = t.LongTensor([[3,2,1,0]])
a.gather(0,index)
tensor([[12,  9,  6,  3]])

这是一个错误例子:

index = index.t()
a.gather(0,index)
tensor([[12],
        [ 8],
        [ 4],
        [ 0]])
a.gather(1,index)
tensor([[ 3],
        [ 6],
        [ 9],
        [12]])

scatter_

这是gather的逆操作,不再介绍

4、高级索引:

和numpy类似
高级索引的结果一般不和原张量共享内存

a = t.arange(0,27).view(3,3,3)
a
tensor([[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]],

        [[ 9, 10, 11],
         [12, 13, 14],
         [15, 16, 17]],

        [[18, 19, 20],
         [21, 22, 23],
         [24, 25, 26]]])
a[[0,1],[1,2],[1,2]]# a[0][1][1]和a[1][2][2]
tensor([ 4, 17])
a[[0,1,2],[1],[1]]# a[0][1][1],a[1][1][1],a[2][1][1]
tensor([ 4, 13, 22])
a[[0,2],...] # 居然还能用省略号...miao~
tensor([[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]],

        [[18, 19, 20],
         [21, 22, 23],
         [24, 25, 26]]])
a[[1],[1],...]
tensor([[12, 13, 14]])

二、 数据类型

数据类型

三、逐元素操作

绝大多数数学运算都有对应的方法,这里不一一列举,使用的时候直接百度吧。

a = a[0]
a
tensor([[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]],

        [[ 9, 10, 11],
         [12, 13, 14],
         [15, 16, 17]],

        [[18, 19, 20],
         [21, 22, 23],
         [24, 25, 26]]])

1、举例:

#t.cos(a) 这句报错,原因是长整形不能进行cos运算
a.type()
torch.Tensor
t.cos(a.float())
tensor([[[ 1.0000,  0.5403, -0.4161],
         [-0.9900, -0.6536,  0.2837],
         [ 0.9602,  0.7539, -0.1455]],

        [[-0.9111, -0.8391,  0.0044],
         [ 0.8439,  0.9074,  0.1367],
         [-0.7597, -0.9577, -0.2752]],

        [[ 0.6603,  0.9887,  0.4081],
         [-0.5477, -1.0000, -0.5328],
         [ 0.4242,  0.9912,  0.6469]]])
a**2 #等价于t.pow(a,2)
tensor([[[  0,   1,   4],
         [  9,  16,  25],
         [ 36,  49,  64]],

        [[ 81, 100, 121],
         [144, 169, 196],
         [225, 256, 289]],

        [[324, 361, 400],
         [441, 484, 529],
         [576, 625, 676]]])
a % 3 # 等价于a.fmod(a,3)
tensor([[[0, 1, 2],
         [0, 1, 2],
         [0, 1, 2]],

        [[0, 1, 2],
         [0, 1, 2],
         [0, 1, 2]],

        [[0, 1, 2],
         [0, 1, 2],
         [0, 1, 2]]])

2) clamp 数据截断

clamp(x,min,max)的取值如下:

t.clamp(a,5,10)
tensor([[[ 5,  5,  5],
         [ 5,  5,  5],
         [ 6,  7,  8]],

        [[ 9, 10, 10],
         [10, 10, 10],
         [10, 10, 10]],

        [[10, 10, 10],
         [10, 10, 10],
         [10, 10, 10]]])
t.clamp(a,min=10)
tensor([[[10, 10, 10],
         [10, 10, 10],
         [10, 10, 10]],

        [[10, 10, 11],
         [12, 13, 14],
         [15, 16, 17]],

        [[18, 19, 20],
         [21, 22, 23],
         [24, 25, 26]]])
t.clamp(a,max=10)
tensor([[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]],

        [[ 9, 10, 10],
         [10, 10, 10],
         [10, 10, 10]],

        [[10, 10, 10],
         [10, 10, 10],
         [10, 10, 10]]])

四、归并操作

此类操作使输出形状小于输入。一般是在某一维度上执行求和、求均值等操作。

a = t.arange(0,24).view(2,3,4)
a
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

        [[12, 13, 14, 15],
         [16, 17, 18, 19],
         [20, 21, 22, 23]]])
a.sum(dim=0)
tensor([[12, 14, 16, 18],
        [20, 22, 24, 26],
        [28, 30, 32, 34]])

1)dim介绍:

一般该类方法均有一个dim参数(对应numpy的axis参数)

从空间坐标轴上考虑,归并就像是投影操作

假设输入为(x,y,z)

  • dim=0 则输出为(1,y,z)或(y,z)
  • dim=1 则输出为(x,1,z)
  • dim=2 则输出为(x,y,1)

    2)其他的几个常用方法

    在某一维度上累加:
a = t.ones(3,3,3)
print(a)
print(a.cummax(dim=1))
tensor([[[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]],

        [[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]],

        [[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]]])
torch.return_types.cummax(
values=tensor([[[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]],

        [[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]],

        [[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]]]),
indices=tensor([[[0, 0, 0],
         [1, 1, 1],
         [2, 2, 2]],

        [[0, 0, 0],
         [1, 1, 1],
         [2, 2, 2]],

        [[0, 0, 0],
         [1, 1, 1],
         [2, 2, 2]]]))

求标准差:

a = t.randn(2,2,2)
print(a)
print(a.std())
print(a.std(dim=0))
tensor([[[-0.4520,  0.1512],
         [-0.3901, -1.9218]],

        [[ 0.9360,  1.1693],
         [ 1.4220,  0.0201]]])
tensor(1.0842)
tensor([[0.9814, 0.7199],
        [1.2813, 1.3731]])

可以看出,torch.randn生成的并不是严格的正态分布,仅仅是接近1