NumPy多维数组重塑:巧用transpose与reshape实现特定轴合并

上周,当我的朋友处理一组 NumPy 形状 (2 ,3 ,4 ,5 ) 时,他需要将最后一个维度合并到 (2 ,4 ,1 5 )。
它首先使用转置来调整轴的顺序并将要连接的尺寸移动到相邻位置。
例如,他将轴顺序从 (0,1 ,2 ,3 ) 更改为 (0,2 ,1 ,3 ),以便第一个轴(3 个矩阵)紧邻第三个轴(列)。

接下来,它使用重塑来连接两个相邻的维度。
它这样做:arr_transpose.reshape(2 ,2 ,3 5 ),因为合并后第二轴和第三轴变成了6 个元素。

它的原始范围是arr=np.arange(2 4 ).reshape(2 ,3 ,2 ,2 )。
转置后变成arr_transpose=arr.transpose(0,2 ,1 ,3 ),形状变成(2 ,2 ,3 ,2 )。
然后,它将数组重塑为 (2 ,2 ,6 ),得到 arr_reshape=arr_transpose.reshape(2 ,2 ,6 )。

输出如下:[[[0 1 4 5 8 9 ][2 3 6 7 1 0 1 1 ]][[1 2 1 3 1 6 1 7 ][1 2 1 3 2 0 2 1 ][1 2 1 3 1 4 1 5 ][1 2 1 3 1 8 1 9 ] [1 2 1 3 1 8 1 9 ]。

我的朋友还提到了一些注意事项,例如选择轴顺序以确保要连接的维度与目标轴相邻且位于目标轴之前。
他还警告说,转置通常会返回图像,而重新格式化可能会产生重复,特别是在涉及元素重新排列时。

最后,他认为使用转置和重塑比串联更高效,因为串联需要手动指定串联轴,而且代码又长又低效。
他表示,复杂的操作可以用一行代码实现,这对于结构化排列高维数组非常有用。

听了他的发言,我觉得这个方法真的很实用。
然而,我刚刚想到的另一件事是,在处理非常大的数组时,这些操作会消耗更多的内存。
因此,在使用这些方法时,还应该注意内存管理。
这取决于你。

小技巧 | Numpy::Squeeze

哦,你在说这个吗?去年我在北京做一个图像处理项目,这让我很沮丧。

当时我使用的是PyTorch和CUDA1 0.2 环境。
处理一批 JPEG 图像。
最初,每张图片的形状为(C,H,W),即(3 ,2 5 6 ,2 5 6 )。
结果我们发现,跑了大约一半后,维度增加了1 ,变成了(1 ,3 ,2 5 6 ,2 5 6 )。
当时我的头很晕,调试了好久。

后来我才知道,这就是你说的光圈吧?在 PyTorch 中,我直接使用 torch.squeeze(0),但它立即恢复为 (3 , 2 5 6 , 2 5 6 )。
此操作比手动索引 a=a[0] 好得多,尤其是在您不知道附加维度在哪里的情况下。

我记得在武汉的一次会议上,我旁边的组里有一个人也在使用 Numpy。
他的数组是(1 , 1 , 5 1 2 , 5 1 2 ),他想要的是(5 1 2 , 5 1 2 ),也是用squeeze解决的。
他表示,squeeze 比手动索引不那么麻烦,而且非常灵活,特别是对于多维情况,因为它会自动删除所有 size=1 的维度。

但是,您需要小心。
如果使用不当,挤压可能会导致问题。
例如,有一次我正在处理模型的输出。
原来是(1 , 1 0)。
我想直接将其更改为(1 0)并挤压(0)。
结果,模型爆炸了。
后来我发现(1 , 1 0)实际上是一个批处理标识符,我不能只压缩第一个维度。
所以你需要知道什么时候使用它,什么时候不使用它。

我还使用了你提到的expand_dims或unsqueeze。
去年,我在苏州做一个视频处理项目。
在 PyTorch 中,我需要将 (C, H, W) 图片转换为 (B, C, H, W)。
这意味着添加额外的批次维度。
只需使用 unsqueeze(0) 即可完成。
这个操作在PyTorch中非常常用,经常需要手动添加维度,尤其是在做模型输入时。

也就是说,这些操作会随着你的使用而变得越来越好用。
最初,您可能会遇到陷阱,例如使用错误的维度索引进行挤压或取消挤压。
结果,阵列变得畸形并且调试需要时间。
但是,根据经验,您将知道何时使用哪一种以及如何使用它们而不会造成问题。

如果你刚刚开始深度学习,你需要了解这些操作。
通过更多的练习和调试,您很快就会掌握它。
如果您有任何具体问题,请随时与我们联系。

关于Numpy转置(T、transpose[三维、四维...高维数组])的理解

一维转置返回自身。
二维行变成列。
在三个维度上使用转置。
.T简单,转置灵活。
如果你自己尝试一下你就会明白。