2013-07-03 8 views
7

Diciamo che abbiamo due matrici A e B e che la matrice A*B è la(moltiplicazione della matrice non element-wise). Desideriamo ricevere solo le voci diagonali di C, che possono essere eseguite tramite np.diagonal(C). Tuttavia, ciò causa un inutile sovraccarico di tempo, perché stiamo moltiplicando A con B anche se abbiamo solo bisogno delle moltiplicazioni di ogni riga in A con la colonna di B che ha lo stesso 'id', ovvero la riga 1 di A con colonna 1 di B, riga 2 di A con la colonna 2 di B e così via: le moltiplicazioni che formano la diagonale di C. C'è un modo per raggiungerlo in modo efficiente usando Numpy? Voglio evitare di usare i loop per controllare quale riga è moltiplicata con quale colonna, invece, vorrei un metodo di numpy incorporato che faccia questo tipo di operazione per ottimizzare le prestazioni.(Python) Come ottenere diagonale (A * B) senza dover eseguire A * B?

Grazie in anticipo ..

+0

Solo una nota per chi guarda questo: 'A * B' in NumPy è una moltiplicazione di elementi, non una moltiplicazione di matrice (che è' a.dot (b) '). – Blair

+0

sono 'A' e' B' di tipo 'ndarray' o' matrix'? – Bitwise

+0

@Blair, questo è il caso se 'A' e' B' sono 'numpy.array'. Se sono 'numpy.matrix', puoi usare' A * B' –

risposta

15

potrei usare einsum qui:

>>> a = np.random.randint(0, 10, (3,3)) 
>>> b = np.random.randint(0, 10, (3,3)) 
>>> a 
array([[9, 2, 8], 
     [5, 4, 0], 
     [8, 0, 6]]) 
>>> b 
array([[5, 5, 0], 
     [3, 5, 5], 
     [9, 4, 3]]) 
>>> a.dot(b) 
array([[123, 87, 34], 
     [ 37, 45, 20], 
     [ 94, 64, 18]]) 
>>> np.diagonal(a.dot(b)) 
array([123, 45, 18]) 
>>> np.einsum('ij,ji->i', a,b) 
array([123, 45, 18]) 

Per gli array più grandi, sarà molto più veloce di fare la moltiplicazione direttamente:

>>> a = np.random.randint(0, 10, (1000,1000)) 
>>> b = np.random.randint(0, 10, (1000,1000)) 
>>> %timeit np.diagonal(a.dot(b)) 
1 loops, best of 3: 7.04 s per loop 
>>> %timeit np.einsum('ij,ji->i', a, b) 
100 loops, best of 3: 7.49 ms per loop 

[Nota: inizialmente avevo fatto l'elementwise versione, ii,ii->i, anziché la moltiplicazione della matrice. Gli stessi trucchi dello einsum funzionano.]

+1

Ottima soluzione e utile benchmark! Grazie! – Curious

-1
def diag(A,B): 
    diags = [] 
    for x in range(len(A)): 
     diags.append(A[x][x] * B[x][x]) 
    return diags 

credo che il codice di cui sopra è che si sta cercando.

+4

Non è così che [moltiplicazione di matrici] (http://en.wikipedia.org/wiki/Matrix_multiplication#Matrix_product_.28two_matrices.29) funziona –

+0

Scusate. Non sapevo se intendevi prodotto scalare o prodotto matrice. – BenjaminCohen

Problemi correlati