2014-08-29 25 views
6

Ho una matrice quadrata grande (circa 14.000 x 14.000) rappresentata come Numpy ndarray. Desidero estrarre un gran numero di righe e colonne - gli indici di cui so in anticipo, anche se saranno di fatto tutte le righe e le colonne che non sono tutte zero - per ottenere una nuova matrice quadrata (circa 10.000 x 10.000).Qual è il modo più veloce per estrarre determinate righe e colonne da un ndarray Numpy?

Il modo più veloce che ho trovato per fare questo è:

> timeit A[np.ix_(indices, indices)] 
1 loops, best of 3: 6.19 s per loop 

Tuttavia, questo è molto più lento rispetto al tempo necessario per fare la moltiplicazione di matrici:

> timeit np.multiply(A, A) 
1 loops, best of 3: 982 ms per loop 

Questo sembra strano, dal momento che sia l'estrazione riga/colonna che la moltiplicazione della matrice devono allocare un nuovo array (che sarà ancora più grande per il risultato della moltiplicazione della matrice rispetto all'estrazione), ma la moltiplicazione della matrice deve anche eseguire calcoli aggiuntivi.

Quindi, la domanda: c'è un modo più efficiente per eseguire l'estrazione, in particolare, che è almeno veloce come la moltiplicazione di matrice?

+0

Sospetto che il motivo per cui la moltiplicazione della matrice è veloce è perché utilizza tutti gli elementi dell'array in modo rigorosamente regolare ed è stato ottimizzato per farlo. Se devi passare in indici arbitrari (vale a dire, non una sezione rettangolare), non otterrai la velocità massima. – BrenBarn

+1

sì, usa numpy 1.9 – seberg

+3

'np.multiply (A, A)' è * elementwise * moltiplicazione. Usa 'np.dot (A, A)' per la moltiplicazione della matrice. –

risposta

1

Se provo a riprodurre il problema, non vedo un effetto così drastico. Ho notato che, a seconda del numero di indici che scegli, l'indicizzazione può anche essere più veloce della moltiplicazione.

>>> import numpy as np 
>>> np.__version__ 
Out[1]: '1.9.0' 
>>> N = 14000 
>>> A = np.random.random(size=[N, N]) 

>>> indices = np.sort(np.random.choice(np.arange(N), 0.9*N, replace=False)) 
>>> timeit A[np.ix_(indices, indices)] 
1 loops, best of 3: 1.02 s per loop 
>>> timeit A.take(indices, axis=0).take(indices, axis=1) 
1 loops, best of 3: 1.37 s per loop 
>>> timeit np.multiply(A,A) 
1 loops, best of 3: 748 ms per loop 

>>> indices = np.sort(np.random.choice(np.arange(N), 0.7*N, replace=False)) 
>>> timeit A[np.ix_(indices, indices)] 
1 loops, best of 3: 633 ms per loop 
>>> timeit A.take(indices, axis=0).take(indices, axis=1) 
1 loops, best of 3: 946 ms per loop 
>>> timeit np.multiply(A,A) 
1 loops, best of 3: 728 ms per loop 
Problemi correlati