python - 在 NumPy 中将 4 维数组 reshape 为 2 维数组背后的直觉和想法

标签 python arrays numpy multidimensional-array reshape

在执行 Kronecker-product 时出于教学原因(没有使用明显且现成的 np.kron()),我获得了一个 4 维数组作为中间结果,我必须将其 reshape 为得到最终结果。

但是,我仍然无法全神贯注于 reshape 这些高维数组。我有这个 4D 数组:

array([[[[ 0,  0],
         [ 0,  0]],

        [[ 5, 10],
         [15, 20]]],


       [[[ 6, 12],
         [18, 24]],

        [[ 7, 14],
         [21, 28]]]])

这是 (2, 2, 2, 2) 的形状,我想将它 reshape 为 (4,4)。有人可能认为这显然与

有关
np.reshape(my4darr, (4,4))

但是,上面的 reshape 没有给我预期的结果,它是:

array([[ 0,  5,  0, 10],
       [ 6,  7, 12, 14],
       [ 0, 15,  0, 20],
       [18, 21, 24, 28]])

如您所见,预期结果 中的所有元素都出现在 4D 数组中。我只是无法掌握根据需要正确地进行 reshape 的窍门。除了答案之外,对如何对此类高维数组进行 reshape 的一些解释将非常有帮助。谢谢!

最佳答案

ndnd 转换的总体思路

ndnd 转换的想法只使用了两件事 -

Permute axes : 获取顺序,使展平版本对应于展平版本的输出。因此,如果您以某种方式最终使用它两次,请再看一遍,因为您不应该这样做。

Reshape : 拆分轴或将最终输出调整为所需的形状。拆分轴主要是在开始时需要的,当输入是 lower-dim 并且我们需要拆分成 block 时。同样,您不应该需要两次以上。

因此,一般我们会分为三个步骤:

    [ Reshape ]      --->  [ Permute axes ]   --->  [ Reshape ]

 Create more axes             Bring axes             Merge axes
                          into correct order

回溯法

最安全的解决方法,给定输入和输出是直通的,可以称为回溯法,即拆分输入轴(从较小的 nd 到较大的轴nd) 或拆分输出轴(当从较大的 nd 变为较小的 nd 时)。拆分的想法是使较小的 nd 的 dims 数量与较大的 nd 的相同。然后,研究输出的步长并将其与输入进行匹配以获得所需的排列顺序。最后,如果最后一个是较小的 nd ,最后可能需要 reshape (默认方式或 C 顺序)以合并轴。

如果输入和输出都具有相同数量的 dims,那么我们需要将两者拆分并分成 block 并研究它们相互间的步幅。在这种情况下,我们应该有 block 大小的额外输入参数,但这可能是题外话。

例子

让我们使用这个具体案例来演示如何应用这些策略。在这里,输入是4D,而输出是2D。所以,很可能,我们不需要 reshape 来 split 。所以,我们需要从排列轴开始。由于最终输出不是 4D,而是 2D,因此我们需要在最后进行整形。

现在,这里的输入是:

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

然后,简单地 reshape 成预期的形状:

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

更多示例

我挖掘了我的历史,发现很少有Q&As 基于ndnd 的转换。这些可以作为其他示例案例,尽管解释较少(主要是)。如前所述,至多两个 reshapes 和至多一个 swapaxes/transpose 完成了所有工作。它们列在下面:

关于python - 在 NumPy 中将 4 维数组 reshape 为 2 维数组背后的直觉和想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47977238/

相关文章:

python - 关于hough_line和hough_line_peaks的代码解释

Javascript 数组 - 检查 2 个数组中的匹配项

python - Numpy 和静态链接

python - 如何修补基类方法?

python - 当数据框有重复的列时,fillna 函数似乎无法与 dict 参数一起正常工作

Python:+= 运算符和追加运算符之间的差异

javascript - 在对象的对象数组中查找属性的最大值

javascript - 从数组中检索多个值的更简单方法

python - matplotlib 中的球面坐标图

python - 如何在一行中打印一个 numpy.array?