Python numpy 4D阵列高级索引与示例

Python numpy 4D阵列高级索引与示例,python,arrays,numpy,numpy-ndarray,Python,Arrays,Numpy,Numpy Ndarray,我正在阅读一些深入的学习代码。我在numpy数组中的高级索引上有问题。我正在测试的代码: import numpy x = numpy.arange(2 * 8 * 3 * 64).reshape((2, 8, 3, 64)) x.shape p1 = numpy.arange(2)[:, None] sd = numpy.ones(2 * 64, dtype=int).reshape((2, 64)) p4 = numpy.arange(128 // 2)[None, :] y = x[

我正在阅读一些深入的学习代码。我在numpy数组中的高级索引上有问题。我正在测试的代码:

import numpy

x = numpy.arange(2 * 8 * 3 * 64).reshape((2, 8, 3, 64))
x.shape

p1 = numpy.arange(2)[:, None]
sd = numpy.ones(2 * 64, dtype=int).reshape((2, 64))
p4 = numpy.arange(128 // 2)[None, :]

y = x[p1, :, sd, p4]
y.shape
为什么
y
的形状是
(2,64,8)

以下是上述代码的输出:

>>> x.shape
(2, 8, 3, 64)

>>> p1
array([[0], [1]])

>>> sd
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])

>>> p4
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]])

>>> y.shape
(2, 64, 8)
我读到:

我认为这与广播有关:

x
形状是
(2,8,3,64)

p1
很简单,它是
数组([[0],[1]]),
只是指选择第一维度的ind
0,1
。双阵列用于广播

p2
,这意味着选择第二维度中的所有8个元素

p3
很复杂,它包含两个“列表”,可以从维度3的3个元素中选择一个,因此生成的新三维应该是1

p4
表示它选择了第四维中的所有64个元素

所以我认为
y.shape
应该是
(2,8,1,64)


但正确的答案是
(2,64,8)
。为什么?

当我第一次在numpy中遇到花式索引时,我也遇到了同样的问题。简单的回答是没有什么诀窍:奇特的索引只是将元素选择到与索引形状相同的输出中。使用纯粹奇特的索引,输出数组的形状将与广播的索引数组相同()。输出的形状与输入的形状几乎没有任何关系,除非您也加入一个常规的切片索引()。你的情况是后者,这增加了混乱

让我们看看你的指数,看看发生了什么:

y = x[p1, :, sd, p4]
x.shape -> 2, 8, 3, 64
p1.shape -> 2, 1
sd.shape -> 2, 64
p4.shape -> 1, 64
关于如何进行的具体文档如下:

需要区分指数组合的两种情况:

  • 高级索引由一个片段分隔,
    省略号
    或。例如
    x[arr1,:,arr2]
  • 高级索引彼此相邻。例如
    x[…,arr1,arr2,:]
    而不是x
    [arr1,:,1]
    ,因为
    1
    是这方面的高级索引
在第一种情况下,高级索引操作产生的维度首先出现在结果数组中,然后是子空间维度。在第二种情况下,高级索引操作产生的维度插入到结果数组中与初始数组中相同的位置(后一种逻辑使简单的高级索引的行为与切片类似)

重点矿山

请记住,在上述两种情况下,索引部分的维度都是索引数组的维度,而不是要索引的数组

那么,您应该期望看到的是广播维度为
p1
sd
p4
2,64
),然后是第二维度的大小
x
8
)。这确实是您得到的:

>>> y.shape
(2, 64, 8)

非常感谢您的解释。我正在消化信息。我可以问几个后续问题吗?选择结果正确吗?代码正在尝试索引\u选择(2,8,3,64)的第三维度,因此我必须将轴从(2,64,8)交换到(2,8,1,64)?是否有更直接的方法获得所需的结果:(2,8,1,64)?谢谢!我不明白这句话“例如x[…,arr1,arr2,:],但不是x[arr1,:,1],因为1在这方面是一个高级索引。”,如果1是一个高级索引,那么x[arr1,:,1]与x[arr1,:,arr2]的情况不是一样吗?@mahon。第一个问题:完全正确。它警告你,`x[arr1,:,1]`与
x相同[arr1,:,arr2]
。如果所有索引都是切片,那么标量将充当切片,因此需要注意。@mahon。您可以用适当的切片替换生成的索引,然后一切都会解决。