python - numpy concatenate



In che modo il metodo transpose() di NumPy permuta gli assi di un array? (3)

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

Quando passiamo una tupla di interi alla funzione transpose() , cosa succede?

Per essere precisi, questo è un array 3D: in che modo NumPy trasforma l'array quando passo la tupla degli assi (1, 0 ,2) ? Puoi spiegare a quale riga o colonna si riferiscono questi interi? E quali sono i numeri degli assi nel contesto di NumPy?

https://ffff65535.com


Come spiegato docs.scipy.org/doc/numpy/reference/generated/… :

Per impostazione predefinita, invertire le dimensioni, altrimenti permuta gli assi in base ai valori indicati.

Quindi puoi passare axes parametri opzionali che definiscono il nuovo ordine di dimensioni.

Ad esempio, trasporre le prime due dimensioni di un array di pixel RGB VGA:

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

Nella notazione C, il tuo array sarebbe:

int arr[2][2][4]

che è un array 3D con 2 array 2D. Ciascuno di questi array 2D ha 2 array 1D, ciascuno di questi array 1D ha 4 elementi.

Quindi hai tre dimensioni. Gli assi sono 0, 1, 2, con le taglie 2, 2, 4. Questo è esattamente il modo in cui numpy tratta gli assi di una matrice N-dimensionale.

Quindi, arr.transpose((1, 0, 2)) prenderebbe l'asse 1 e lo mise in posizione 0, asse 0 e lo mise in posizione 1, e l'asse 2 e lo lascerebbe in posizione 2. Stai effettivamente permutando gli assi :

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

In altre parole, 1 -> 0, 0 -> 1, 2 -> 2 . Gli assi di destinazione sono sempre in ordine, quindi tutto ciò che serve è specificare gli assi sorgente. Leggi la tupla in questo ordine: (1, 0, 2) .

In questo caso, le nuove dimensioni della matrice sono nuovamente [2][2][4] , solo perché gli assi 0 e 1 avevano la stessa dimensione (2).

Più interessante è una trasposizione di (2, 1, 0) che ti dà una matrice di [4][2][2] .

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

In altre parole, 2 -> 0, 1 -> 1, 0 -> 2 . Leggere la tupla in questo ordine: (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]]])

Hai finito con un int[4][2][2] .

Probabilmente capirai meglio se tutte le dimensioni fossero di dimensioni diverse, quindi potresti vedere dove è andato ogni asse.

Perché è il primo elemento interno [0, 8] ? Perché se visualizzi il tuo array 3D come due fogli di carta, 0 e 8 sono allineati, uno su un foglio e uno sull'altro foglio, entrambi in alto a sinistra. Trasponendo (2, 1, 0) stai dicendo che vuoi che la direzione della carta su carta ora marcia lungo la carta da sinistra a destra, e che la direzione da sinistra a destra passi ora da carta a carta. Avevi 4 elementi da sinistra a destra, quindi ora hai quattro pezzi di carta. E avevi 2 documenti, quindi ora hai 2 elementi che vanno da sinistra a destra.

Scusa per la terribile arte ASCII. ¯\_(ツ)_/¯


Per trasporre un array, NumPy scambia solo le informazioni di forma e passo per ciascun asse. Ecco i passi:

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

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

Si noti che l'operazione di trasposizione ha invertito le falcate per l'asse 0 e l'asse 1. Anche le lunghezze di questi assi sono state scambiate (entrambe le lunghezze sono 2 in questo esempio).

Nessun dato deve essere copiato affinché ciò accada; NumPy può semplicemente cambiare il modo in cui guarda la memoria sottostante per costruire il nuovo array.

Visualizzare passi da gigante

Il valore di passo rappresenta il numero di byte che devono essere percorsi in memoria per raggiungere il valore successivo di un asse di un array.

Ora, il nostro arr array 3D sembra questo (con assi etichettati):

Questo array è memorizzato in un blocco contiguo di memoria ; essenzialmente è unidimensionale. Per interpretarlo come un oggetto 3D, NumPy deve saltare sopra un certo numero costante di byte per spostarsi lungo uno dei tre assi:

Dal momento che ogni intero occupa 8 byte di memoria (stiamo usando il tipo di int64 dtype), il valore di passo per ogni dimensione è 8 volte il numero di valori che dobbiamo saltare. Ad esempio, per spostarsi lungo l'asse 1, vengono saltati quattro valori (32 byte) e per spostarsi lungo l'asse 0, devono essere saltati otto valori (64 byte).

Quando scriviamo arr.transpose(1, 0, 2) stiamo scambiando gli assi 0 e 1. L'array trasposto assomiglia a questo:

Tutto ciò che NumPy deve fare è scambiare le informazioni sul passo per l'asse 0 e l'asse 1 (l'asse 2 è invariato). Ora dobbiamo saltare ulteriormente per spostarci lungo l'asse 1 rispetto all'asse 0:

Questo concetto di base funziona per qualsiasi permutazione degli assi di un array. Il codice effettivo che gestisce la trasposizione è scritto in C e può essere trovato here .





transpose