numpy数组如何快速压缩尾维度?

6

在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] - Joe Kington
1
@JoeKington: 这是正确的(尝试一下)。x.shape[:-2] 返回 x.shape 到倒数第二个元素(但不包括它)。因此对于一个三维数组 x,它仅返回 x.shape 的第一个元素。我使用 [:-2] 而不是 [0],因为我正在寻找适用于所有 N>2 的 ND 数组的通用解决方案。 - EelkeSpaak
@ElkeSpaak - 对,我当时想得不够清晰。 - Joe Kington
MATLAB能够处理4维或5维矩阵吗? - hpaulj
3个回答

3

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不同,它只是将最后两个维度合并。像MATLAB一样将其压缩到2维是一个更简单的表达式。

MATLAB之所以简洁,仅仅是因为您的需求符合它的假设。 numpy的等效代码并不那么简洁,但可以给您更多的控制权。

例如,保留最后一个维度或将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形状的相同信息,但这是一种更简洁的处理重塑的方式。


2
它还有一个“好处”,即如果重塑不能在不复制的情况下完成,它将引发错误,因此我经常将其用作断言我的代码是否有效地使用内存的形式。 - Jaime
如果 x 的维度高于 3,为什么不使用 x.shape = *(x.shape[:-2]), -1 - tjysdsg

1
您可以使用 np.hstack
>>> np.hstack(x).shape
(25, 625)

np.hstack 接受一系列数组并将它们水平堆叠成一个单独的数组。


1
这是一个有趣的np.hstack用法!然而,它与x.reshape(x.shape[:-2] + (-1,))不产生相同的结果,因此应谨慎使用。进一步思考后,我认为正在发生的是np.hstack将数组的第一个维度视为可迭代维度,因此返回与np.hstack(x[0,:,:],x[1,:,:],...)相同的结果。我需要保留第一个维度不变的功能(即以前在x[0,:,:]中的所有数据现在都在x[0,:]中),就像Matlab版本一样。 - EelkeSpaak
你想要一个新的数组还是只想要它的形状? - Mazdak
我需要的是数组本身的内容,形状只是为了说明。我编辑了原来的问题以使这更加清晰。 - EelkeSpaak
@EelkeSpaak,你能否添加一个期望结果的最小示例? - Mazdak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接