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

81
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 transpose()función, ¿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)? ¿Puede explicar a qué fila o columna se refieren estos números enteros? ¿Y qué son los números de eje en el contexto de NumPy?

Frank Hu
fuente
2
0es el primer eje, 1es el segundo, 2es el tercero, etc ... El axesparámetro transposeproporciona el nuevo orden en el que desea que se coloquen, en su ejemplo: primero el segundo, luego el primero, luego el tercero.
Jaime
En la pantalla 3D hay bloques, filas y columnas. Su transposición ha cambiado el orden de los bloques y filas, dejando las columnas sin cambios. Lo que solía ser la segunda fila del primer bloque se convierte en la primera fila del segundo bloque.
hpaulj

Respuestas:

185

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

>>> arr.strides
(64, 32, 8)

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

Observe que la operación de transposición intercambió los pasos del eje 0 y el eje 1. Las longitudes de estos ejes también se intercambiaron (ambas longitudes están 2en este ejemplo).

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


Visualización de pasos

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

Ahora, nuestra matriz 3D se arrve así (con ejes etiquetados):

ingrese 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 sobre un cierto número constante de bytes para moverse a lo largo de uno de los tres ejes:

ingrese la descripción de la imagen aquí

Dado que cada entero ocupa 8 bytes de memoria (estamos usando el dtype int64), el valor de paso para cada dimensión es 8 veces el número de valores que necesitamos para 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, es necesario saltar ocho valores (64 bytes).

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

ingrese la descripción de la imagen aquí

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

ingrese 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í .

Alex Riley
fuente
6
@Alex: ¡gracias! Las cifras se hicieron usando draw.io .
Alex Riley
6

Como se explica en la documentación :

Por defecto, invierte las dimensiones, de lo contrario permuta los ejes de acuerdo con los valores dados.

De modo que puede pasar un parámetro opcional que axesdefine el nuevo orden de dimensiones.

Por ejemplo, transponer las dos primeras dimensiones de una matriz de píxeles RGB VGA:

 >>> x = np.ones((480, 640, 3))
 >>> np.transpose(x, (1, 0, 2)).shape
 (640, 480, 3)
Falko
fuente
1
Hola, gracias por tu respuesta. Sin embargo, todavía no puedo entender este problema, como puede ver, la forma de arr es (2,2,4) y arr.transpose (1,0,2) es (2,2,4) también. esta es una matriz 3-d, cómo transformar la matriz cuando paso (1,0,2), ¿puede explicar a qué fila o columna se refiere el 1,0,2? ¿Y qué son los números de eje en términos de numpy?
Frank Hu
1
@FrankHu visualiza en el espacio 3d, por lo que la rotación del eje x, y es lo que sucedió aquí. (1,0,2) se transpuso de (0,1,2), por lo que los primeros 2 ejes se cambian. 0 es el número de índice del eje. Digamos, x, y, z se asigna a 0,1,2
CodeFarmer
5

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.

Entonces tienes tres dimensiones. Los ejes son 0, 1, 2, con tamaños 2, 2, 4. Así es exactamente como numpy trata los ejes de una matriz N-dimensional.

Por arr.transpose((1, 0, 2))lo tanto, tomaría el eje 1 y lo colocaría en la posición 0, el eje 0 y lo colocaría en la posición 1, y el eje 2 y lo dejaría en la posición 2. 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. Leer el valor de 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 (2, 1, 0)que le da una variedad de [4][2][2].

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

En otras palabras, 2 -> 0, 1 -> 1, 0 -> 2. Leer el valor de 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á una mejor comprensión si todas las dimensiones fueran de diferente tamaño, de modo que pueda ver dónde fue cada eje.

¿Por qué es el primer elemento interior [0, 8]? Porque si visualizas tu matriz 3D como dos hojas de papel, 0y 8están alineadas, una en un papel y otra en el otro, ambas en la parte superior izquierda. Al transponer (2, 1, 0), está diciendo que quiere 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 ahora ir 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.

Perdón por el terrible arte ASCII. ¯\_(ツ)_/¯

Robert B
fuente
¿Estoy en lo cierto al pensar que la tupla a la que le das transpose()no es una permutación matemática ni nada? ¿Son literalmente instrucciones que dicen "hacer que los ejes estén ahora en estas posiciones"? Por ejemplo, .transpose(p, q, r, s)¿estás diciendo "poner eje pcomo 0, qcomo 1er, rcomo 2do y scomo 3er"? O visto de otra manera b = a.transpose(axes)significa b.shape == tuple(a.shape[i] for i in axes)?
Tim
La idea de intercambiar ejes con arte ASCII aclara mi comprensión. Muchas gracias
K_inverse
0

Parece que la pregunta y el ejemplo se originan en el libro Python for Data Analysis de Wes McKinney. Esta característica de transposese menciona en el Capítulo 4.1. Transposición de matrices e intercambio de ejes .

Para matrices de mayor dimensión, transposeaceptará una tupla de números de eje para permutar los ejes (para una mayor flexibilidad).

Aquí "permutar" significa "reorganizar", por lo que reorganizar el orden de los ejes.

Los números en .transpose(1, 0, 2)determinan cómo se cambia el orden de los ejes en comparación con el original. Al usar .transpose(1, 0, 2), queremos decir, "Cambiar el primer eje por el segundo". Si usamos .transpose(0, 1, 2), la matriz permanecerá igual porque no hay nada que cambiar; es el orden predeterminado.

El ejemplo en el libro con una (2, 2, 4)matriz de tamaño no es muy claro ya que el primer y el segundo eje tienen el mismo tamaño. Entonces, el resultado final no parece cambiar, excepto el reordenamiento de las filas arr[0, 1]y arr[1, 0].

Si probamos un ejemplo diferente con una matriz tridimensional y cada dimensión tiene un tamaño diferente, la parte de reordenamiento se vuelve más clara.

In [2]: x = np.arange(24).reshape(2, 3, 4)

In [3]: x
Out[3]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

In [4]: x.transpose(1, 0, 2)
Out[4]: 
array([[[ 0,  1,  2,  3],
        [12, 13, 14, 15]],

       [[ 4,  5,  6,  7],
        [16, 17, 18, 19]],

       [[ 8,  9, 10, 11],
        [20, 21, 22, 23]]])

Aquí, los tamaños de matriz originales son (2, 3, 4). Cambiamos el 1º y 2º, por lo que se vuelve (3, 2, 4)de tamaño. Si miramos más de cerca para ver cómo ocurrió exactamente el reordenamiento; las matrices de números parecen haber cambiado en un patrón particular. Usando la analogía del papel de @ RobertB , si tuviéramos que tomar los 2 trozos de números y escribir cada uno en hojas, luego tomar una fila de cada hoja para construir una dimensión de la matriz, ahora tendríamos una matriz de tamaño 3x2x4 , contando desde la capa más externa hasta la más interna.

[ 0,  1,  2,  3] \ [12, 13, 14, 15]

[ 4,  5,  6,  7] \ [16, 17, 18, 19]

[ 8,  9, 10, 11] \ [20, 21, 22, 23]

Podría ser una buena idea jugar con matrices de diferentes tamaños y cambiar diferentes ejes para tener una mejor intuición de cómo funciona.

Ayşe Nur
fuente
-3

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 (rango (24), int) .reshape ((2,3,4))

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

el eje 0 ocupa el segundo lugar

el eje 1 ocupa el tercer lugar

eje 2 cuentos 1er lugar

por supuesto, debemos tener cuidado de que los valores en el parámetro de tupla pasados ​​a transponer sean únicos y estén en el rango (número de ejes)

Ram Raghu
fuente
No ha abordado la pregunta del OP, que es lo que sucede cuando transpone con ejes especificados .
Robert B
respuesta agregada a la pregunta cuando se especifican ejes.
Raghu Ram