¿Cómo el método transpose () de NumPy permuta los ejes de una matriz?

In [28]: arr = np.arange(16).reshape((2, 2, 4)) In [29]: arr Out[29]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) In [32]: arr.transpose((1, 0, 2)) Out[32]: array([[[ 0, 1, 2, 3], [ 8, 9, 10, 11]], [[ 4, 5, 6, 7], [12, 13, 14, 15]]]) 

Cuando pasamos una tupla de enteros a la función transpose() , ¿qué sucede?

Para ser específico, esta es una matriz 3D: ¿cómo transforma NumPy la matriz cuando paso la tupla de ejes (1, 0 ,2) ? ¿Puedes explicar a qué fila o columna se refieren estos enteros? ¿Y cuáles son los números de eje en el contexto de NumPy?

Para transponer una matriz, NumPy simplemente intercambia la información de forma y zancada de cada eje. Aquí están los pasos:

 >>> arr.strides (64, 32, 8) >>> arr.transpose(1, 0, 2).strides (32, 64, 8) 

Observe que la operación de transposición cambió las zancadas para el eje 0 y el eje 1. Las longitudes de estos ejes también se intercambiaron (ambas longitudes son 2 en este ejemplo).

No es necesario copiar datos para que esto suceda; NumPy puede simplemente cambiar la forma en que se ve en la memoria subyacente para construir la nueva matriz.


Visualizando avances

El valor de zancada representa el número de bytes que deben recorrerse en la memoria para alcanzar el siguiente valor de un eje de una matriz.

Ahora, nuestra matriz 3D arr mira esto (con ejes etiquetados):

introduzca la descripción de la imagen aquí

Esta matriz se almacena en un bloque de memoria contiguo ; Esencialmente es unidimensional. Para interpretarlo como un objeto 3D, NumPy debe saltar un cierto número constante de bytes para moverse a lo largo de uno de los tres ejes:

introduzca la descripción de la imagen aquí

Como cada entero ocupa 8 bytes de memoria (estamos usando el tipo de dt64), el valor de zancada para cada dimensión es 8 veces el número de valores que necesitamos saltar. Por ejemplo, para moverse a lo largo del eje 1, se saltan cuatro valores (32 bytes), y para moverse a lo largo del eje 0, se deben saltar ocho valores (64 bytes).

Cuando escribimos arr.transpose(1, 0, 2) estamos intercambiando los ejes 0 y 1. La matriz transpuesta se ve así:

introduzca la descripción de la imagen aquí

Todo lo que debe hacer NumPy es intercambiar la información de zancada para el eje 0 y el eje 1 (el eje 2 no se modifica). Ahora debemos saltar más para movernos a lo largo del eje 1 que del eje 0:

introduzca la descripción de la imagen aquí

Este concepto básico funciona para cualquier permutación de los ejes de una matriz. El código real que maneja la transposición está escrito en C y se puede encontrar aquí .

Como se explica en la documentación :

Por defecto, invierta las dimensiones, de lo contrario permute los ejes de acuerdo con los valores dados.

Por lo tanto, puede pasar un parámetro de axes opcional que define el nuevo orden de dimensiones.

Por ejemplo, la transposición de las dos primeras dimensiones de una matriz de píxeles VGA RGB:

  >>> x = np.ones((480, 640, 3)) >>> np.transpose(x, (1, 0, 2)).shape (640, 480, 3) 

En notación C, su matriz sería:

 int arr[2][2][4] 

que es una matriz 3D que tiene 2 matrices 2D. Cada una de esas matrices 2D tiene 2 matrices 1D, cada una de esas matrices 1D tiene 4 elementos.

Así que tienes tres dimensiones. Los ejes son 0, 1, 2, con tamaños 2, 2, 4. Así es exactamente cómo trata numéricamente los ejes de una matriz de N dimensiones.

Por lo tanto, arr.transpose((1, 0, 2)) tomaría el eje 1 y lo pondría en la posición 0, el eje 0 y lo pondría en la posición 1, y el eje 2 y lo dejaría en la posición 2. Usted está permutando efectivamente los ejes :

 0 -\/-> 0 1 -/\-> 1 2 ----> 2 

En otras palabras, 1 -> 0, 0 -> 1, 2 -> 2 . Los ejes de destino siempre están en orden, por lo que todo lo que necesita es especificar los ejes de origen. Lea la tupla en ese orden: (1, 0, 2) .

En este caso, las nuevas dimensiones de su matriz son nuevamente [2][2][4] , solo porque los ejes 0 y 1 tenían el mismo tamaño (2).

Más interesante es una transposición de (2, 1, 0) que te da una matriz de [4][2][2] .

 0 -\ /--> 0 1 --X---> 1 2 -/ \--> 2 

En otras palabras, 2 -> 0, 1 -> 1, 0 -> 2 . Lea la tupla en ese orden: (2, 1, 0) .

 >>> arr.transpose((2,1,0)) array([[[ 0, 8], [ 4, 12]], [[ 1, 9], [ 5, 13]], [[ 2, 10], [ 6, 14]], [[ 3, 11], [ 7, 15]]]) 

Terminaste con un int[4][2][2] .

Probablemente obtendrás una mejor comprensión si todas las dimensiones fueran de diferente tamaño, de modo que pudieras ver a dónde iba cada eje.

¿Por qué es el primer elemento interno [0, 8] ? Porque si visualiza su matriz 3D como dos hojas de papel, 0 y 8 están alineados, uno en un papel y otro en el otro, ambos en la parte superior izquierda. Al transponer (2, 1, 0) está diciendo que desea que la dirección de papel a papel marche ahora a lo largo del papel de izquierda a derecha, y la dirección de izquierda a derecha para ir ahora de papel a papel. Tenías 4 elementos que iban de izquierda a derecha, así que ahora tienes cuatro hojas de papel. Y tenías 2 papeles, así que ahora tienes 2 elementos que van de izquierda a derecha.

Lo siento por el terrible arte ASCII. ¯\_(ツ)_/¯

Para resumir a.transpose () [i, j, k] = a [k, j, i]

 a = np.array( range(24), int).reshape((2,3,4)) a.shape gives (2,3,4) a.transpose().shape gives (4,3,2) shape tuple is reversed. 

Cuando se pasa un parámetro de tupla, los ejes se permutan de acuerdo con la tupla. Por ejemplo

a = np.array (range (24), int) .reshape ((2,3,4))

a [i, j, k] es igual a a .transpose ((2,0,1)) [k, i, j]

el eje 0 toma el 2do lugar

el eje 1 toma el 3er lugar

eje 2 cuentos 1er lugar

Por supuesto, debemos tener cuidado de que los valores en el parámetro de tupla pasado a la transposición sean únicos y dentro del rango (número de ejes)