【问题标题】:Easy way to collapse trailing dimensions of numpy array?折叠numpy数组尾随维度的简单方法?
【发布时间】:2015-08-27 02:30:48
【问题描述】:

在 Matlab 中,我可以执行以下操作:

X = randn(25,25,25);
size(X(:,:))

ans = 
    25   625

我经常发现自己想快速折叠数组的尾随维度,但不知道如何在 numpy 中做到这一点。

我知道我能做到:

In [22]: x = np.random.randn(25,25,25)
In [23]: x = x.reshape(x.shape[:-2] + (-1,))
In [24]: x.shape
Out[24]: (25, 625)

但是x.reshape(x.shape[:-2] + (-1,)) 比简单的x(:,:) 简洁得多(并且需要更多关于x 的信息)。

我显然已经尝试过类似的 numpy 索引,但这并没有按预期工作:

In [25]: x = np.random.randn(25,25,25)
In [26]: x[:,:].shape
Out[26]: (25, 25, 25)

关于如何以简洁的方式折叠数组的尾随维度的任何提示?

编辑:请注意,我关注的是结果数组本身,而不仅仅是它的形状。我只是在上面的例子中使用size()和x.shape来表示数组是什么样的。

【问题讨论】:

  • 附带说明,您的示例不正确...x.shape[:-2] 将产生一个空元组。 (添加-1 意味着该数组将被“展平”为一个15625 长度的数组。)我猜你的意思是x.shape[0]?
  • @JoeKington:它是正确的(试试看)。 x.shape[:-2] 返回 x.shape 直到(但不包括)倒数第二个元素。所以对于 3D 数组 x,它只返回 x.shape 的第一个元素。我使用了[:-2] 而不是[0],因为我正在寻找一种适用于所有 N>2 的 ND 阵列的通用解决方案。
  • @ElkeSpaak - 对。我没有想清楚。
  • 那个 MATLAB 是否可以处理 4 维或 5 维矩阵?

标签: python arrays numpy multidimensional-array


【解决方案1】:

4d 或更高版本会发生什么?

octave:7> x=randn(25,25,25,25);
octave:8> size(x(:,:))
ans =
      25   15625

您的 (:,:) 将其缩小为 2 个维度,并结合最后一个维度。最后一个维度是 MATLAB 自动添加和折叠维度的地方。

In [605]: x=np.ones((25,25,25,25))

In [606]: x.reshape(x.shape[0],-1).shape  # like Joe's
Out[606]: (25, 15625)

In [607]: x.reshape(x.shape[:-2]+(-1,)).shape
Out[607]: (25, 25, 625)

您的reshape 示例与 MATLAB 不同,它只是折叠最后一个 2。像 MATLAB 一样将其折叠到二维是一个更简单的表达式。

MATLAB 很简洁,因为您的需求符合它的假设。 numpy 等效项不是那么简洁,但可以提供更多控制权

例如保留最后一个维度,或者将维度 2 x 2 组合起来:

In [608]: x.reshape(-1,x.shape[-1]).shape
Out[608]: (15625, 25)
In [610]: x.reshape(-1,np.prod(x.shape[-2:])).shape
Out[610]: (625, 625)

什么是等效的 MATLAB?

octave:24> size(reshape(x,[],size(x)(2:end)))
ans =
15625      25
octave:31> size(reshape(x,[],prod(size(x)(3:end))))

【讨论】:

    【解决方案2】:

    您可能会发现直接修改shape 属性会更简洁一些。例如:

    import numpy as np
    
    x = np.random.randn(25, 25, 25)
    x.shape = x.shape[0], -1
    
    print x.shape
    print x
    

    这在功能上等同于reshape(在数据排序等意义上)。显然,它仍然需要关于x 形状的相同信息,但它是一种更简洁的处理重塑的方式。

    【讨论】:

    • 它有一个额外的“好处”,如果没有副本就无法进行整形,则会引发错误,所以我经常使用它作为断言我的代码有效使用内存的一种形式.
    • 如果x 的维度大于3,为什么不x.shape = *(x.shape[:-2]), -1
    【解决方案3】:

    你可以使用np.hstack:

    >>> np.hstack(x).shape
    (25, 625)
    

    np.hstack 获取一系列数组并将它们水平堆叠以形成单个数组。

    【讨论】:

    • np.hstack 的用法很有趣!但是,它不会产生与x.reshape(x.shape[:-2] + (-1,)) 相同的结果,因此应谨慎使用。再想一想,我相信np.hstack 将数组的 first 维度视为可迭代维度,因此返回与np.hstack(x[0,:,:],x[1,:,:],...) 相同的值。我需要保持第一个维度不变的功能(即以前在 x[0,:,:] 中的所有数据现在都在 x[0,:] 中),就像 Matlab 版本一样。
    • 你想要一个新数组还是只想要它的形状?
    • 我关注的是数组本身的内容,形状只是为了说明。我编辑了原始问题以使其更清楚。
    • @EelkeSpaak 你能添加一个你预期结果的最小例子吗?
    猜你喜欢
    • 1970-01-01
    • 2017-06-07
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 2017-01-27
    • 2013-09-20
    • 1970-01-01
    相关资源
    最近更新 更多