【问题标题】:Reshaping rank > 2 numpy arrays in Python在 Python 中重塑 rank > 2 个 numpy 数组
【发布时间】:2025-12-16 02:30:01
【问题描述】:

我正在使用 numpy 数组作为 Python 中的 rank > 2 张量,并试图将这样的张量重塑为矩阵,即 rank-2 数组。标准的 ndarray.reshape() 函数并不真正适用于此,因为我需要以特定方式对张量的索引进行分组。我的意思是:假设我从 3 阶张量 T_ijk 开始。例如,我正在尝试找到一个将输出 2 阶张量 T_(j)(ik) 的函数,即对于此示例,所需的输入/输出将是

[Input:]      T=np.array([[[1 2]
                           [3 4]]
                          [[5 6]
                           [7 8]]])

[Output:]     array([[1, 2, 5, 6],
                     [3, 4, 7, 8]])

另外,有朋友建议我tensorflow可能有这样的功能,但我没用过。有人对此有任何见解吗?

【问题讨论】:

  • 请按照*.com/help/minimal-reproducible-example提供示例输入和输出
  • 您需要转置(交换)一些轴以及 reshaoe 以获得您想要的顺序。
  • 是的,我看到除了整形之外的几次转置在这样一个简单的例子中是如何工作的,但是如果我正在处理一个更复杂的案例,例如如果我想将 T_ijklmno 转换为 T_(ilo)(jmnk) 必须弄清楚要切换哪些轴以及如何重塑可能会失控......这就是我正在寻找内置解决方案的原因

标签: python numpy tensorflow multidimensional-array tensor


【解决方案1】:

试试这个 -

k = 1
m = 2
i = 5
j = 5
l = 2

#dummy T_ijklm
T = np.array(range(100)).reshape(k,m,i,j,l)
T_new = T.reshape(k*m,i*j*l)

print('Original T:',T.shape)
print('New T:',T_new.shape)

#(km)(ijl) = 2*50

Original T: (1, 2, 5, 5, 2)
New T: (2, 50)

新张量现在是 2 级

array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
        66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
        82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
        98, 99]])

【讨论】:

  • 谢谢!我明白你在说什么,但这不会弄乱元素的顺序吗?我认为虽然这可能会将数组的维度更改为我想要的,但我实际上并没有用新索引“重新标记”元素,这是我真正需要的......
  • 我对你用新索引“重新标记”元素的意思有点困惑。张量只是按维度划分的元素的集合。更高等级的张量将有 5 个维度,对其进行整形只会降低维度而不影响项目本身。
【解决方案2】:
In [216]: arr = np.arange(1,9).reshape(2,2,2)                                                        
In [217]: arr                                                                                        
Out[217]: 
array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])

reshape 将元素保持在原始 [1,2,3,4,5...] 顺序中

In [218]: arr.reshape(2,4)                                                                           
Out[218]: 
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

找出正确的转置顺序可能很棘手。有时我只是尝试几件事。在这里我注意到你想保留最后一个维度的顺序,所以我们要做的就是交换前 2 个轴:

In [219]: arr.transpose(1,0,2)                                                                       
Out[219]: 
array([[[1, 2],
        [5, 6]],

       [[3, 4],
        [7, 8]]])

现在重塑做我们想要的:

In [220]: arr.transpose(1,0,2).reshape(2,4)                                                          
Out[220]: 
array([[1, 2, 5, 6],
       [3, 4, 7, 8]])

据我所知,这个序列是最好的“内置”方法。

你评论:

如果我想将 T_ijklmno 转换为 T_(ilo)(jmnk) 必须弄清楚要切换哪些轴以及如何重塑可能会失控......这就是我寻找内置解决方案的原因

T_.... 符号提醒我我们可以使用einsum 来进行转置:

In [221]: np.einsum('ijk->jik',arr)                                                                  
Out[221]: 
array([[[1, 2],
        [5, 6]],

       [[3, 4],
        [7, 8]]])

所以T_ijklmno to T_(ilo)(jmnk) 可能会变成

np.einsum('ijklmno->ilojmnk',T).reshape(I*L*O, J*M*N*K)
T.transpose(0,3,6,1,4,5,2).reshape(...)

(我只是通过观察你的T 表达式来写这些的)

有很多方法可以转置和重塑具有 7 维的数组,因此想出比现有方法更通用的方法(转置、交换轴、einsum)几乎没有意义。像使用“ijk...”一样简单地识别维度是问题中最困难的部分。

【讨论】: