【问题标题】:Pytorch different outputs between with transposePytorch与转置之间的不同输出
【发布时间】:2021-11-25 11:50:58
【问题描述】:

让我有一个张量维度 (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)

两种方法都有效,但输出略有不同,我无法理解它们之间的区别。

谢谢

【问题讨论】:

  • 首先不清楚 torch.transpose 不会引发错误,因为您只传递了 2 个参数 pytorch.org/docs/stable/generated/torch.transpose.html 。但是,如果您确实设法使用该方法转置 A,则预期输出会有所不同。 A[0].reshape(20,10,10) 不同于 A[0].transpose.reshape(20,10,10)。查看重塑的详细内容,torch 或 nunmpy 文档没有详细介绍,但这里有一个快速指南:blog.finxter.com/numpy-reshape。理解它的一种简单方法是重塑保留数据的顺序,而转置则不会。
  • 因为你在重新整形之前对 B 进行了转置,所以输出矩阵确实不同。假设您有一个 2x2 矩阵,并且在将其转换为一维数组之前对其进行转置,它当然会与非转置矩阵不同,即使其中的值相同,只是顺序不同

标签: python numpy view pytorch reshape


【解决方案1】:

BC的区别在于你使用了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=1axis=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])

正如我所说,重塑在张量之上构建视图不会改变其内存布局,它是一个抽象级别,可以更好地操作张量。

所以最后,是的,您最终会得到两个不同的结果:CA 共享相同的数据,而 B 是一个副本并且具有不同的内存布局。

【讨论】:

    【解决方案2】:

    转置/置换和视图/重塑相同!
    reshapeview 仅影响张量的 shape,但不会改变元素。
    相比之下,transposepermute 改变了张量中元素的底层顺序。有关详细信息,请参阅 this answerthis one

    这里有一个例子,B=1N=3C=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]]]])
    

    但是,如果您只更改形状(即使用viewreshape),您会错误地“混合”来自两个通道的值:

    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]]]])
    
    

    【讨论】:

      猜你喜欢
      • 2021-09-09
      • 2020-06-27
      • 1970-01-01
      • 2021-11-16
      • 2020-12-09
      • 2020-12-28
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多