pytorch Tensor操作(二)

高级索引

PyTorch在0.2版本中完善了索引操作,目前已经支持绝大多数numpy的高级索引。高级索引可以看成是普通索引操作的扩展,但是高级索引操作的结果一般不和原始的Tensor贡献内出。

x = t.arange(0,27).view(3,3,3)
x
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.]]])
x[[1, 2], [1, 2], [2, 0]] # x[1,1,2]和x[2,2,0]
tensor([ 14.,  24.])
x[[2, 1, 0], [0], [1]] # x[2,0,1],x[1,0,1],x[0,0,1]
tensor([ 19.,  10.,   1.])
x[[0, 2], ...] # x[0] 和 x[2]
tensor([[[  0.,   1.,   2.],
         [  3.,   4.,   5.],
         [  6.,   7.,   8.]],

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

Tensor类型

tensor数据类型

Data type dtype CPU tensor GPU tensor
32-bit floating point torch.float32 or torch.float torch.FloatTensor torch.cuda.FloatTensor
64-bit floating point torch.float64 or torch.double torch.DoubleTensor torch.cuda.DoubleTensor
16-bit floating point torch.float16 or torch.half torch.HalfTensor torch.cuda.HalfTensor
8-bit integer (unsigned) torch.uint8 torch.ByteTensor torch.cuda.ByteTensor
8-bit integer (signed) torch.int8 torch.CharTensor torch.cuda.CharTensor
16-bit integer (signed) torch.int16 or torch.short torch.ShortTensor torch.cuda.ShortTensor
32-bit integer (signed) torch.int32 or torch.int torch.IntTensor torch.cuda.IntTensor
64-bit integer (signed) torch.int64 or torch.long torch.LongTensor torch.cuda.LongTensor

各数据类型之间可以互相转换,type(new_type)是通用的做法,同时还有floatlonghalf等快捷方法。CPU tensor与GPU tensor之间的互相转换通过tensor.cudatensor.cpu方法实现,此外还可以使用tensor.to(device)。Tensor还有一个new方法,用法与t.Tensor一样,会调用该tensor对应类型的构造函数,生成与当前tensor类型一致的tensor。torch.*_like(tensora) 可以生成和tensora拥有同样属性(类型,形状,cpu/gpu)的新tensor。 tensor.new_*(new_shape) 新建一个不同形状的tensor。

# 设置默认tensor,注意参数是字符串
t.set_default_tensor_type('torch.DoubleTensor')
a = t.Tensor(2,3)
a.dtype # 现在a是DoubleTensor,dtype是float64
torch.float64
# 恢复之前的默认设置
t.set_default_tensor_type('torch.FloatTensor')
# 把a转成FloatTensor,等价于b=a.type(t.FloatTensor)
b = a.float() 
b.dtype
torch.float32
c = a.type_as(b)
c
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]])
a.new(2,3) # 等价于torch.DoubleTensor(2,3),建议使用a.new_tensor
tensor([[ 4.6390e-310,  1.4147e+161,   1.4917e+20],
        [ 2.0093e+174,  1.4327e+228,  1.3404e-317]], dtype=torch.float64)
t.zeros_like(a) #等价于t.zeros(a.shape,dtype=a.dtype,device=a.device)
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]], dtype=torch.float64)
t.zeros_like(a, dtype=t.int16) #可以修改某些属性
tensor([[ 0,  0,  0],
        [ 0,  0,  0]], dtype=torch.int16)
t.rand_like(a)
tensor([[ 0.8882,  0.7037,  0.5756],
        [ 0.7113,  0.2868,  0.7597]], dtype=torch.float64)
a.new_ones(4,5, dtype=t.int)
tensor([[ 1,  1,  1,  1,  1],
        [ 1,  1,  1,  1,  1],
        [ 1,  1,  1,  1,  1],
        [ 1,  1,  1,  1,  1]], dtype=torch.int32)
a.new_tensor([3,4]) # 
tensor([ 3.,  4.], dtype=torch.float64)

逐元素操作

这部分操作会对tensor的每一个元素(point-wise,又名element-wise)进行操作,此类操作的输入与输出形状一致。常用的操作如表3-4所示。

函数 功能
abs/sqrt/div/exp/fmod/log/pow… 绝对值/平方根/除法/指数/求余/求幂…
cos/sin/asin/atan2/cosh… 相关三角函数
ceil/round/floor/trunc 上取整/四舍五入/下取整/只保留整数部分
clamp(input, min, max) 超过min和max部分截断
sigmod/tanh… 激活函数

对于很多操作,例如div、mul、pow、fmod等,PyTorch都实现了运算符重载,所以可以直接使用运算符。如a ** 2 等价于torch.pow(a,2), a * 2等价于torch.mul(a,2)

其中clamp(x, min, max)的输出满足以下公式:
y i = { m i n , if  x i < m i n x i , if  m i n x i m a x m a x , if  x i > m a x y_i = \begin{cases} min, & \text{if } x_i \lt min \\ x_i, & \text{if } min \le x_i \le max \\ max, & \text{if } x_i \gt max\\ \end{cases}
clamp常用在某些需要比较大小的地方,如取一个tensor的每个元素与另一个数的较大值。

a = t.arange(0, 6).view(2, 3)
t.cos(a)
tensor([[1.0000000000, 0.5403022766, -0.4161468446],
        [-0.9899924994, -0.6536436081, 0.2836622000]])
a % 3 # 等价于t.fmod(a, 3)
tensor([[ 0.,  1.,  2.],
        [ 0.,  1.,  2.]])
a ** 2 # 等价于t.pow(a, 2)
tensor([[  0.,   1.,   4.],
        [  9.,  16.,  25.]])
# 取a中的每一个元素与3相比较大的一个 (小于3的截断成3)
print(a)
t.clamp(a, min=3)
tensor([[ 0.,  1.,  2.],
        [ 3.,  4.,  5.]])

tensor([[ 3.,  3.,  3.],
        [ 3.,  4.,  5.]])
b = a.sin_() # 效果同 a = a.sin();b=a ,但是更高效节省显存
a
tensor([[0.0000000000, 0.8414709568, 0.9092974067],
        [0.1411200017, -0.7568024993, -0.9589242935]])

归并操作

此类操作会使输出形状小于输入形状,并可以沿着某一维度进行指定操作。如加法sum,既可以计算整个tensor的和,也可以计算tensor中每一行或每一列的和。

常用归并操作

函数 功能
mean/sum/median/mode 均值/和/中位数/众数
norm/dist 范数/距离
std/var 标准差/方差
cumsum/cumprod 累加/累乘

以上大多数函数都有一个参数**dim**,用来指定这些操作是在哪个维度上执行的。关于dim(对应于Numpy中的axis)的解释众说纷纭,这里提供一个简单的记忆方式:

假设输入的形状是(m, n, k)

  • 如果指定dim=0,输出的形状就是(1, n, k)或者(n, k)
  • 如果指定dim=1,输出的形状就是(m, 1, k)或者(m, k)
  • 如果指定dim=2,输出的形状就是(m, n, 1)或者(m, n)

size中是否有"1",取决于参数keepdimkeepdim=True会保留维度1。注意,以上只是经验总结,并非所有函数都符合这种形状变化方式,如cumsum

b = t.ones(2, 3)
b.sum(dim = 0, keepdim=True)
tensor([[ 2.,  2.,  2.]])
# keepdim=False,不保留维度"1",注意形状
b.sum(dim=0, keepdim=False)
tensor([ 2.,  2.,  2.])
b.sum(dim=1)
tensor([ 3.,  3.])
a = t.arange(0, 6).view(2, 3)
print(a)
a.cumsum(dim=1) # 沿着行累加
tensor([[ 0.,  1.,  2.],
        [ 3.,  4.,  5.]])
tensor([[  0.,   1.,   3.],
        [  3.,   7.,  12.]])

猜你喜欢

转载自blog.csdn.net/weixin_44510615/article/details/90050081