2013-07-10 13 views
10

Considerare il seguente esercizio nella trasmissione di array Numpy.Numpy, python: espande automaticamente le dimensioni degli array durante la trasmissione

import numpy as np 
v = np.array([[1.0, 2.0]]).T # column array 

A2 = np.random.randn(2,10) # 2D array 
A3 = np.random.randn(2,10,10) # 3D 

v * A2 # works great 

# causes error: 
v * A3 # error 

Conosco le regole NumPy per la radiodiffusione, e ho familiarità con bsxfun funzionalità in Matlab. Capisco perché il tentativo di trasmettere un (2,1) array in un array (2, N, N) fallisce e che devo rimodellare l'array (2,1) in un array (2,1,1) prima di questo la trasmissione passa attraverso

La mia domanda è: c'è un modo per dire a Python di eseguire il rilievo automatico della dimensionalità di un array quando tenta di trasmettere, senza che io debba specificarlo specificatamente?

ho non voglio esplicitamente paio il (2,1) di vettore con l'array multidimensionale sta andando in onda contro --- altrimenti avrei potuto fare qualcosa di stupido e brutto come assurdamente mult_v_A = lambda v,A: v.reshape([v.size] + [1]*(A.ndim-1)) * A. Non so in anticipo se la matrice "A" sarà 2D o 3D o N-D.

La funzionalità di trasmissione di Matlab bsxfun include implicitamente le dimensioni necessarie, quindi spero che ci sia qualcosa che potrei fare in Python.

+4

La mia opinione è che questa è una funzionalità e non un bug. Ad esempio, supponiamo di avere un vettore di colonna 2 per 1 'v' e quindi di avere un' ndarray' 2 per 2 per 10. Vuoi rimodellare 'v' per avere forma' (2,1,1) 'o forma' (1,2,1) '? Se si riempiono le dimensioni, potrebbe essere ambiguo per l'utente. Forzare una risagoma esplicita è una procedura generale migliore e lasciare all'utente la possibilità di scrivere una funzione speciale per eseguire automaticamente la riformulazione se l'utente ha una convenzione fissa. Ma non è bello creare una dimensione globale "numpy" che costringa una convention su di te. Sarebbe troppo facile abusare. – ely

+0

-1 @EMS. Questa ambiguità è prontamente risolta specificando che la prima dimensione non singleton verrà utilizzata nella trasmissione. Questo atteggiamento di "In questo modo è meglio" è del tutto inappropriato per i sistemi utilizzati da programmatori professionisti e matematici applicati --- questo è un difetto in termini di illegittimità e conformità, non una caratteristica. –

+0

-1 @Ahmmed Fasih. Sono un matematico applicato che scrive il codice Python per applicazioni scientifiche ogni giorno, e sento che la tua convenzione proposta di adottare sempre la prima dimensione non singleton sarebbe molto scarsa. Molto meglio per te scrivere una funzione che adotta questa convenzione piuttosto che per gli sviluppatori di NumPy preoccuparsi di codificare una convenzione come quella che avvantaggia alcuni utenti (come te), ma non sarebbe utile per altri utenti (come me). – ely

risposta

9

E 'brutto, ma questo funzionerà :

(v.T * A3.T).T 

Se non si dà alcun argomento, recepisce inverte la tupla forma, in modo da poter ora avvalersi delle norme di trasmissione di fare la loro magia. L'ultima trasposizione restituisce tutto nell'ordine corretto.

+1

In realtà è meno brutto di quello che ho avuto dopo aver studiato la risposta di @ unutbu, che era 'np.swapaxes (v.T * np.swapaxes (A3,0, -1), 0, -1)'! Sapere che la trasposizione inverte tutte le dimensioni rende questo molto più ordinato. Almeno gli utenti vedranno queste trasposizioni e si spera che pensino "Ok, c'è una trasmissione in corso qui, con solo un piccolo tocco di funk per rendere le dimensioni allineate, ok, sto bene". Grazie capo. –

8

La trasmissione NumPy aggiunge ulteriori assi a sinistra.

Quindi, se ad organizzare gli array in modo che le assi comuni sono a destra e gli assi broadcastable sono a sinistra, quindi è possibile utilizzare la trasmissione senza alcun problema:

import numpy as np 
v = np.array([[1.0, 2.0]]) # shape (1, 2) 

A2 = np.random.randn(10,2) # shape (10, 2) 
A3 = np.random.randn(10,10,2) # shape (10, 10, 2) 

v * A2 # shape (10, 2) 

v * A3 # shape (10, 10, 2) 
+0

Questa almeno è una soluzione a metà strada. Sfortunatamente la convenzione stabilita nella mia applicazione è che vettori come 'v' sono array di colonne. Supponendo che non volessi riorganizzare il codice (e i miei utenti) per prevedere array di righe, sto discutendo se una funzione che scambia le dimensioni per fare una trasmissione moltiplicata è davvero meno completa di un'operazione di risagoma che intreccia 'A' e' v' nel mio post originale. –

+0

C'è qualche motivo per cui Numpy aggiunge le dimensioni a sinistra, ma non a destra? Sembra arbitrario, ma forse c'è qualche razionale importante legato alla memoria o all'algebra? –

+0

Forse rispondere alla mia (sotto) domanda, è perché la trasmissione inizia dalle dimensioni finali degli array e funziona verso sinistra, e continua ad aggiungere le dimensioni secondo necessità, purché le regole siano rispettate? Interessante! –

Problemi correlati