2013-06-07 13 views
6

Ho un array A che è della forma (M, N) ora vorrei eseguire l'operazioneMultipying e aggiungendo all'interno di una troppo grande array

R = (A[:,newaxis,:] * A[newaxis,:,:]).sum(2)

che dovrebbe produrre una (MxM) array. Ora il problema è che la matrice è abbastanza grande e ottengo un errore di memoria, perché l'array MxMxN non si adatta alla memoria.

quale sarebbe la migliore strategia per ottenere questo risultato? C? carta geografica()? o c'è ancora una funzione speciale per questo?

ringraziamento, David

+0

'A' è davvero un array MxN? Immagino che 'A [:, newaxis,:]' sia un array MxN. Anche allora, 'A [:, newaxis ,:] * A [newaxis,:,:]' dovrebbe produrre una matrice bidimensionale, quindi non capisco 'sum (2)', perché non esiste un terzo asse (o newaxis è una sezione, non un singolo numero). Manca qualcosa qui. – Evert

+0

In base alla precisione richiesta, è possibile tentare di utilizzare un tipo diverso per i valori all'interno dell'array. Ad esempio, 'numpy.float32' o' numpy.int16'. Questo potrebbe dimezzare i tuoi requisiti di memoria. – Evert

+0

@Evert A [:, np.newaxis,:]. Shape == (M, 1, N) e (A [:, np.newaxis ,:] * A [np.newaxis,:,:]). Forma == (M, M, N) – JoshAdel

risposta

7

Non sono sicuro di quanto grande si array vengono, ma il seguente è equivalente:

R = np.einsum('ij,kj',A,A) 

e può essere un po 'più veloce ed è molto meno intensivo di memoria:

In [7]: A = np.random.random(size=(500,400)) 

In [8]: %timeit R = (A[:,np.newaxis,:] * A[np.newaxis,:,:]).sum(2) 
1 loops, best of 3: 1.21 s per loop 

In [9]: %timeit R = np.einsum('ij,kj',A,A) 
10 loops, best of 3: 54 ms per loop 

Se io aumentare le dimensioni del A a (500,4000), np.einsum aratri attraverso il CALCOLO n in circa 2 secondi, mentre la formulazione originale macina la mia macchina fino a fermarsi a causa della dimensione della matrice temporanea che deve creare.

Aggiornamento:

Come @Jaime sottolineato nei commenti, np.dot(A,A.T) è anche una formulazione equivalente del problema, e può essere ancora più veloce rispetto alla soluzione np.einsum. Pieno merito per averlo sottolineato, ma nel caso non lo pubblicasse come soluzione formale, volevo farlo nella risposta principale.

+7

+1 Ma il calcolo dell'OP equivale anche a 'np.dot (A, AT)', e sul mio sistema, per una matrice '' (500, 400) ', è circa 10 volte più veloce di' np.einsum' , che è già 6 volte più veloce del metodo dell'OP. – Jaime

+0

@Jaime buona cattura. Pubblicalo come risposta e lo inviterò. fwow, 'np.dot' è solo circa il 2,5 più veloce di' np.einsum' sulla mia macchina per (500.400). Per (500,4000) anche se 'np.dot' è circa 10 volte più veloce. – JoshAdel

+0

Sono una puttana reputazione, non proprio così ... ;-) Sentiti libero di postare i tempi di 'np.dot' se vuoi, penso che sarà più pulito con una sola risposta. – Jaime