numpy np.unravel_index的直观解释是什么?

lrl1mhuk  于 2023-08-05  发布在  其他
关注(0)|答案(6)|浏览(108)

我已经阅读了np.unravel_index的文档,并尝试了一下这个函数,但我不知道它在做什么。

ulydmbyx

ulydmbyx1#

计算机内存是线性寻址的。每个存储器单元对应于一个数字。一个内存块可以用一个基址和一个项索引来寻址,基址是它的第一个元素的内存地址。例如,假设基址为10,000:

item index      0       1       2       3
memory address  10,000  10,001  10,002  10,003

字符串
为了存储多维块,必须以某种方式使其几何形状适合线性存储器。在CNumPy中,这是逐行完成的。2D示例为:

| 0      1      2      3
--+------------------------
0 | 0      1      2      3
1 | 4      5      6      7
2 | 8      9     10     11


因此,例如,在这个3乘4的块中,2D索引(1, 2)将对应于线性索引6,即1 x 4 + 2
unravel_index做相反的事情。给定一个线性索引,它计算相应的ND索引。由于这取决于块尺寸,因此也必须通过这些尺寸。因此,在我们的例子中,我们可以从线性索引6中得到原始的2D索引(1, 2)

>>> np.unravel_index(6, (3, 4))
(1, 2)


注:上述内容仅涉及一些细节。1)将项索引转换为存储器地址也必须考虑项大小。例如,整数通常具有4或8个字节。因此,在后一种情况下,项i的内存地址将是base + 8 x i。2). NumPy比建议的要灵活一些。如果需要,它可以按列组织ND数据。它甚至可以处理内存中不连续的数据,例如留下间隙等。
额外阅读:ndarray内部存储器布局

ipakzgxi

ipakzgxi2#

我们将从文档中的一个示例开始。

>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))

字符串
首先,(7,6)指定我们要将索引转换回的目标数组的维度。第二,[22, 41, 37]是这个数组上的一些索引**如果数组是扁平的。**如果一个7乘6的数组是扁平的,它的索引将如下所示

[ 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*]


如果我们将这些索引恢复到它们在dim (7, 6)数组中的原始位置,则会是

[[ 0,   1,   2,   3,   4,   5],
       [ 6,   7,   8,   9,  10,  11],
       [12,  13,  14,  15,  16,  17],
       [18,  19,  20,  21, *22*, 23],  <- (3, 4)
       [24,  25,  26,  27,  28,  29],
       [30,  31,  32,  33,  34,  35],
       [36, *37*, 38,  39,  40, *41*]]
           (6, 1)               (6,5)


unravel_index函数的返回值告诉你**如果数组不是扁平的,[22,41,37]**的索引应该是什么。如果数组不是扁平的,这些索引应该是[(3, 4), (6, 5), (6,1)]。换句话说,该函数将flatten数组中的索引传输回其未flatten版本。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html

yvfmudvl

yvfmudvl3#

这与其他两个答案在内容上没有什么不同,但它可能更直观。如果你有一个二维矩阵或数组,你可以用不同的方式引用它。您可以键入(row,col),以获取(row,col)处的值,或者您可以为每个单元格指定一个单个数字索引。unravel_index只是在矩阵中引用值的这两种方式之间进行转换。


的数据
这可扩展到大于2的尺寸。您还应该知道np.ravel_multi_index(),它执行反向转换。注意它需要(row,col)和数组的形状。
我还看到索引矩阵中有两个10。

gwo2fgha

gwo2fgha4#

我可以用一个很简单的例子来解释。这是用于np.ravel_multi_index以及np.unravel_index

>>> X = np.array([[4,  2],
                  [9,  3],
                  [8,  5],
                  [3,  3],
                  [5,  6]])
>>> X.shape
(5, 2)

字符串
找到所有值3在X中的位置:

>>> idx = np.where(X==3)
>>> idx
(array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))


x = [1,3,3]y = [1,0,1]它返回索引的x,y(因为X是二维的)。
如果对idx应用ravel_multi_index,则获得:

>>> idx_flat = np.ravel_multi_index(idx, X.shape)
>>> idx_flat
array([3, 6, 7], dtype=int64)


idx_flat是X的线性指数,其中值为3。
从上面的例子中,我们可以理解:

  • ravel_multi_index将多维索引(nd数组)转换为一维索引(线性数组)
  • 它只适用于索引,即输入和输出都是索引

结果索引将是X.ravel()的直接索引。您可以在下面的x_linear中进行验证:

>>> x_linear = X.ravel()
>>> x_linear
array([4, 2, 9, 3, 8, 5, 3, 3, 5, 6])


然而,unravel_index非常简单,只是上面的反向(np.ravel_multi_index)

>>> idx = np.unravel_index(idx_flat , X.shape)
>>> idx
(array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))


idx = np.where(X==3)相同

  • unravel_index将一维索引(线性数组)转换为多维索引(nd数组)
  • 它只适用于索引,即输入和输出都是索引
5t7ly7z5

5t7ly7z55#

给定一个raveled_index到一个.ravel() ed数组中,np.unravel_index计算出到基数组中的等价的非展开索引:

import numpy as np

my_array = np.random.random((100, 42))
raveled_array = my_array.ravel()

raveled_index = 1337
unraveled_index = np.unravel_index(raveled_index, my_array.shape)

assert raveled_array[raveled_index] == my_array[unraveled_index]

字符串
两个很好的知道:

  1. raveled_array也称为flat_array;因此,raveled_indexflat_index只不过是“扁平”数组的索引。此外,由于平面阵列“丢失”了其原始形状信息,因此在调用np.unravel_index时需要添加此信息。
  2. unraveled_index通常被称为multi_index。这是因为您需要多个值(一个N元组)来索引任何具有my_array.dim == N的数组中的元素。因此,np.unravel_index的逆称为np.ravel_multi_index
xfyts7mz

xfyts7mz6#

这仅适用于2D情况,但是在这种情况下返回的两个坐标np.unravel_index函数分别等效于进行楼层划分和应用模函数。

for j in range(1,1000):
    for i in range(j):
        assert(np.unravel_index(i,(987654321,j))==(i//j,i%j))

字符串
形状数组的第一个元素(即987654321)是没有意义的,除了把一个上限多大的解开线性指数可以通过函数。

相关问题