scatter & gather
参考笔者另一篇博客Pytorch中scatter与gather操作
expand
返回当前张量在某维扩展更大后的张量。扩展(expand)张量不会分配新的内存,只是在存在的张量上创建一个新的视图(view),一个大小(size)等于1的维度扩展到更大的尺寸。
x = torch.tensor([[1,2,3]])
x.expand(2,-1) # 第一个维度重复一次,第二个维度不变,注意,只能操作大小等于1的维度
tensor([[1, 2, 3],
[1, 2, 3]])
repeat
沿着特定的维度重复这个张量,和expand()不同的是,这个函数拷贝张量的数据。
x = torch.tensor([[1,2,3]])
x.repeat(2,2)
tensor([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3]])
对比:
x = torch.tensor([[1,2,3]])
y = x.expand(2,-1)
z = x.repeat(2,1)
print(x.data_ptr(), y.data_ptr(), z.data_ptr())
2434171052800 2434171052800 2434177810176
更多信息可以参考PyTorch学习笔记——repeat()和expand()区别评论区。
reshape & view
功能相似,但是view()
只能操作tensor
,reshape()
可以操作 tensor
和 ndarray
。view()
只能用在 contiguous
的变量上。如果在 view 之前用了transpose
, permute
等,需要用 contiguous()
来返回一个 contiguous copy。 view() 操作后的 tensor 和原 tensor 共享存储。
pytorch 中的 torch.reshape()
大致相当于tensor.contiguous().view()
。
x = torch.tensor([[1,2,3]])
x.reshape(3,1)
>>>
tensor([[1],
[2],
[3]])
x.view(3,1) # x.view(*[3,1])
>>>
tensor([[1],
[2],
[3]])
permute & transpose
两者都是实现维度之间的交换,transpose 只能一次转换两个维度,permute 可以一次转换多个维度,permute 可以通过 transpose 组合的形式实现。在卷积神经网络中,cross-channel max pooling
就用到了这类变换。
permute:
a = torch.tensor([[[0,1,2],[3,4,5]]])
print("a.shape:", a.shape)
print('a:\n',a)
b = a.permute(0,2,1)
print("b.shape:", b.shape)
print('b:\n',b)
c = a.permute(1,2,0)
print("c.shape:", c.shape)
print('c\n',c)
# 输出
a.shape: torch.Size([1, 2, 3])
a:
tensor([[[0, 1, 2],
[3, 4, 5]]])
b.shape: torch.Size([1, 3, 2])
b:
tensor([[[0, 3],
[1, 4],
[2, 5]]])
c.shape: torch.Size([2, 3, 1])
c
tensor([[[0],
[1],
[2]],
[[3],
[4],
[5]]])
transpose:
a = torch.tensor([[[0,1,2],[3,4,5]]])
print("a.shape:", a.shape)
print('a:\n',a)
d = a.transpose(0,1)
print("d.shape:", d.shape)
print('d\n',d)
e = a.transpose(2,1)
print("e.shape:", e.shape)
print('e\n',e)
#输出
a.shape: torch.Size([1, 2, 3])
a:
tensor([[[0, 1, 2],
[3, 4, 5]]])
d.shape: torch.Size([2, 1, 3])
d
tensor([[[0, 1, 2]],
[[3, 4, 5]]])
e.shape: torch.Size([1, 3, 2])
e
tensor([[[0, 3],
[1, 4],
[2, 5]]])
reshape 与 view 可以重新设置维度;permute 和 transpose 只能在已有的维度之间转换,并且包含转置的概念。
matmul
torch.matmul
是tensor的乘法,输入可以是高维的。
-
当输入是都是二维时,就是普通的矩阵乘法,和
tensor.mm
函数用法相同。a=torch.ones(3,4) b=torch.ones(4,2) c=torch.matmul(a,b) c.shape # torch.Size([3,2])
-
当输入有多维时,把多出的一维作为batch提出来,其他部分做矩阵乘法。
a=torch.ones(5,3,4) b=torch.ones(4,2) c=torch.matmul(a,b) c.shape # torch.Size([5,3,2])
两个都是三维,如下,将b的第0维度的1维broadcast成2提出来,后两维做矩阵乘法即可。:
a=torch.ones(2,5,3) b=torch.ones(1,3,4) c=torch.matmul(a,b) c.shape # torch.Size([2,5,4])
官网例子:
a=torch.ones(2,1,3,4) b=torch.ones(5,4,2) c=torch.matmul(a,b) c.shape # torch.Size([2,5,3,2])
首先把a的第0维度2维作为batch提出来,则a和b都可看作三维。再把a的1维broadcat成5提出来。然后a剩下(3,4),b剩下(4,2),做矩阵乘法得到(3,2)。
ger
向量外积:
a = torch.tensor([1,2,3])
b = torch.tensor([1,2,3,4])
torch.ger(a,b)
Out[15]:
tensor([[ 1, 2, 3, 4],
[ 2, 4, 6, 8],
[ 3, 6, 9, 12]])