如果我有一个形状为 [z, d, d] 的张量 x,它表示一系列图像帧,就像视频数据一样。令pz=z**0.5,令x = x.view(pz, pz, d, d)。然后我们可以得到一个网格大小为pz*pz的图像网格,每个图像的形状为[d, d]. 现在,我想得到一个形状为 [1, 1, p*d, p*d] 的矩阵或张量,并且必须确保所有元素与所有原始图像保持相同的中间位置。
举个例子:
x = [[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15]]]
表示形状为 [2,2] 且 z = 4 的系列图像 我想要一个像这样的张量:
tensor([[ 0, 1, 4, 5],
[ 2, 3, 6, 7],
[ 8, 9, 12, 13],
[10, 11, 14, 15]])
我可以使用 x = x.view(1, 1, 4, 4) 得到一个相同形状的,但它是这样的:
tensor([[[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]]]])
我不想要。
还有更多,x有更多维度怎么样?就像 [b, c, z, d, d]。怎么处理?
任何建议都会有所帮助。
我有一个关于三维情况的解决方案。如果 x.shape = [z, d, d],那么下面的代码将起作用。但不适用于高维张量。嵌套循环可以,但太重了。 我对三维情况的解决方案:
d = 2
z = 4
b, c = 1, 1
x = torch.arange(z*d*d).view(z, d, d)
# x = torch.tensor([[[ 1, 2],
# [ 4, 6]],
#
# [[ 8, 10],
# [12, 14]],
#
# [[16, 18],
# [20, 22]],
#
# [[24, 26],
# [28, 30]],
#
# [[32, 34],
# [36, 38]],
#
# [[40, 42],
# [44, 46]],
#
# [[48, 50],
# [52, 54]],
#
# [[56, 58],
# [60, 62]],
#
# [[64, 66],
# [68, 70]]])
# make z-index planes to a grid layout
grid_side_len = int(z**0.5)
grid_x = x.view(grid_side_len, grid_side_len, d, d)
# for all rows of crops , horizontally stack them togather
plane = []
for i in range(grid_x.shape[0]):
cat_crops = torch.hstack([crop for crop in grid_x[i]])
plane.append(cat_crops)
plane = torch.vstack([p for p in plane])
print("3D crop to 2D crop plane:")
print(x)
print(plane)
print(plane.shape)
print("2D crop plane to 3D crop:")
# group all rows
split = torch.chunk(plane, plane.shape[1]//d, dim=0)
spat_flatten = torch.cat([torch.cat(torch.chunk(p, p.shape[1]//d, dim=1), dim=0) for p in split], dim=0)
crops = [t[None,:,:] for t in torch.chunk(spat_flatten, spat_flatten.shape[0]//d, dim=0)]
spat_crops = torch.cat(crops, dim=0)
print(spat_crops)
print(spat_crops.shape)
torch.transpose
和torch.reshape
操作来解决。从排列张量开始:
>>> x = torch.arange(16).view(4,2,2)
首先转置张量,使您想要整理的维度“垂直”站立,这可以通过
x.transpose(dim0=1, dim1=2)
:
>>> x.transpose(1,2)
tensor([[[ 0, 2],
[ 1, 3]],
[[ 4, 6],
[ 5, 7]],
[[ 8, 10],
[ 9, 11]],
[[12, 14],
[13, 15]]])
然后重塑以整理维度:
>>> x.transpose(1,2).reshape(2,4,2)
tensor([[[ 0, 2],
[ 1, 3],
[ 4, 6],
[ 5, 7]],
[[ 8, 10],
[ 9, 11],
[12, 14],
[13, 15]]])
然后向后翻转以恢复step 1中元素的顺序。:
>>> x.transpose(1,2).reshape(2,4,2).transpose(1,2)
tensor([[[ 0, 1, 4, 5],
[ 2, 3, 6, 7]],
[[ 8, 9, 12, 13],
[10, 11, 14, 15]]])
最后,重塑成想要的形状:
>>> x.transpose(1,2).reshape(2,4,2).transpose(1,2).reshape(len(x),-1)
tensor([[ 0, 1, 4, 5],
[ 2, 3, 6, 7],
[ 8, 9, 12, 13],
[10, 11, 14, 15]])
从那里您可以通过更改维度大小甚至扩展到更高的维度数字来满足您的需求,例如您所描述的
[b, c, z, d, d]
。如果你通过玩这个例子来理解这个简单的方法,你将能够解决任何与此类似的问题。