¿Qué es una explicación intuitiva de np.unravel_index?

Más o menos lo que dice el título. He leído la documentación y he jugado con la función por un tiempo, pero no puedo discernir cuál es la manifestación física de esta transformación.

La memoria de la computadora se dirige de forma lineal. Cada celda de memoria corresponde a un número. Un bloque de memoria puede direccionarse en términos de una base, que es la dirección de memoria de su primer elemento, y el índice del elemento. Por ejemplo, asumiendo que la dirección base es 10,000:

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

Para almacenar bloques multidimensionales, su geometría debe hacerse de alguna manera para que quepa en la memoria lineal. En C y NumPy , esto se hace fila por fila. Un ejemplo 2D sería:

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

Así, por ejemplo, en este bloque de 3 por 4, el índice 2D (1, 2) correspondería al índice lineal 6 que es 1 x 4 + 2 .

unravel_index hace lo inverso. Dado un índice lineal, calcula el índice ND correspondiente. Ya que esto depende de las dimensiones del bloque, estas también deben ser aprobadas. Entonces, en nuestro ejemplo, podemos obtener el índice 2D original (1, 2) del índice lineal 6 :

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

Nota: Lo anterior pasa por alto algunos detalles. 1) La traducción del índice del elemento a la dirección de memoria también debe tener en cuenta el tamaño del elemento. Por ejemplo, un entero generalmente tiene 4 u 8 bytes. Entonces, en el último caso, la dirección de memoria para el elemento i sería base + 8 xi . 2). NumPy es un poco más flexible de lo sugerido. Puede organizar los datos de ND columna por columna si lo desea. Incluso puede manejar datos que no son contiguos en la memoria pero, por ejemplo, dejan espacios vacíos, etc.

Comenzaremos con un ejemplo en la documentación.

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

Primero, (7,6) especifica la dimensión de la matriz de destino en la que queremos convertir los índices de nuevo. Segundo, [22, 41, 37] hay algunos índices en esta matriz si la matriz está aplanada. Si una matriz de 7 por 6 se aplana, sus índices se verán como

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

Si volvemos a desplegar estos índices en sus posiciones originales en una matriz oscura (7, 6) , sería

  [[ 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) 

Los valores de retorno de la función unravel_index indican cuáles deberían haber sido los índices de [22, 41, 37] si la matriz no está aplanada. Estos índices deberían haber sido [(3, 4), (6, 5), (6,1)] si la matriz no está aplanada. En otras palabras, la función transfiere los índices en una matriz plana a su versión no desplegada.

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html

Esto no es diferente en contenido que las otras dos respuestas, pero podría ser más intuitivo. Si tiene una matriz 2D o matriz, puede hacer referencia a ella de diferentes maneras. Puede escribir (fila, columna), para obtener el valor en (fila, columna), o puede asignar a cada celda un índice de un solo número. unravel_index simplemente se traduce entre estas dos formas de referenciar valores en una matriz.

introduzca la descripción de la imagen aquí

Esto es extensible a dimensiones mayores a 2. También debe tener en cuenta np.ravel_index (), que realiza la transformación inversa. Tenga en cuenta que requiere el índice y la forma de la matriz.

También veo que tengo dos 10s en la matriz de índice – whoops.

Puedo explicarlo con un ejemplo muy simple. Esto es para np.ravel_multi_index así como np.unravel_index

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

Encuentra, donde todo el valor 3 se presenta en X

 idx = np.where(X==3) Output: idx = (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64)) ie, x = [1, 3, 3] y = [1, 0, 1] 

devuelve la x, y de los índices [porque X es bidimensional]


Si aplicas ravel_multi_index para idx obtenido

 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 

Del ejemplo anterior, podemos entender,

  • ravel_multi_index convierte los índices multidimensionales (nd array) en índices unidimensionales (array lineal)
  • Funciona solo en índices, es decir, tanto la entrada como la salida son índices

Los índices de resultados serán índices directos de X.ravel (). Puedes verificar en el siguiente x_linear

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

Considerando que, unravel_index es muy simple, justo al revés de lo anterior (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)) 

que es igual que idx = np.where (X == 3)

  • unravel_index convierte los índices unidimensionales (matriz lineal) en índices multidimensionales (matriz nd)
  • Funciona solo en índices, es decir, tanto la entrada como la salida son índices