Tensor数据类型

对比

Python PyTorch
Int IntTensor of size()
float FloatTensor of size()
Int array IntTensor of size [d1,d2,…]
Float array FloatTensor of size[d1,d2,…]
string

可以发现PyTorch并不支持string表示,但是我们可以使用如下两种方法在PyTorch 中表示string。

  • One-hot
  • Embedding
    • Word2vec
    • glove

这里不对以上两种方法展开进行讲解,大家感兴趣可以自行百度。

数据类型

PyTorch数据类型

最常用的一般是以下几种

  • FloatTensor
  • DoubleTensor
  • IntTensor
  • LongTensor
  • ByteTensor

数据类型推断

1
2
3
4
5
6
In [3]: a=torch.randn(2,3)
In [4]: a.type()
Out[4]: 'torch.FloatTensor'
In [5]: type(a)
Out[5]: torch.Tensor

  • type():打出当前tensor的数据类型
  • isinstance():检验当前数据是否为此类型
  • type(xxx):Python自带的类型检测,只能检测最基本数据类型

以下代码测试说明了,同一数据部署在CPU和GPU上数据类型是不一样的

1
2
3
4
5
In [7]: isinstance(a,torch.cuda.FloatTensor)
Out[7]: False
In [8]: a=a.cuda()
In [9]: isinstance(a,torch.cuda.FloatTensor)
Out[9]: True

标量的表示: Dim0

1
2
3
4
In [10]: torch.tensor(1.0)
Out[10]: tensor(1.)
In [11]: torch.tensor(1.3)
Out[11]: tensor(1.3000)

以下代码展示了shape,size(),dim()的使用方法。

其中输入19和21是常见的确定tensor维度的方法

1
2
3
4
5
6
7
8
9
In [17]: a=torch.tensor(1.3)
In [18]: a.shape
Out[18]: torch.Size([])
In [19]: len(a.shape)
Out[19]: 0
In [20]: a.size()
Out[20]: torch.Size([])
In [21]: a.dim()
Out[21]: 0

向量Vector:Dim1

一个元素的一维向量,其实就是多加了一个中括号,详情见下面的代码。

FloatTensor接收的参数是shape,然后随机初始化向量。

然后In [9]以后介绍了一种numpy转tensor的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [3]: torch.tensor([1.1])
Out[3]: tensor([1.1000])
In [4]: a=torch.tensor([1.1])
In [5]: a.dim()
Out[5]: 1
In [6]: torch.tensor([1.1,2.2])
Out[6]: tensor([1.1000, 2.2000])
In [7]: torch.FloatTensor(1)
Out[7]: tensor([0.])
In [8]: torch.FloatTensor(2)
Out[8]: tensor([0., 0.])
In [9]: import numpy as np
In [10]: data=np.ones(2)
In [11]: data
Out[11]: array([1., 1.])
In [12]: torch.from_numpy(data)
Out[12]: tensor([1., 1.], dtype=torch.float64)

矩阵Matrix:Dim2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [3]: a=torch.randn(2,3)
In [4]: a
Out[4]:
tensor([[-0.6969, 1.8345, -0.4894],
[-0.0066, -0.0398, -0.6140]])
In [5]: a.shape
Out[5]: torch.Size([2, 3])
In [6]: a.size(0)
Out[6]: 2
In [7]: a.size(1)
Out[7]: 3
In [8]: a.shape[1]
Out[8]: 3

在PyTorch中,randn是随机正态分布,而rand是随机均匀分布。

Dim3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [3]: a=torch.rand(1,2,3)
In [4]: a
Out[4]:
tensor([[[0.7603, 0.4443, 0.4788],
[0.0602, 0.6325, 0.8426]]])
In [5]: a.shape
Out[5]: torch.Size([1, 2, 3])

In [6]: a[0]
Out[6]:
tensor([[0.7603, 0.4443, 0.4788],
[0.0602, 0.6325, 0.8426]])
In [7]: a[0,1]
Out[7]: tensor([0.0602, 0.6325, 0.8426])
In [8]: a[0,1,0]
Out[8]: tensor(0.0602)

In [9]: list(a.shape)
Out[9]: [1, 2, 3]

三维的tensor一般用于RNN中

Dim4

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
In [3]: a=torch.rand(2,3,28,28)
In [4]: a.dim()
Out[4]: 4
In [5]: a
Out[5]:
tensor([[[[0.5255, 0.9019, 0.9471, ..., 0.7050, 0.4455, 0.8681],
[0.7229, 0.9215, 0.4863, ..., 0.4863, 0.5061, 0.3511],
[0.0015, 0.3703, 0.0695, ..., 0.7927, 0.0028, 0.5953],
...,
[0.3896, 0.5274, 0.7822, ..., 0.7864, 0.5558, 0.2190],
[0.8072, 0.7983, 0.8963, ..., 0.8586, 0.2881, 0.1836],
[0.7002, 0.4452, 0.8168, ..., 0.6467, 0.2885, 0.4928]],
[[0.5885, 0.6984, 0.6732, ..., 0.3300, 0.3039, 0.1747],
[0.2004, 0.1730, 0.4867, ..., 0.5207, 0.3391, 0.6586],
[0.0279, 0.1897, 0.5924, ..., 0.7152, 0.6622, 0.1943],
...,
[0.6697, 0.9150, 0.1786, ..., 0.6098, 0.8226, 0.2826],
[0.2074, 0.6030, 0.0912, ..., 0.9088, 0.1924, 0.6403],
[0.0557, 0.0836, 0.2382, ..., 0.4082, 0.0600, 0.5102]],
[[0.3708, 0.5273, 0.0810, ..., 0.8926, 0.5854, 0.7139],
[0.6355, 0.3067, 0.9933, ..., 0.7173, 0.0793, 0.3067],
[0.9277, 0.6752, 0.7401, ..., 0.6875, 0.4112, 0.9575],
...,
[0.2762, 0.6146, 0.9833, ..., 0.2625, 0.9879, 0.1417],
[0.1789, 0.9695, 0.6872, ..., 0.2485, 0.0840, 0.4170],
[0.5604, 0.1260, 0.8523, ..., 0.6334, 0.1975, 0.5056]]],
[[[0.9585, 0.5642, 0.2652, ..., 0.7171, 0.5738, 0.7511],
[0.0737, 0.4149, 0.1017, ..., 0.4772, 0.4125, 0.4467],
[0.6502, 0.9494, 0.1355, ..., 0.0834, 0.4446, 0.5004],
...,
[0.2966, 0.6502, 0.6373, ..., 0.6158, 0.9067, 0.0245],
[0.1544, 0.6203, 0.7105, ..., 0.5898, 0.9481, 0.7846],
[0.0048, 0.8663, 0.5166, ..., 0.7284, 0.1925, 0.2311]],
[[0.0852, 0.0139, 0.8834, ..., 0.6738, 0.1022, 0.8247],
[0.0161, 0.2121, 0.9729, ..., 0.2736, 0.3918, 0.5949],
[0.1229, 0.8208, 0.6334, ..., 0.0238, 0.5333, 0.0843],
...,
[0.9250, 0.3495, 0.2272, ..., 0.2272, 0.7861, 0.1189],
[0.7124, 0.8442, 0.6705, ..., 0.7530, 0.0809, 0.4165],
[0.5223, 0.0803, 0.3681, ..., 0.3973, 0.7163, 0.1920]],
[[0.1807, 0.7834, 0.5945, ..., 0.5394, 0.7165, 0.4785],
[0.8470, 0.0618, 0.2278, ..., 0.5901, 0.4242, 0.0087],
[0.9244, 0.1387, 0.8042, ..., 0.4879, 0.6511, 0.4556],
...,
[0.2453, 0.7729, 0.5773, ..., 0.7876, 0.7998, 0.5125],
[0.3097, 0.0141, 0.5490, ..., 0.2160, 0.4402, 0.9370],
[0.5274, 0.9141, 0.0378, ..., 0.9517, 0.8165, 0.6193]]]])
In [6]: a.shape
Out[6]: torch.Size([2, 3, 28, 28])

In [7]: a.numel()
Out[7]: 4704

numel函数的含义是number

of element,返回对应tensor中元素的个数

四维的tensor一般用于CNN中

创建Tensor

从numpy中导入数据

1
2
3
4
5
6
7
8
9
In [4]: a=np.array([2,3.3])
In [5]: torch.from_numpy(a)
Out[5]: tensor([2.0000, 3.3000], dtype=torch.float64)
In [6]: a=np.ones([2,3])
In [7]: torch.from_numpy(a)
Out[7]:
tensor([[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)

从List列表中导入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [3]: torch.tensor([2.,3.2])
Out[3]: tensor([2.0000, 3.2000])
In [4]: torch.FloatTensor([2.,3.2])
Out[4]: tensor([2.0000, 3.2000])
In [5]: torch.FloatTensor(2,3)
Out[5]:
tensor([[0., 0., 0.],
[0., 0., 0.]])
In [6]: torch.tensor([[2.,3.2],[1.,22.3]])
Out[6]:
tensor([[ 2.0000, 3.2000],
[ 1.0000, 22.3000]])
In [7]: torch.Tensor(2,3)
Out[7]:
tensor([[0., 0., 0.],
[0., 0., 0.]])

注意区分大写Tensor和小写tensor,见In

[3]和In [7]的区别,然后In [4]和In [5]也要进行区分。

生成未经过初始化的数据uninitalized

  • torch.empty()

  • torch.FloatTensor()

  • torch.IntTensor(d1,d2,d3l)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
In [3]: torch.empty(1)
Out[3]: tensor([0.])
In [4]: torch.empty([2,3])
Out[4]:
tensor([[0., 0., 0.],
[0., 0., 0.]])
In [5]: torch.empty(2,3)
Out[5]:
tensor([[0., 0., 0.],
[0., 0., 0.]])
In [6]: torch.Tensor(2,3)
Out[6]:
tensor([[0., 0., 0.],
[0., 0., 0.]])
In [7]: torch.IntTensor(2,3)
Out[7]:
tensor([[0, 0, 0],
[0, 0, 0]], dtype=torch.int32)
In [8]: torch.FloatTensor(2,3)
Out[8]:
tensor([[0., 0., 0.],
[0., 0., 0.]])

非常不建议直接将未初始化的Tensor带入计算,有极大概率出现奇怪的问题。这是因为未经初始化的Tensor,随机生成的数据有可能会相差较大(比如极大或者极小),上面的代码并没有出现这样的问题,可能是因为运气比较好。

empty()加不加括号都可以

生成数据过大或过小的情况

设置默认数据类型

PyTorch默认的Tensor类型是FloatTensor,因此在这种情况下,使用Tensor或tensor生成的tensor的数据类型都是FloatTensor类型的。

设置Tensor默认的数据类型采用的函数是set_default_tensor_type

1
2
3
4
5
6
In [3]: torch.tensor([1.2,3]).type()
Out[3]: 'torch.FloatTensor'
In [4]: torch.set_default_tensor_type(torch.DoubleTensor)
In [5]: torch.tensor([1.2,3]).type()
Out[5]: 'torch.DoubleTensor'

随机初始化

  • rand():随机生成(0,1)之间的数(均匀分布)
  • rand_like:传入参数是一个Tensor,就rand一个和传入tensor形状一样的tensor
  • randint:指定最小值和最大值以及Tensor的维度信息,然后进行随机。
  • randint_like:同randlike,这里不再赘述,详情见上面的rand_like函数
  • randn:随机生成(0,1)之间的数(正态分布)
  • full:给定维度信息和对应的数,使用该数初始化给定维度的tensor。
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
27
28
29
30
31
32
33
34
35
36
37
38
In [3]: torch.rand(3,3)
Out[3]:
tensor([[0.2722, 0.3876, 0.2607],
[0.2612, 0.5041, 0.4084],
[0.2007, 0.0119, 0.1834]])
In [4]: a=torch.rand(3,3)
In [5]: torch.rand_like(a)
Out[5]:
tensor([[0.1392, 0.9533, 0.5443],
[0.9043, 0.4646, 0.0362],
[0.7572, 0.5375, 0.8975]])
In [6]: b=torch.randint(1,10,[2,3])
In [7]: b
Out[7]:
tensor([[5, 6, 9],
[5, 1, 1]])
In [8]: c=torch.randint_like(b,1,100)
In [9]: c
Out[9]:
tensor([[42, 20, 59],
[15, 51, 1]])
In [10]: torch.randn(3,3)
Out[10]:
tensor([[ 0.6524, -1.4728, 0.0623],
[-0.6681, 0.7447, 0.9798],
[ 0.0814, 1.3355, -0.7414]])
In [11]: torch.full([5,2],0.1213)
Out[11]:
tensor([[0.1213, 0.1213],
[0.1213, 0.1213],
[0.1213, 0.1213],
[0.1213, 0.1213],
[0.1213, 0.1213]])
In [12]: torch.full([],7)#生成标量
Out[12]: tensor(7)
In [13]: torch.full([1],7)#生成一维向量
Out[13]: tensor([7])

arange

传入两个或三个参数,分别表示起始和终止位置(左闭右开),然后第三个参数是步长,不写就默认是1。

1
2
3
4
5
In [3]: torch.arange(0,10)
Out[3]: tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [4]: torch.arange(0,10,2)
Out[4]: tensor([0, 2, 4, 6, 8])

linspace/logspace

linspace和arange非常的像,但是第三个参数不表示步长了,而是表示的是数量,还有一个非常重要的不同是,这里的终止点是包含在了分割的序列中的。(见下面的例子)

logspace先是同linspace一样,将起始点和终止点之间的数据划分成给定数量的等差数列,然后将这些值作为指数,10作为底数(当然底数也可以自己通过改变base参数进行设置),计算出来的序列作为最后呈现的答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [3]: torch.linspace(0,10,steps=5)
Out[3]: tensor([ 0.0000, 2.5000, 5.0000, 7.5000, 10.0000])
In [4]: torch.linspace(0,10,steps=10)
Out[4]:
tensor([ 0.0000, 1.1111, 2.2222, 3.3333, 4.4444, 5.5556, 6.6667, 7.7778,
8.8889, 10.0000])
In [5]: torch.linspace(0,10,steps=11)
Out[5]: tensor([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
In [6]: torch.logspace(0,-1,steps=10)
Out[6]:
tensor([1.0000, 0.7743, 0.5995, 0.4642, 0.3594, 0.2783, 0.2154, 0.1668, 0.1292,
0.1000])
In [7]: torch.logspace(0,10,steps=11,base=2)
Out[7]:
tensor([1.0000e+00, 2.0000e+00, 4.0000e+00, 8.0000e+00, 1.6000e+01, 3.2000e+01,
6.4000e+01, 1.2800e+02, 2.5600e+02, 5.1200e+02, 1.0240e+03])

ones/zeros/eye

这个非常简单,大家直接看下面的例子就可以明白,这里就不再赘述。

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
In [3]: torch.ones(3,3)
Out[3]:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
In [4]: torch.zeros(3,3)
Out[4]:
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [5]: torch.eye(3,3)
Out[5]:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
In [6]: torch.eye(3,5)
Out[6]:
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.]])
In [7]: torch.eye(3)
Out[7]:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])

like方法在这里也可以使用哦。比如ones_like

randperm

随机打乱函数,一般用于打乱索引编号。

1
2
3
In [3]: idx=torch.randperm(10)
In [4]: idx
Out[4]: tensor([8, 6, 9, 5, 1, 2, 4, 7, 3, 0])

Tensor 切片

简单切片

1
2
3
4
5
6
7
8
9
In [3]: a=torch.rand(4,3,28,28)
In [4]: a[0].shape
Out[4]: torch.Size([3, 28, 28])
In [5]: a[0,1].shape
Out[5]: torch.Size([28, 28])
In [6]: a[0,1,2,3]
Out[6]: tensor(0.4744)
In [7]: a[:2].shape
Out[7]: torch.Size([2, 3, 28, 28])

选区间

1
2
3
4
5
6
7
8
9
In [9]: a[:2,:1,:,:].shape
Out[9]: torch.Size([2, 1, 28, 28])
In [10]: a[:2,1:,:,:].shape
Out[10]: torch.Size([2, 2, 28, 28])
In [11]: a[:2,-1,:,:].shape
Out[11]: torch.Size([2, 28, 28])
In [12]: a[:2,-1:,:,:].shape
Out[12]: torch.Size([2, 1, 28, 28])

有步长的切片

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

特定索引切片

使用index_select这个函数

传入两个参数,第一个参数是一个标量表示对第几个维度进行索引操作,第二个参数是一个tensor数组,表示我们想取出来的索引号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [21]: a=torch.eye(3)
In [22]: a
Out[22]:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
In [23]: a.index_select(0,torch.tensor([0,2]))
Out[23]:
tensor([[1., 0., 0.],
[0., 0., 1.]])
In [24]: a.index_select(0,torch.arange(2))
Out[24]:
tensor([[1., 0., 0.],
[0., 1., 0.]])

1
2
3
4
5
6
7
8
9
10
11
12
13
In [3]: a=torch.rand(4,3,28,28)
In [4]: a.shape
Out[4]: torch.Size([4, 3, 28, 28])
In [5]: a[...].shape
Out[5]: torch.Size([4, 3, 28, 28])

In [6]: a[0,...].shape
Out[6]: torch.Size([3, 28, 28])
In [7]: a[:,1,...].shape
Out[7]: torch.Size([4, 28, 28])
In [8]: a[...,:2].shape
Out[8]: torch.Size([4, 3, 28, 2])

通过遮罩取数

使用到的函数是masked_selected,这个函数并不是非常的常用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [3]: z=torch.randn(3,4)
In [4]: z
Out[4]:
tensor([[-0.9371, 1.0520, 0.2948, 0.3691],
[ 0.9820, 0.9555, -0.9335, -1.5135],
[-0.2594, -0.7860, -0.5336, 0.2682]])
In [5]: mask=z.ge(0.5)
In [6]: mask
Out[6]:
tensor([[False, True, False, False],
[ True, True, False, False],
[False, False, False, False]])
In [7]: torch.masked_select(z,mask)
Out[7]: tensor([1.0520, 0.9820, 0.9555])

通过take来进行取数

take取数会将tensor打平然后再根据新的索引进行取数操作,详情见下面的例子。

1
2
3
In [3]: src=torch.tensor([[4,3,5],[6,7,8]])
In [4]: torch.take(src,torch.tensor([0,2,5]))
Out[4]: tensor([4, 5, 8])

Tensor 维度变换

  • view/reshape
  • squeeze/unsqueeze
  • transpose/t/permute
  • expand/repeat

reshape/view

reshape和view是完全等价的,详情见下面的例子。

1
2
3
4
5
6
7
8
In [3]: a=torch.rand(4,1,28,28)
In [4]: a.shape
Out[4]: torch.Size([4, 1, 28, 28])
In [5]: a.view(4,28*28).shape
Out[5]: torch.Size([4, 784])
In [6]: a.reshape(4,28*28).shape
Out[6]: torch.Size([4, 784])

squeeze/unsqueeze

unsqueeze

对于一个维度为n的tensor,想要扩展维度所能够传入参数的范围是**$[-n-1,n+1)$**

如果输入的是正的索引(或0)则是在之前插入,负的索引则是在之后插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [3]: a=torch.randn(4,1,28,28)
In [4]: a.shape
Out[4]: torch.Size([4, 1, 28, 28])
In [5]: a.unsqueeze(0).shape
Out[5]: torch.Size([1, 4, 1, 28, 28])
In [6]: a.unsqueeze(-1).shape
Out[6]: torch.Size([4, 1, 28, 28, 1])
In [7]: a.unsqueeze(4).shape
Out[7]: torch.Size([4, 1, 28, 28, 1])
In [8]: a.unsqueeze(-4).shape
Out[8]: torch.Size([4, 1, 1, 28, 28])
In [9]: a.unsqueeze(-5).shape
Out[9]: torch.Size([1, 4, 1, 28, 28])
In [10]: a.unsqueeze(5).shape
Out[10]: RuntimeError: Dimension out of range

squeeze

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [3]: b=torch.rand(1,32,1,1)
In [4]: b.shape
Out[4]: torch.Size([1, 32, 1, 1])
In [5]: b.squeeze().shape
Out[5]: torch.Size([32])
In [6]: b.squeeze(0).shape
Out[6]: torch.Size([32, 1, 1])
In [7]: b.squeeze(-1).shape
Out[7]: torch.Size([1, 32, 1])
In [8]: b.squeeze(1).shape # can't squeeze this dimension
Out[8]: torch.Size([1, 32, 1, 1])
In [9]: b.squeeze(-4).shape
Out[9]: torch.Size([32, 1, 1])

expand/repeat

expand

这是维度扩展函数和维度增加函数还是有较大不同的,注意区分!维度增加是增加了一个新的维度,而维度扩展是将当前已有维度改变其shape的大小。

两个API所实现的功能是完全一样的,但是我们更加推荐使用第一个API,因为第一个API是在数据需要使用时才进行复制,因此expand的执行速度更快,并且更加节约内存。

只有原来维度为1,才能够被扩展!!!

如果expand中填写的参数为-1,表示的是维度大小保持不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [3]: a=torch.rand(1,3)
In [4]: a
Out[4]: tensor([[0.2768, 0.6714, 0.6259]])
In [5]: a.shape
Out[5]: torch.Size([1, 3])
In [6]: a.expand(4,3)
Out[6]:
tensor([[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259]])
In [7]: a.expand(4,-1)
Out[7]:
tensor([[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259],
[0.2768, 0.6714, 0.6259]])

repeat

传入的参数和expand函数有一些不同,这里所传入的参数代表拷贝的次数,比如如果原来维度大小是32,下面对应参数填写为2,最后生成的大小就是64。

1
2
3
4
5
6
7
8
9
10
In [3]: a=torch.rand(1,32,1,1)
In [4]: a.repeat(4,32,1,1).shape
Out[4]: torch.Size([4, 1024, 1, 1])
In [5]: a.repeat(4,1,1,1).shape
Out[5]: torch.Size([4, 32, 1, 1])
In [6]: a.repeat(4,1,32,32).shape
Out[6]: torch.Size([4, 32, 32, 32])
In [7]: a.repeat(4,1,32,0).shape
Out[7]: torch.Size([4, 32, 32, 0])

transpose/t/permute

t

矩阵转置操作

这个函数只适用于二维tensor,其他维度的tensor使用会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
In [3]: a=torch.rand(3,4)
In [4]: a
Out[4]:
tensor([[0.0723, 0.9169, 0.2574, 0.9654],
[0.5009, 0.9152, 0.6344, 0.7596],
[0.5432, 0.3906, 0.9426, 0.9421]])
In [5]: a.t()
Out[5]:
tensor([[0.0723, 0.5009, 0.5432],
[0.9169, 0.9152, 0.3906],
[0.2574, 0.6344, 0.9426],
[0.9654, 0.7596, 0.9421]])

transpose

矩阵维度交换函数,直接输入两个需要进行交换的维度,就可以直接将这两个维度进行交换,同时这两个维度存储的信息也会进行交换。

1
2
3
4
5
6
7
8
9
10
In [3]: a=torch.rand(4,3,32,32)
In [4]: a1=a.transpose(1,3).contiguous().view(4,3*32*32).view(4,3,32,32)
In [5]: a2=a.transpose(1,3).contiguous().view(4,3*32*32).view(4,32,32,3).transpose(1,3)
In [6]: a1.shape,a2.shape
Out[6]: (torch.Size([4, 3, 32, 32]), torch.Size([4, 3, 32, 32]))
In [7]: torch.all(torch.eq(a,a1))
Out[7]: tensor(False)
In [8]: torch.all(torch.eq(a,a2))
Out[8]: tensor(True)

contiguous函数是使内存顺序变得连续,不然会如果有以下写法会出现报错。(因为view会忽视维度信息)

view忽视了维度信息引起的报错

permute

和transpose比较类似,但是很好的解决了transpose每次只能交换两个维度的问题,我们输入的参数,是维度的排列顺序,这样就可以同时交换多个维度。

1
2
3
4
5
In [3]: a=torch.rand(1,2,3,4)
In [4]: a.shape
Out[4]: torch.Size([1, 2, 3, 4])
In [5]: a.permute(3,0,2,1).shape
Out[5]: torch.Size([4, 1, 3, 2])

本站由 @anonymity 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。