nd 到 nd 转换的总体思路
这种nd 到nd 转换的想法只使用了两件事-
置换轴: 获得顺序,使得展平版本对应于展平版本的输出。所以,如果你最终以某种方式使用了它两次,请再看一遍,因为你不应该这样做。
重塑:分割轴或将最终输出带到所需的形状。分割轴主要在开始时需要,当输入是低亮度并且我们需要分割成块时。同样,您不应该超过两次。
因此,通常我们将分为三个步骤:
[ Reshape ] ---> [ Permute axes ] ---> [ Reshape ]
Create more axes Bring axes Merge axes
into correct order
回溯法
考虑到输入和输出,最安全的解决方法是通过所谓的回溯方法,即拆分输入的轴(从较小的nd 到较大的nd)或分割输出的轴(从更大的nd 到更小的nd)。拆分的想法是使较小的nd 的暗淡数量与较大的nd 相同。然后,研究输出的步幅并将其与输入进行匹配以获得所需的置换顺序。最后,如果最后一个是较小的nd 一个,最后可能需要重新整形(默认方式或 C 顺序)来合并轴。
如果输入和输出的维度数相同,那么我们需要将两者拆分并分成块并研究它们的步幅。在这种情况下,我们应该有块大小的额外输入参数,但这可能是题外话。
示例
让我们用这个具体案例来演示如何应用这些策略。在这里,输入是4D,而输出是2D。所以,很可能,我们不需要 reshape 来拆分。所以,我们需要从排列轴开始。由于最终输出不是4D,而是2D,所以我们需要在最后进行reshape。
现在,这里的输入是:
In [270]: a
Out[270]:
array([[[[ 0, 0],
[ 0, 0]],
[[ 5, 10],
[15, 20]]],
[[[ 6, 12],
[18, 24]],
[[ 7, 14],
[21, 28]]]])
预期的输出是:
In [271]: out
Out[271]:
array([[ 0, 5, 0, 10],
[ 6, 7, 12, 14],
[ 0, 15, 0, 20],
[18, 21, 24, 28]])
此外,这是一个较大的 nd 到较小的 nd 转换,因此回溯方法将涉及拆分输出并研究其 strides 并匹配输入中的相应值:
axis = 3
--- -->
axis = 1
------>
axis=2| axis=0| [ 0, 5, 0, 10],
| [ 6, 7, 12, 14],
v
| [ 0, 15, 0, 20],
v
[18, 21, 24, 28]])
因此,所需的置换顺序是(2,0,3,1):
In [275]: a.transpose((2, 0, 3, 1))
Out[275]:
array([[[[ 0, 5],
[ 0, 10]],
[[ 6, 7],
[12, 14]]],
[[[ 0, 15],
[ 0, 20]],
[[18, 21],
[24, 28]]]])
然后,简单地重塑为预期的形状:
In [276]: a.transpose((2, 0, 3, 1)).reshape(4,4)
Out[276]:
array([[ 0, 5, 0, 10],
[ 6, 7, 12, 14],
[ 0, 15, 0, 20],
[18, 21, 24, 28]])
更多示例
我挖掘了我的历史,发现很少有基于nd 到nd 转换的Q&As。这些可以作为其他示例案例,尽管解释较少(大部分)。如前所述,最多两个reshapes 和最多一个swapaxes/transpose 在任何地方都完成了这项工作。它们在下面列出: