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?
0
es el primer eje,1
es el segundo,2
es el tercero, etc ... Elaxes
parámetrotranspose
proporciona el nuevo orden en el que desea que se coloquen, en su ejemplo: primero el segundo, luego el primero, luego el tercero.Respuestas:
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
2
en 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
arr
ve así (con ejes etiquetados):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:
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í: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:
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í .
fuente
Como se explica en la documentación :
De modo que puede pasar un parámetro opcional que
axes
define 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)
fuente
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,0
y8
está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.
¯\_(ツ)_/¯
fuente
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 ejep
como 0,q
como 1er,r
como 2do ys
como 3er"? O visto de otra manerab = a.transpose(axes)
significab.shape == tuple(a.shape[i] for i in axes)
?Parece que la pregunta y el ejemplo se originan en el libro Python for Data Analysis de Wes McKinney. Esta característica de
transpose
se menciona en el Capítulo 4.1. Transposición de matrices e intercambio de ejes .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 filasarr[0, 1]
yarr[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.
fuente
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)
fuente