Pytorch 笔记

torch.cat()

在给定维度上对输入的张量序列进行连接操作

  • Args
    • tensors (sequence of Tensors): any python sequence of tensors of the same type. 任意 Tensor 类型的 python 序列,序列中的数据是任意相同 shape 的同类型的Tensor
      • Non-empty tensors provided must have the same shape, except in the cat dimension.
    • dim (int, optional): the dimension over which the tensors are concatenated 维度不能超过输入数据任意一个张量的维度
  • Keyword args: out (Tensor, optional): the output tensor.

torch.gather()

1
torch.gather(input, dim, index, *, sparse_grad=False, out=None) -> Tensor

沿着由 dim 指定的轴收集数值

  • dim = 0的情况,代表的是横向,按行取值
    • length矩阵中的数的值代表的是行数,所在列代表的是列数
1
2
3
4
5
6
7
8
9
10
11
12
13
input = [
[0.0, 0.1, 0.2, 0.3],
[1.0, 1.1, 1.2, 1.3],
[2.0, 2.1, 2.2, 2.3]
]#shape [3,4]
input = torch.tensor(input)
length = torch.LongTensor([
[2,2,2,2],
[1,1,1,1],
[0,0,0,0],
[0,1,2,0]
])#[4,4]
out = torch.gather(input, dim=0, index=length)
1
2
3
4
tensor([[2.0000, 2.1000, 2.2000, 2.3000],
[1.0000, 1.1000, 1.2000, 1.3000],
[0.0000, 0.1000, 0.2000, 0.3000],
[0.0000, 1.1000, 2.2000, 0.3000]])

用矩阵的方式演示

length矩阵中的数的值代表的是行数,数的位置代表的列数,比如 length 矩阵中的第三行第三列(从 0 数起)的数 0,其值是 0,代表在 input 中所取的数是第 0 行,位置是第三列,则表示在 input 中所取的数是第三列,

  • dim = 1的情况
    • length矩阵中的数的值代表的是列数,所在行代表的是行数
1
2
3
4
5
6
7
8
9
10
11
12
input = [
[0.0, 0.1, 0.2, 0.3],
[1.0, 1.1, 1.2, 1.3],
[2.0, 2.1, 2.2, 2.3]
]#shape [3,4]
input = torch.tensor(input)
length = torch.LongTensor([
[2,2,2,2],
[1,1,1,1],
[0,1,2,0]
])#[3,4]
out = torch.gather(input, dim=1, index=length)
1
2
3
tensor([[0.2000, 0.2000, 0.2000, 0.2000],
[1.1000, 1.1000, 1.1000, 1.1000],
[2.0000, 2.1000, 2.2000, 2.0000]])

对应的取值矩阵是

unsqueeze()squeeze()

unsqueeze()函数

torch.unsqueeze(input, dim, out=None) 扩展维度,返回一个新的张量,对输入的既定位置插入维度1

返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个

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

x = torch.Tensor([1, 2, 3, 4]) # torch.Tensor 是默认的 tensor 类型(torch.FlaotTensor)的简称
x # tensor([1., 2., 3., 4.])
x.size() # torch.Size([4])
x.dim() # 1

x = torch.Tensor([1, 2, 3, 4])
x = torch.unsqueeze(x, 0) # tensor([[1., 2., 3., 4.]])
x.size() # torch.Size([1, 4])
x.dim() # 2

x = torch.Tensor([1, 2, 3, 4])
x = torch.unsqueeze(x, 1) # tensor([[1.], [2.], [3.], [4.]])
x.size() # torch.Size([4, 1])
x.dim() # 2

x = torch.Tensor([1, 2, 3, 4])
x = torch.unsqueeze(x, -1) # tensor([[1.], [2.], [3.], [4.]])
x.size() # torch.Size([4, 1])
x.dim() # 2

x = torch.Tensor([1, 2, 3, 4])
x = torch.unsqueeze(x, -2) # tensor([[1., 2., 3., 4.]])
x.size() # torch.Size([1, 4])
x.dim() # 2

边界测试

A dim value within the range [-input.dim() - 1, input.dim() + 1)

1
2
x = torch.Tensor([1, 2, 3, 4])
torch.unsqueeze(x, -3)

IndexError: Dimension out of range (expected to be in range of [-2, 1], but got -3)

1
2
x = torch.Tensor([1, 2, 3, 4])
torch.unsqueeze(x, 2)

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

为何取值范围要如此设计呢?
原因:方便操作
0(-2)- 行扩展
1(-1)- 列扩展
正向:我们在 0,1 位置上扩展
逆向:我们在 -2,-1 位置上扩展
维度扩展:1 维 ->2 维,2 维 ->3 维,…,n 维 ->n+1 维
维度降低:n 维 ->n-1 维,n-1 维 ->n-2 维,…,2 维 ->1 维

以 1 维 ->2 维 为例,

正向 的角度思考:

torch.Size([4])
最初的 tensor([1., 2., 3., 4.]) 是 1 维,我们想让它扩展成 2 维,那么,可以有两种扩展方式:

一种是:扩展成 1 行 4 列 ,即 tensor([[1., 2., 3., 4.]])
针对第一种,扩展成 [1, 4] 的形式,那么,在 dim=0 的位置上添加 1

另一种是:扩展成 4 行 1 列,即
tensor([[1.], [2.], [3.], [4.]])
针对第二种,扩展成 [4, 1] 的形式,那么,在 dim=1 的位置上添加 1

逆向 的角度思考:
原则:一般情况下, -1是代表的是 最后一个元素
在上述的原则下
扩展成 [1, 4] 的形式,就变成了,在 dim=-2 的的位置上添加 1
扩展成 [4, 1] 的形式,就变成了,在 dim=-1 的的位置上添加 1

unsequeeze_unsqueeze 的区别

unsqueeze_unsqueeze实现一样的功能,区别在于 unsqueeze_in_place操作,即 unsqueeze不会对使用 unsqueezetensor进行改变,想要获取 unsqueeze 后的值必须赋予个新值,unsqueeze_则会对自己改变

squeeze()函数

作用是降维,torch.squeeze(input, dim=None, out=None)将输入张量形状中的 1 去除并返回。 如果输入是形如 (A×1×B×1×C×1×D),那么输出形状就为:(A×B×C×D)。当给定dim 时,那么挤压操作只在给定维度上。例如,输入形状为:(A×1×B), squeeze(input, 0)将会保持张量不变,只有用squeeze(input, 1),形状会变成(A×B)

unsqueeze 一样,返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个

多维张量本质上就是一个变换,如果维度是 1 ,那么,1 仅仅起到扩充维度的作用,而没有其他用途,因而,在进行降维操作时,为了加快计算,是可以去掉这些 1 的维度

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
m = torch.zeros(2, 1, 2, 1, 2)
print(m.size()) # torch.Size([2, 1, 2, 1, 2])

n = torch.squeeze(m)
print(n.size()) # torch.Size([2, 2, 2])

n = torch.squeeze(m, 0) # 当给定 dim 时,那么挤压操作只在给定维度上
print(n.size()) # torch.Size([2, 1, 2, 1, 2])

n = torch.squeeze(m, 1)
print(n.size()) # torch.Size([2, 2, 1, 2])

n = torch.squeeze(m, 2)
print(n.size()) # torch.Size([2, 1, 2, 1, 2])

n = torch.squeeze(m, 3)
print(n.size()) # torch.Size([2, 1, 2, 2])

p = torch.zeros(2, 1, 1)
print(p)
# tensor([[[0.]],
# [[0.]]])
print(p.numpy())
# [[[0.]]
# [[0.]]]

print(p.size())
# torch.Size([2, 1, 1])

q = torch.squeeze(p)
print(q)
# tensor([0., 0.])

print(q.numpy())
# [0. 0.]

print(q.size())
# torch.Size([2])


print(torch.zeros(3, 2).numpy())
# [[0. 0.]
# [0. 0.]
# [0. 0.]]

Pytorch 笔记
https://silhouettesforyou.github.io/2022/02/21/7c5a55cd05b9/
Author
Xiaoming
Posted on
February 21, 2022
Licensed under