Tensor的操作1(索引、切片、维度变换)

目录

  • 索引
    • select by index
    • 选择性的获取元素
    • 对指定维度采样指定的元素
    • 省略性写法
    • 带mask的选法
    • 先将tensor打平再选择
  • Tensor的维度变换
    • view
    • squeeze and unsqueeze
      • unsqueeze
      • squeeze
    • repeat and expand
    • transpose and permute
      • transpose
      • permute

索引

select by index

In [1]: import torch

In [2]: a = torch.rand(4,3,28,28)  # 随机生成一个4*3*28*28的tensor

In [3]: a[0].shape  # 第0维的第1个元素的size
Out[3]: torch.Size([3, 28, 28])

In [4]: a[0,0].shape
Out[4]: torch.Size([28, 28])

In [5]: a[0,0,2,4]
Out[5]: tensor(0.4495)

选择性的获取元素

In [6]: a.shape
Out[6]: torch.Size([4, 3, 28, 28])

In [7]: a[:2].shape  # 从开头取到2(不包括2)
Out[7]: torch.Size([2, 3, 28, 28])

In [8]: a[:2,:1].shape
Out[8]: torch.Size([2, 1, 28, 28])

In [9]: a[:2,1:].shape
Out[9]: torch.Size([2, 2, 28, 28])

In [10]: a[:2,-1:].shape  # 最后一个元素取到最末尾
Out[10]: torch.Size([2, 1, 28, 28])

In [11]: a[:,:,0:28:2,0:28:2].shape  # 取元素的step为2
Out[11]: torch.Size([4, 3, 14, 14])

对指定维度采样指定的元素

In [12]: a.index_select(0, torch.tensor([0,2])).shape  # 对第0维采样0,2
Out[12]: torch.Size([2, 3, 28, 28])

In [13]: a.index_select(1, torch.tensor([0,2])).shape
Out[13]: torch.Size([4, 2, 28, 28])

In [14]: a.index_select(2,torch.arange(28)).shape
Out[14]: torch.Size([4, 3, 28, 28])

省略性写法

In [22]: a[...].shape
Out[22]: torch.Size([4, 3, 28, 28])

In [23]: a[0,...].shape
Out[23]: torch.Size([3, 28, 28])

In [24]: a[:,1,...].shape
Out[24]: torch.Size([4, 28, 28])

带mask的选法

In [27]: x = torch.randn(3,4)

In [28]: x
Out[28]:
tensor([[ 0.1600,  1.1167, -0.5031, -2.0422],
        [ 0.0912, -0.7644,  0.8397, -0.3581],
        [ 1.1684, -0.9302, -1.4750,  0.0792]])

In [29]: mask = x.ge(0.5)

In [30]: mask
Out[30]:
tensor([[False,  True, False, False],
        [False, False,  True, False],
        [ True, False, False, False]])

In [31]: torch.masked_select(x,mask)
Out[31]: tensor([1.1167, 0.8397, 1.1684])

先将tensor打平再选择

In [32]: src = torch.tensor([4,3,5],[6,7,8])

In [35]: torch.take(src,torch.tensor([0,2,5]))
Out[35]: tensor([4, 5, 8])

Tensor的维度变换

view

In [1]: import torch

In [2]: a=torch.rand(4,1,28,28)

In [3]: a.shape
Out[3]: torch.Size([4, 1, 28, 28])

In [4]: a.view(4,28*28)
Out[4]:
tensor([[0.3681, 0.6182, 0.5406,  ..., 0.3441, 0.7353, 0.7404],
        [0.0606, 0.1527, 0.5305,  ..., 0.3635, 0.2176, 0.1675],
        [0.2906, 0.9702, 0.5708,  ..., 0.5743, 0.3238, 0.8871],
        [0.4259, 0.3133, 0.3642,  ..., 0.1067, 0.6268, 0.1117]])

In [5]: a.view(4,28*28).shape
Out[5]: torch.Size([4, 784])

In [6]: a.view(4*28,28).shape
Out[6]: torch.Size([112, 28])

注意:
1.view变换前后的总体size要相等
2.会丢失数据的维度信息,不方便恢复

# 维度信息有问题的报错
In [8]: a.view(4,743)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-8-9ba94a9550d8> in <module>
----> 1 a.view(4,743)

RuntimeError: shape '[4, 743]' is invalid for input of size 3136

squeeze and unsqueeze

unsqueeze

在指定的位置增加一个维度
注意:Tensor从头到尾的index是从0开始,从尾到头的index是从-1开始

In [12]: a.shape
Out[12]: torch.Size([4, 1, 28, 28])

In [13]: a.unsqueeze(0).shape
Out[13]: torch.Size([1, 4, 1, 28, 28])

In [14]: a.unsqueeze(-1).shape
Out[14]: torch.Size([4, 1, 28, 28, 1])

In [15]: a.unsqueeze(3).shape
Out[15]: torch.Size([4, 1, 28, 1, 28])

In [16]: a.unsqueeze(-4).shape
Out[16]: torch.Size([4, 1, 1, 28, 28])

In [17]: a.unsqueeze(5).shape
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-17-b54eab361a50> in <module>
----> 1 a.unsqueeze(5).shape

IndexError: Dimension out of range (expected to be in range of [-5, 4], but got 5)

In [18]:

如果要将两个维度不一样的tensor相加则要用到unsqueeze

In [18]: b = torch.rand(32)

In [19]: f = torch.rand(4,32,14,14)

In [22]: b= b.unsqueeze(1).unsqueeze(2).unsqueeze(0)

In [23]: b.shape
Out[23]: torch.Size([1, 32, 1, 1])

squeeze

In [24]: b.shape
Out[24]: torch.Size([1, 32, 1, 1])

In [25]: b.squeeze().shape  # 把能压缩的都压缩了
Out[25]: torch.Size([32])

In [26]: b.squeeze(0).shape
Out[26]: torch.Size([32, 1, 1])

In [27]: b.squeeze(-2).shape
Out[27]: torch.Size([1, 32, 1])

repeat and expand

expand:不主动复制数据
`repeat``:直接复制数据

In [34]: a=torch.rand(4,32,14,14)

In [35]: b.shape
Out[35]: torch.Size([1, 32, 1, 1])

In [36]: b.expand(4,32,14,14).shape
Out[36]: torch.Size([4, 32, 14, 14])

repeat表示拷贝数据的次数

In [37]: b.shape
Out[37]: torch.Size([1, 32, 1, 1])

In [38]: b.repeat(4,32,1,2).shape
Out[38]: torch.Size([4, 1024, 1, 2])

transpose and permute

transpose

a.transpose(d1,d2)只能转换两个维度

In [39]: a=torch.rand(4,3,28,28)

In [40]: a.transpose(1,3).shape
Out[40]: torch.Size([4, 28, 28, 3])

permute

随意变化多个维度

In [41]: a=torch.rand(4,3,28,28)

In [42]: a.shape
Out[42]: torch.Size([4, 3, 28, 28])

In [43]: a.permute(0,3,2,1).shape
Out[43]: torch.Size([4, 28, 28, 3])

你可能感兴趣的:(学习记录,pytorch)