减少n维numpy数组维数的有效方法

时间:2015-04-13 14:48:49

标签: python arrays numpy merge concatenation

我正在开展一个项目,我有一组用于手势识别的样本(ChaLearn数据集)。

输入是(10000,6,32,64,64)数组。我有10000个例子,6个featuremaps(正文,l-hand,r-hand in depth和rgb images),32帧64 x 64。

我必须只选择深度图像(指数1,3和5)和32帧中的4帧(指数8,13,18,25)

我对python并不熟悉,所以我一直在搞乱,我认为我的解决方案很好,但它确实很慢。大多数情况下,这两个选项占用了大量时间(此位为70-80秒)。

samples.shape在开始时给了我(10000,6,32,64,64)

samples = samples[0:samples.shape[0],0:samples.shape[1],(7,13,18,25)]
samples = samples[0:samples.shape[0],(1,3,5)]
samples = floatX(samples.reshape((samples.shape[0],12,64,64)))/255.

samples.shape最后给了我(10000,12,64,64)。

有没有更有效的方法来实现我的目标?或者我在这里完全错了?

暂时忽略floatx部分:)

3 个答案:

答案 0 :(得分:2)

正如在另一个答案中所提到的,在numpy中有一些关于使这更容易的讨论,但在你的情况下,因为你想要索引的两个轴在形状上是相邻的,所以事情并没有那么糟糕。在完全避免使用中间副本后,这应该可以帮助您:

depth_idx = np.array([1, 3, 5], dtype=np.intp)
frame_idx = np.array([8, 13, 18, 25], dtype=np.intp)
samples = samples[:, depth_idx[:, None], frame_idx].reshape(-1, 12, 64, 64)

实际上,由于您的depth_idx恰好可以作为切片写入,因此对于这种特殊情况,您实际上会做得更好:

samples = samples[:, 1::2, frame_idx].reshape(-1, 12, 64, 64)

答案 1 :(得分:1)

首先,你可以samples[:,:,(7,13,18,25)]。但是,这很慢的原因是因为你正在做2个复制操作。你现在无法解决这个问题,尽管你可以使用take来简化一些事情:

samples = np.take(np.take(samples, [7,13,18,25], axis=2), [1,3,4], axis=1)

实际上正在进行的工作使您正在尝试的操作变得更加容易,但它还没有准备好。

如果你没有使用numpy 1.9,你肯定应该升级到它,因为你正在做的“花哨”索引要快得多。 take版本在早期版本中会更快。

答案 2 :(得分:1)

  

是否有更有效的方法来实现我的目标?

如果您愿意研究另一层抽象,您可能需要考虑为更大数据设计的格式。就个人而言,我使用HDF,它有一些不错的python模块,如h5pypytables

我看到的两个主要优点是,您将能够一次存储更大的数据集(因为您不必将整个集合加载到内存中),并且您将能够将元数据应用于数据(.attrs)。当你构建hdf数据集时,你可以组织它,这样你对“索引1,3和5”这样的东西的“查询”可能更合乎逻辑。