Pytorch 与转置之间的不同输出
Pytorch different outputs between with transpose
设张量维度为 (B, N^2, C)
我将其重塑为 (B, C, N, N)。
我认为我有以下两个选择
A = torch.rand(5, 100, 20) # Original Tensor
# First Method
B = torch.transpose(2, 1)
B = B.view(5, 20, 10, 10)
# Second Method
C = A.view(5, 20, 10, 10)
两种方法都有效,但输出略有不同,我看不出它们之间的区别。
谢谢
B
和C
的区别是你使用了torch.transpose
,这意味着你交换了两个轴,这意味着你改变了内存的布局。最后的视图只是一个很好的界面,供您访问数据,但它对张量的基础数据没有影响。它归结为一个连续的内存数据缓冲区。
举个小例子,我们更容易掌握:
>>> A = torch.rand(1, 4, 3)
tensor([[[0.2656, 0.5920, 0.3774],
[0.8447, 0.5984, 0.0614],
[0.5160, 0.8048, 0.6260],
[0.1644, 0.3144, 0.1040]]])
这里交换 axis=1
和 axis=2
归结为批量转置(用数学术语):
>>> B = A.transpose(2, 1)
tensor([[[0.4543, 0.7447, 0.7814, 0.3444],
[0.9766, 0.2732, 0.4766, 0.0387],
[0.0123, 0.7260, 0.8939, 0.8581]]])
在内存布局方面A
有如下内存布局:
>>> A.flatten()
tensor([0.4543, 0.9766, 0.0123, 0.7447, 0.2732, 0.7260, 0.7814, 0.4766, 0.8939,
0.3444, 0.0387, 0.8581])
而 B
有不同的布局。通过 layout 我的意思是内存安排,我不是指它的 shape 这是无关紧要的:
>>> B.flatten()
tensor([0.4543, 0.7447, 0.7814, 0.3444, 0.9766, 0.2732, 0.4766, 0.0387, 0.0123,
0.7260, 0.8939, 0.8581])
正如我所说的重塑 ,即 在张量之上构建视图不会改变其内存布局,它是更好地操纵张量的抽象级别。
所以最后,是的,你得到了两个不同的结果:C
与 A
共享相同的数据,而 B
是一个副本并且具有不同的内存布局.
Transposing/permuting 和 view/reshape 不 相同!
reshape
and view
只影响张量的 shape
,但不改变元素的底层顺序。
相比之下,transpose
and permute
change the underlying order of elements in the tensor. See , and this one更详细。
举个例子,B=1
、N=3
和C=2
,第一个通道有偶数0..16,第二个通道有奇数1..17 :
A = torch.arange(2*9).view(1,9,2)
tensor([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15],
[16, 17]]])
如果你正确地转置然后重塑,你就能正确地分割成偶数和奇数通道:
A.transpose(1,2).view(1,2,3,3)
tensor([[[[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]],
[[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]]]])
但是,如果您仅更改形状(即,使用 view
或 reshape
),您会错误地“混合”来自两个通道的值:
A.view(1,2,3,3)
tensor([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]]])
设张量维度为 (B, N^2, C) 我将其重塑为 (B, C, N, N)。
我认为我有以下两个选择
A = torch.rand(5, 100, 20) # Original Tensor
# First Method
B = torch.transpose(2, 1)
B = B.view(5, 20, 10, 10)
# Second Method
C = A.view(5, 20, 10, 10)
两种方法都有效,但输出略有不同,我看不出它们之间的区别。
谢谢
B
和C
的区别是你使用了torch.transpose
,这意味着你交换了两个轴,这意味着你改变了内存的布局。最后的视图只是一个很好的界面,供您访问数据,但它对张量的基础数据没有影响。它归结为一个连续的内存数据缓冲区。
举个小例子,我们更容易掌握:
>>> A = torch.rand(1, 4, 3)
tensor([[[0.2656, 0.5920, 0.3774],
[0.8447, 0.5984, 0.0614],
[0.5160, 0.8048, 0.6260],
[0.1644, 0.3144, 0.1040]]])
这里交换 axis=1
和 axis=2
归结为批量转置(用数学术语):
>>> B = A.transpose(2, 1)
tensor([[[0.4543, 0.7447, 0.7814, 0.3444],
[0.9766, 0.2732, 0.4766, 0.0387],
[0.0123, 0.7260, 0.8939, 0.8581]]])
在内存布局方面A
有如下内存布局:
>>> A.flatten()
tensor([0.4543, 0.9766, 0.0123, 0.7447, 0.2732, 0.7260, 0.7814, 0.4766, 0.8939,
0.3444, 0.0387, 0.8581])
而 B
有不同的布局。通过 layout 我的意思是内存安排,我不是指它的 shape 这是无关紧要的:
>>> B.flatten()
tensor([0.4543, 0.7447, 0.7814, 0.3444, 0.9766, 0.2732, 0.4766, 0.0387, 0.0123,
0.7260, 0.8939, 0.8581])
正如我所说的重塑 ,即 在张量之上构建视图不会改变其内存布局,它是更好地操纵张量的抽象级别。
所以最后,是的,你得到了两个不同的结果:C
与 A
共享相同的数据,而 B
是一个副本并且具有不同的内存布局.
Transposing/permuting 和 view/reshape 不 相同!
reshape
and view
只影响张量的 shape
,但不改变元素的底层顺序。
相比之下,transpose
and permute
change the underlying order of elements in the tensor. See
举个例子,B=1
、N=3
和C=2
,第一个通道有偶数0..16,第二个通道有奇数1..17 :
A = torch.arange(2*9).view(1,9,2)
tensor([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15],
[16, 17]]])
如果你正确地转置然后重塑,你就能正确地分割成偶数和奇数通道:
A.transpose(1,2).view(1,2,3,3)
tensor([[[[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]],
[[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]]]])
但是,如果您仅更改形状(即,使用 view
或 reshape
),您会错误地“混合”来自两个通道的值:
A.view(1,2,3,3)
tensor([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]]])