在 NumPy 中将四维数组重塑为二维数组背后的直觉和想法

2025-01-09 08:46:00
admin
原创
105
摘要:问题描述:Kronecker-product在出于教学原因实施时(没有使用明显且现成的np.kron()),我获得了一个四维数组作为中间结果,我必须重塑它才能获得最终结果。但是,我仍然无法理解如何重塑这些高维数组。我有这个4D数组:array([[[[ 0, 0], [ 0, 0]], ...

问题描述:

Kronecker-product在出于教学原因实施时(没有使用明显且现成的np.kron()),我获得了一个四维数组作为中间结果,我必须重塑它才能获得最终结果。

但是,我仍然无法理解如何重塑这些高维数组。我有这个4D数组:

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

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


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

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

这是形状(2, 2, 2, 2),我想将其重塑为(4,4)。有人可能会认为这显然与

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

但是,上述重塑并没有给我预期的结果

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

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


解决方案 1:

nd转型nd的总体思路

nd这种转变的想法nd只使用两件事 -

  • 排列轴(如果所需的排列顺序是滚动顺序,或者只需交换两个轴,则使用numpy.transposenumpy.moveaxis或)以及numpy.rollaxis`numpy.swapaxes`

  • 重塑。

排列轴:为了获得这样的顺序,即扁平版本与输出的扁平版本相对应。因此,如果您最终以某种方式使用了两次,请再查看一次,因为您不应该这样做。

重塑:分割轴或将最终输出变成所需形状。分割轴大多在开始时需要,当输入为低维时,我们需要将其分割成块。同样,您不需要超过两次。

因此,一般来说我们会有三个步骤:

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

 Create more axes             Bring axes             Merge axes
                          into correct order

回溯法

给定输入和输出,最安全的解决方法是通过所谓的回溯方法,即分割输入的轴(从较小nd到较大时nd)或分割输出的轴(从较大nd到较小时nd)。分割的想法是使较小轴的维度数nd与较大轴的维度数相同nd。然后,​​研究输出的步幅并将其与输入进行匹配以获得所需的置换顺序。最后,如果最终的维度较小,则可能需要在最后进行重塑(默认方式或 C 顺序)nd以合并轴。

如果输入和输出的维度数相同,那么我们需要将两者分开并分成块,然后研究它们之间的差异。在这种情况下,我们应该有额外的块大小输入参数,但这可能与主题无关。

例子

让我们使用这个特定案例来演示如何应用这些策略。在这里,输入是4D,而输出是2D。所以,很可能我们不需要重塑来分裂。所以,我们需要从排列轴开始。由于最终输出不是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]])

此外,这是一个从大到小ndnd转换,因此回溯方法将涉及分割输出、研究其步幅并与输入中的相应值进行匹配:

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

更多示例

我翻遍了我的历史,发现很少Q&As有基于转换ndnd。这些可以作为其他示例案例,尽管解释较少(大多数情况下)。如前所述,最多两个reshapes和最多一个swapaxes/transpose在所有地方都有效。它们列在下面:

  • Python 将三维数组重塑为二维数组

  • 使用 python/numpy 重塑数组

  • 合并不重叠的数组块

  • 从 Numpy 三维数组转换为二维数组

  • 如何使用 reshape 将 N 长度向量重塑为 numpy 中的 3x(N/3) 矩阵

  • 从四维列表构建图像

  • 在多维空间中将多个子矩阵重塑/组合为一个矩阵

  • 将多个小的二维矩阵交织成一个更大的矩阵

  • 如何按3X3检索每个部分?

  • 将 3D Numpy 数组重塑为 2D 数组

  • 通过更大的矩阵在子矩阵中迭代

  • 将二维 NumPy 数组重组为三维

  • Numpy 将形状从(3,512,660,4)更改为(3,2048,660,1)

  • Numpy:旋转M的子矩阵m

  • 将 3D numpy 数组拆分为 3D 块

  • 将 3D 矩阵转换为级联 2D 矩阵

  • 重新排列 numpy 数组

  • Numpy:沿指定轴重塑数组

  • 如何从二维数组构造二维数组

  • 如何由子矩阵形成矩阵?

  • Python:将 3D 图像系列重塑为像素系列

解决方案 2:

看起来您正在寻找一个transpose后跟一个的reshape

x.transpose((2, 0, 3, 1)).reshape(np.prod(x.shape[:2]), -1)

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

为了帮助您理解为什么需要转置,让我们分析一下您错误形状的输出(通过一次reshape调用获得)以了解它为什么不正确。

这个结果的简单 2D 重塑版本(没有任何转置)如下所示 -

x.reshape(4, 4)

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

现在根据您的预期输出考虑此输出 -

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

您会注意到,您的实际结果是通过对错误形状的输出进行 Z 形遍历获得的 -

start
    | /|     /| /|
    |/ |    / |/ |
      /    /    / 
     /    /    /
    | /| /    | /|
    |/ |/     |/ |
                 end

这意味着您必须以不同的步幅移动数组才能获得实际结果。总之,简单的重塑是不够的。您必须转置原始数组,使这些 Z 形元素彼此相邻,以便后续的重塑调用为您提供所需的输出。

要了解如何正确转置,您应该沿着输入跟踪元素,并找出需要跳转到哪些轴才能到达输出中的每个元素。转置随之而来。Divakar的回答很好地解释了这一点。

解决方案 3:

Divarkar 的回答很棒,尽管有时对我来说只需检查transposereshape涵盖所有可能的情况就更容易。

例如,以下代码

n, m = 4, 2
arr = np.arange(n*n*m*m).reshape(n,n,m,m)
for permut in itertools.permutations(range(4)):
    arr2 = (arr.transpose(permut)).reshape(n*m, n*m)
    print(permut, arr2[0])

给出了使用transpose+可以从 4 维数组中获得的所有结果reshape。因为我知道输出应该是什么样子,所以我只会选择显示正确答案的排列。如果我没有得到我想要的结果,那么transpose+reshape就不够通用,无法满足我的情况,我必须做一些更复杂的事情。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3416  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2228  
  敏捷每日站会作为敏捷项目管理中的关键环节,对于提升产品生命周期管理(PLM)效率有着不可忽视的作用。PLM涵盖了产品从概念产生到最终报废的全过程管理,涉及众多环节与人员,而每日站会能够通过优化沟通机制,让信息在团队中快速、准确地流动,从而推动整个PLM流程更加顺畅、高效。接下来,我们将深入探讨如何通过四步优化沟通机制,...
plm系统   0  
  在企业的发展进程中,产品生命周期管理(PLM)项目管理至关重要,而数据驱动决策则是提升PLM项目管理效能的关键手段。通过运用合适的分析模型,企业能够从海量数据中挖掘有价值的信息,为决策提供有力支撑,进而优化产品全生命周期的各个环节。以下将详细介绍助力PLM项目管理实现数据驱动决策的5大分析模型。需求分析模型需求分析是P...
plm系统功能介绍   0  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与运营中扮演着至关重要的角色。它涵盖了从产品概念设计到退役的全流程管理,确保产品数据的有效整合与协同。然而,在复杂多变的商业环境中,黑天鹅事件随时可能降临,给企业带来难以预估的冲击。这些意外事件具有不可预测性、极大的影响力和事后的可解释性等特点,会对PLM系统的正常运...
plm系统的主要功能模块   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用