【问题标题】:Advanced indexing is returning an array with the wrong shape高级索引返回一个形状错误的数组
【发布时间】:2017-04-10 05:47:12
【问题描述】:

我一直在使用this reference 来了解高级索引。一个具体的例子如下;

示例 假设 x.shape 是 (10,20,30) 并且 ind 是一个 (2,3,4) 形的索引 intp 数组,那么 result = x[...,ind,:] 的形状是 (10,2,3 ,4,30) 因为 (20,) 形的子空间已被 (2,3,4) 形的广播索引子空间取代。如果我们让 i, j, k 在 (2,3,4) 形子空间上循环,则 result[...,i,j,k,:] = x[...,ind[i,j,k ],:]。此示例产生与 x.take(ind, axis=-2) 相同的结果。

我一直试图理解这一点,为了帮助我,我得到了一个生成一些数组的小脚本。我有;

Indexing arrays
i => 12 x 25
j => 12 x 25
k => 12 x 1

Input array
x => 2 x 3 x 4 x 4

Output Array
Cols => 2 x 12 x 25

我用来制作Cols的代码如下;

cols = x[:, k, i, j]

根据我对示例 cols 的理解,实际上应该具有形状 (2 x 12 x 1 x 12 x 25 x 12 x 25)。我是这样来的;

它的原始尺寸是 2 x 3 x 4 x 4

2 不变,但所有其他维度都改变了

将 3 替换为 k,一个 12 x 1 的数组

前 4 个被 i 替换,一个 12 x 25 的数组

第二个 4 被 j 代替,也是一个 12 x 25 的数组

显然我在这里误解了一些东西,我哪里出错了?

【问题讨论】:

  • 也来自该文档部分:Advanced indexes always are broadcast and iterated as one: 相反,您是单独应用它们。

标签: python arrays numpy


【解决方案1】:

这就是你想要的:

i=np.random.randint(0,4,(12,25))
j=np.random.randint(0,4,(12,25))
k=np.random.randint(0,3,(12,1))
x=np.random.randint(1,11,(2,3,4,4))

x1 = x[:,k,:,:][:,:,:,i,:][:,:,:,:,:,j]
x1.shape

(2, 12, 1, 12, 25, 12, 25)

为什么原来的方法不能这样工作?我认为高级索引可能会贪婪地确定您是否同时按多个维度进行索引。例如,您的原始形状:

x.shape
(2,3,4,4) 

可以有多种解释。您想要的是每个轴都是独立的,但将其解释为 6 个(4,4) 矩阵或 2 个(3,4,4) 张量同样有效。因此,当通过[...,i,j] 进行索引时,您可以将i 解释为在第三个轴上,而j 在第四个轴上,或者i,j 在最后两个轴上。 Numpy 猜你的意思是第二个:

x[...,i,j].shape
(2,3,12,25)

您也可以将x 解释为 8 个(3,4) 矩阵,当您这样做时会发生这种情况:

x[:,k,i,:].shape
(2,12,25,4)

请注意,它还将您的 (12,1) k 数组广播到 (12,25) 以匹配 i 进行索引。您可以通过在k 上使用.squeeze() 来确认广播正在发生:

x[:,k.squeeze(),i,:]
Traceback (most recent call last):
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (12,) (12,25)

如果您将 x 解释为 2 个 (3,4,4) 张量,则 numpy 会两者兼而有之。它将k 广播到(12,25),然后根据一组三个(12,25) 索引数组对最后三个维度进行索引,将所有三个维度作为一个单元减少。

您可以使用np.ix_ 在某种程度上覆盖此行为,但np.ix_ 的所有参数都必须是 1d,因此如果没有扁平化和重塑,您会很不走运,这有点违背了这里的目的,但也作品:

x2 = x[np.ix_(np.arange(x.shape[0]), k.flat, i.flat, j.flat)].reshape((x.shape[0], ) + k.shape + i.shape + j.shape)

x2.shape
(2, 12, 1, 12, 25, 12, 25)

np.all(x1 == x2)
True

【讨论】:

  • 谢谢丹尼尔!我真的很想了解 numpy 如何创建 Cols 数组,但我无法在脑海中容纳那么多维度!
  • 是的,我不是那种人。试着这样看:如果a.shape=(5,5),那么a[np.arange(5),np.arange(5)]a 不同,它是a[a[1,1], a[2,2], a[3,3], a[4,4], a[5,5]] 的对角线。换句话说,a[np.arange(5),np.arange(5)].shape == arange(5).shape.
  • 所有三个索引数组都广播到 (12,25)。广播对于理解多个索引数组的作用至关重要。使用 (n,) 和 (n,) 进行索引会产生 (n,) 输出;使用 (n,1) 和 (m) 进行索引会产生 (n,m) 输出。切片会增加一个维度,但如果切片位于索引元组的中间,则会出现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
相关资源
最近更新 更多