np.unravel_index的直观解释是什么?
What is an intuitive explanation of np.unravel_index?
标题说的差不多。我已经阅读了文档并且已经使用该函数一段时间了,但我无法辨别这种转换的物理表现是什么。
计算机内存是线性寻址的。每个存储单元对应一个数字。一个内存块可以根据基址(它的第一个元素的内存地址)和项目索引来寻址。例如,假设基址为 10,000:
item index 0 1 2 3
memory address 10,000 10,001 10,002 10,003
要存储多维块,必须以某种方式使它们的几何形状适合线性内存。在 C
和 NumPy
中,这是逐行完成的。二维示例为:
| 0 1 2 3
--+------------------------
0 | 0 1 2 3
1 | 4 5 6 7
2 | 8 9 10 11
因此,例如,在这个 3×4 块中,二维索引 (1, 2)
将对应于线性索引 6
,即 1 x 4 + 2
。
unravel_index
则相反。给定线性索引,它会计算相应的 ND
索引。因为这取决于块尺寸,所以这些也必须通过。因此,在我们的示例中,我们可以从线性索引 6
:
中获取原始二维索引 (1, 2)
>>> np.unravel_index(6, (3, 4))
(1, 2)
注意:以上内容忽略了一些细节。 1) 将项目索引转换为内存地址还必须考虑项目大小。例如,一个整数通常有 4 或 8 个字节。因此,在后一种情况下,项目 i
的内存地址将为 base + 8 x i
。 2). NumPy 比建议的要灵活一些。如果需要,它可以逐列组织 ND
数据。它甚至可以处理内存中不连续的数据,例如留有间隙等
我们将从文档中的示例开始。
>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))
首先,(7,6)
指定我们要将索引转回的目标数组的维数。其次,[22, 41, 37]
是这个数组的一些索引 如果数组被展平。 如果一个 7 x 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*]
如果我们将这些索引展开回到它们在暗淡 (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
函数的 return 值告诉你 如果数组是 [=22, 41, 37] 的索引应该是什么没有被压扁。如果数组没有展平,这些索引应该是 [(3, 4), (6, 5), (6,1)]
。换句话说,该函数将展平数组中的索引传输回其未展平版本。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html
这与其他两个答案在内容上没有什么不同,但可能更直观。如果你有一个二维矩阵或数组,你可以用不同的方式引用它。您可以键入 (row, col) 以获取 (row, col) 处的值,或者您可以为每个单元格指定一个数字索引。 unravel_index 只是在这两种引用矩阵值的方式之间进行转换。
这可以扩展到大于 2 的维度。您还应该知道 np.ravel_multi_index(),它执行反向转换。请注意,它需要 (row, col) 和数组的形状。
我还看到我在索引矩阵中有两个 10 -- 糟糕。
我可以用非常简单的例子来解释。这适用于 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]
它 returns 索引的 x, y(因为 X 是二维的)。
如果申请ravel_multi_index获得idx
:
>>> 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数组)
- 它仅适用于索引,即输入和输出都是索引
这只适用于2D的情况,但是两个坐标np.unravel_index函数returns在这个例子中相当于分别做floor除法和应用取模函数。
for j in range(1,1000):
for i in range(j):
assert(np.unravel_index(i,(987654321,j))==(i//j,i%j))
形状数组的第一个元素(即 987654321)是没有意义的,除了设置一个上限来说明函数可以传递多大的未分解的线性索引。
标题说的差不多。我已经阅读了文档并且已经使用该函数一段时间了,但我无法辨别这种转换的物理表现是什么。
计算机内存是线性寻址的。每个存储单元对应一个数字。一个内存块可以根据基址(它的第一个元素的内存地址)和项目索引来寻址。例如,假设基址为 10,000:
item index 0 1 2 3
memory address 10,000 10,001 10,002 10,003
要存储多维块,必须以某种方式使它们的几何形状适合线性内存。在 C
和 NumPy
中,这是逐行完成的。二维示例为:
| 0 1 2 3
--+------------------------
0 | 0 1 2 3
1 | 4 5 6 7
2 | 8 9 10 11
因此,例如,在这个 3×4 块中,二维索引 (1, 2)
将对应于线性索引 6
,即 1 x 4 + 2
。
unravel_index
则相反。给定线性索引,它会计算相应的 ND
索引。因为这取决于块尺寸,所以这些也必须通过。因此,在我们的示例中,我们可以从线性索引 6
:
(1, 2)
>>> np.unravel_index(6, (3, 4))
(1, 2)
注意:以上内容忽略了一些细节。 1) 将项目索引转换为内存地址还必须考虑项目大小。例如,一个整数通常有 4 或 8 个字节。因此,在后一种情况下,项目 i
的内存地址将为 base + 8 x i
。 2). NumPy 比建议的要灵活一些。如果需要,它可以逐列组织 ND
数据。它甚至可以处理内存中不连续的数据,例如留有间隙等
我们将从文档中的示例开始。
>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))
首先,(7,6)
指定我们要将索引转回的目标数组的维数。其次,[22, 41, 37]
是这个数组的一些索引 如果数组被展平。 如果一个 7 x 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*]
如果我们将这些索引展开回到它们在暗淡 (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
函数的 return 值告诉你 如果数组是 [=22, 41, 37] 的索引应该是什么没有被压扁。如果数组没有展平,这些索引应该是 [(3, 4), (6, 5), (6,1)]
。换句话说,该函数将展平数组中的索引传输回其未展平版本。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html
这与其他两个答案在内容上没有什么不同,但可能更直观。如果你有一个二维矩阵或数组,你可以用不同的方式引用它。您可以键入 (row, col) 以获取 (row, col) 处的值,或者您可以为每个单元格指定一个数字索引。 unravel_index 只是在这两种引用矩阵值的方式之间进行转换。
这可以扩展到大于 2 的维度。您还应该知道 np.ravel_multi_index(),它执行反向转换。请注意,它需要 (row, col) 和数组的形状。
我还看到我在索引矩阵中有两个 10 -- 糟糕。
我可以用非常简单的例子来解释。这适用于 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]
它 returns 索引的 x, y(因为 X 是二维的)。
如果申请ravel_multi_index获得idx
:
>>> 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数组)
- 它仅适用于索引,即输入和输出都是索引
这只适用于2D的情况,但是两个坐标np.unravel_index函数returns在这个例子中相当于分别做floor除法和应用取模函数。
for j in range(1,1000):
for i in range(j):
assert(np.unravel_index(i,(987654321,j))==(i//j,i%j))
形状数组的第一个元素(即 987654321)是没有意义的,除了设置一个上限来说明函数可以传递多大的未分解的线性索引。