2013-07-03 3 views
7

Nehmen wir an, wir haben zwei Matrizen A und B und lassen die Matrix CA*B sein (Matrixmultiplikation nicht elementweise). Wir möchten nur die diagonalen Einträge von C, die über np.diagonal(C) erfolgen kann. Dies verursacht jedoch unnötigen Zeitaufwand, da wir A mit B multiplizieren, obwohl wir nur die Multiplikationen jeder Zeile in A mit der Spalte B benötigen, die dieselbe "ID" hat, also Zeile 1 von A mit Spalte 1 von B, Reihe 2 von A mit Spalte 2 von B und so weiter: die Multiplikationen, die die Diagonale C bilden. Gibt es eine Möglichkeit, das mit Numpy effizient zu erreichen? Ich möchte vermeiden, mit Schleifen zu steuern, welche Zeile mit welcher Spalte multipliziert wird, stattdessen wünsche ich eine integrierte numpy-Methode, die diese Art von Vorgang zur Optimierung der Leistung ausführt.(Python) Wie bekomme ich die Diagonale (A * B), ohne A * B ausführen zu müssen?

Vielen Dank im Voraus ..

+0

Nur eine Anmerkung für jeden, der dies betrachtet: 'A * B 'in NumPy ist elementweise Multiplikation, nicht Matrixmultiplikation (die' a.dot (b)' ist). – Blair

+0

sind 'A' und' B' vom Typ 'ndarray' oder' matrix'? – Bitwise

+0

@Blair, das ist der Fall, wenn 'A' und' B' 'numpy.array' sind. Wenn sie 'numpy.matrix' sind, können Sie' A * B' –

Antwort

15

Ich könnte einsum hier verwenden:

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

Für größere Arrays, wird es viel schneller, als direkt die Vermehrung zu tun:

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

[Anmerkung: Ursprünglich hatte ich das getan element Version, ii,ii->i, anstelle der Matrixmultiplikation. Die gleichen einsum Tricks funktionieren.]

+1

Tolle Lösung und nützlicher Benchmark! Vielen Dank! – Curious

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

Ich glaube, der obige Code ist, dass Sie suchen.

+4

So funktioniert [Matrix-Multiplikation] (http://en.wikipedia.org/wiki/Matrix_multiplication#Matrix_product_.28zwei_matrizen.29) nicht –

+0

Es tut uns leid. Ich wusste nicht, ob du Skalarprodukt oder Matrixprodukt meinst. – BenjaminCohen

Verwandte Themen