微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

理解重塑张量时的顺序

如何解决理解重塑张量时的顺序

对于张量:

x = torch.tensor([
    [
        [[0.4495,0.2356],[0.4069,0.2361],[0.4224,0.2362]],[[0.4357,0.6762],[0.4370,0.6779],[0.4406,0.6663]]
    ],[
        [[0.5796,0.4047],[0.5655,0.4080],[0.5431,0.4035]],[[0.5338,0.6255],[0.5335,0.6266],[0.5204,0.6396]]
    ]
])

首先想把它分成 2 个 (x.shape[0]) 张量然后连接它们。在这里,只要我得到正确的输出,我真的不必实际拆分它,但是在视觉上将它拆分然后将它们连接在一起对我来说更有意义。

例如:

# the shape of the splits are always the same
split1 = torch.tensor([
    [[0.4495,0.6663]]
])
split2 = torch.tensor([
    [[0.5796,0.6396]]
])

split1 = torch.cat((split1[0],split1[1]),dim=1)
split2 = torch.cat((split2[0],split2[1]),dim=1)
what_i_want = torch.cat((split1,split2),dim=0).reshape(x.shape[0],split1.shape[0],split1.shape[1])

enter image description here

对于上面的结果,我认为直接重塑 x.reshape([2,3,4]) 会起作用,它导致正确的尺寸但不正确的结果。

总的来说,我是:

  1. 不确定如何将张量拆分为 x.shape[0] 张量。
  2. 对重塑的工作方式感到困惑。大多数情况下,我都能得到正确的尺寸,但数字的顺序总是不正确。

谢谢

解决方法

python、pytorch、numpy、c++等中内存中元素的顺序是row-major顺序:

[ first,second
  third,forth  ]

而在 matlab、fortran 等中,顺序是 column major

[ first,third
  second,fourth ]

对于高维张量,这意味着元素从最后一维到第一维排序。

您可以使用 torch.arange 后跟 .view 轻松地将其可视化:

a = torch.arange(24)
a.view(2,3,4)

结果与

tensor([[[ 0,1,2,3],[ 4,5,6,7],[ 8,9,10,11]],[[12,13,14,15],[16,17,18,19],[20,21,22,23]]])

如您所见,元素首先按行(最后一个维度)排序,然后按列排序,最后按第一个维度排序。

当你 reshape 一个张量时,你不会改变元素的底层顺序,只会改变张量的 shape。但是,如果您 permute 张量 - 您会更改元素的基本顺序。

看看 a.view(3,4)a.permute(0,2) 的区别——结果两个张量的 shape 是一样的,但元素的顺序不同:

In []: a.view(3,4)
Out[]:
tensor([[[ 0,7]],[[ 8,11],[12,15]],[[16,23]]])

In []: a.permute(1,2)
Out[]:
tensor([[[ 0,[[ 4,19]],23]]])
,

您的示例,使用 numpy 方法(我没有安装 tensorflow):

In [559]: x = np.array([
     ...:     [
     ...:         [[0.4495,0.2356],...:           [0.4069,0.2361],...:           [0.4224,0.2362]],...: 
     ...:          [[0.4357,0.6762],...:           [0.4370,0.6779],...:           [0.4406,0.6663]]
     ...:     ],...:     [
     ...:         [[0.5796,0.4047],...:           [0.5655,0.4080],...:           [0.5431,0.4035]],...: 
     ...:          [[0.5338,0.6255],...:           [0.5335,0.6266],...:           [0.5204,0.6396]]
     ...:     ]
     ...: ])
In [560]: x.shape
Out[560]: (2,2)

In [562]: s1=np.concatenate((x[0,0],x[0,1]),axis=1)
In [563]: s2=np.concatenate((x[1,x[1,axis=1)
In [564]: s1.shape
Out[564]: (3,4)

In [565]: new =np.concatenate((s1,s2),axis=0)
In [566]: new.shape
Out[566]: (6,4)
In [567]: new.reshape(2,4)
Out[567]: 
array([[[0.4495,0.2356,0.4357,[0.4069,0.2361,0.437,[0.4224,0.2362,0.4406,0.6663]],[[0.5796,0.4047,0.5338,[0.5655,0.408,0.5335,[0.5431,0.4035,0.5204,0.6396]]])

numpy 有一个 stack,它在新轴上连接数组,因此我们可以跳过最后一个连接并使用

重塑
np.stack((s1,s2))    # or
np.array((s1,s2))

到达那里的直接方法是交换中间的二维:

In [569]: x.transpose(0,3).shape
Out[569]: (2,2)

In [571]: x.transpose(0,3).reshape(2,4)
Out[571]: 
array([[[0.4495,0.6396]]])

reshape 可用于组合“相邻”维度,但不会重新排序基础数据。即 x.ravel()reshape 保持相同。虽然允许将 (2,2) 重塑为 (2,4),但值的明显顺序可能不是您想要的。如果您尝试重塑,那可能会更容易看到

In [572]: np.arange(6).reshape(2,3)
Out[572]: 
array([[0,2],[3,4,5]])
In [573]: _.reshape(3,2)
Out[573]: 
array([[0,1],[2,[4,5]])

将其与转置进行比较:

In [574]: np.arange(6).reshape(2,3).transpose(1,0)
Out[574]: 
array([[0,[1,4],5]])

我在 [569] 中所做的转置/交换可能难以理解。重新排序维度的方法有很多,很难一概而论。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。