Что такое интуитивное объяснение np.unravel_index?
Довольно многое, что говорится в названии. Я прочитал документацию, и я играл с этой функцией какое-то время, но я не могу различить, что такое физическое проявление этого преобразования.
Ответы
Ответ 1
Начнем с примера в документации.
>>> 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 обратно в его невыпущенную версию.
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html
Ответ 2
Компьютерная память адресуется линейно. Каждой ячейке памяти соответствует номер. Блок памяти может быть адресован в терминах базы, которая является адресом памяти ее первого элемента и индексом элемента. Например, если базовый адрес равен 10 000:
item index 0 1 2 3
memory address 10,000 10,001 10,002 10,003
Чтобы хранить многомерные блоки, их геометрия должна каким-то образом быть встроена в линейную память. В C
и NumPy
это выполняется по очереди. 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
. Поскольку это зависит от размеров блока, они также должны быть переданы. Итак, в нашем примере мы можем вернуть исходный 2D-индекс (1, 2)
из линейного индекса 6
:
>>> np.unravel_index(6, (3, 4))
(1, 2)
Примечание. Вышеупомянутые лозунги над несколькими деталями. 1) При переводе индекса элемента на адрес памяти также необходимо учитывать размер элемента. Например, целое число обычно имеет 4 или 8 байтов. Итак, в последнем случае адрес памяти для элемента i
будет base + 8 xi
. 2). NumPy немного более гибкий, чем предлагается. При желании он может организовывать столбцы по столбцам ND
. Он может даже обрабатывать данные, которые не смежны в памяти, но, например, оставляют пробелы и т.д.
Ответ 3
По содержанию это не отличается от двух других ответов, но может быть более интуитивным. Если у вас есть двумерная матрица или массив, вы можете ссылаться на нее по-разному. Вы можете набрать (row, col), чтобы получить значение в (row, col), или вы можете дать каждой ячейке индекс из одного числа. unravel_index просто переводит между этими двумя способами ссылки на значения в матрице.
Это может быть расширено до размеров больше 2. Вы также должны знать о np.ravel_multi_index(), который выполняет обратное преобразование. Обратите внимание, что для этого требуется индекс и форма массива.
Я также вижу, что у меня есть две десятки в матрице индекса - упс.
Ответ 4
Я могу объяснить это на очень простом примере. Это для 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)
Output: idx = (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
i.e, x = [1, 3, 3]
y = [1, 0, 1]
возвращает индексы x, y [потому что X двумерный]
Если вы примените ravel_multi_index для полученного idx
idx_flat = np.ravel_multi_index(idx, X.shape)
Output: idx_flat = array([3, 6, 7], dtype=int64)
idx_flat is a linear index of X where value 3 presents
Из приведенного выше примера мы можем понять,
- ravel_multi_index преобразует многомерные индексы (nd массив) в одномерные индексы (линейный массив)
- Работает только с индексами, т.е. и вход, и выход являются индексами
Индексы результата будут прямыми индексами X.ravel(). Вы можете проверить в ниже x_linear
x_linear = X.ravel()
Output: 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)
Output: (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
который совпадает с idx = np.where(X == 3)
- unravel_index преобразует одномерные индексы (линейный массив) в многомерные индексы (nd массив)
- Работает только с индексами, т.е. и вход, и выход являются индексами