2013-07-02 14 views
6

Szukam szybkiego sposobu obliczania sumy n produktów zewnętrznych.Python - szybki sposób na zsumowanie produktów zewnętrznych?

Zasadniczo zacznę macierzach uzyskanych z rozkładu normalnego - jest n wektorów z przeciwko elementów:

A = np.random.normal(size = (n, v)) 
B = np.random.normal(size = (n, v)) 

Co I jak jest obliczenie zewnętrzne produkty każdego wektora wielkości vw i B i podsumować je razem.

Uwaga: A * B.T nie działa - A ma rozmiar n x v, a B ma rozmiar v x n.

Najlepsze, co mogę zrobić, to stworzyć pętlę, w której konstruowane są produkty zewnętrzne, a następnie podsumowywane później. I mieć tak:

outers = np.array([A[i] * B[i].T]) 

Stwarza n X V X V tablicy (pętla jest na liście pojmowania, który jest następnie przekształcany w tablicy), które następnie można podsumować razem za pomocą np.sum(outers, axis = 0). Jest to jednak dość powolne i zastanawiałem się, czy istnieje wektoryzowana funkcja, której mogę użyć, aby przyspieszyć ten proces.

Jeśli ktokolwiek ma jakieś rady, byłbym bardzo wdzięczny!

Odpowiedz

7

Wydaje mi się, że wszystko, co musisz zrobić, to zmienić kolejność transpozycji i wykonać A.T * B zamiast A * B.T.

Jeśli nie jest to dokładnie to, czego szukasz, spójrz na np.einsum, który może zrobić bardzo potężny voodoo. W powyższym przykładzie:

np.einsum('ij,ik->jk', A, B) 
+0

einsum działa pięknie. Dzięki! – Adam

2

Weź również pod uwagę np.outer.

np.array([np.outer(A, B) for i in xrange(n)]).sum(0) 

Chociaż np.einsum zasugerowany przez @Jamie jest oczywistym zwycięzcą.

In [63]: %timeit np.einsum('ij,ik->jk', A, B) 
100000 loops, best of 3: 4.61 us per loop 

In [64]: %timeit np.array([np.outer(A[i], B[i]) for i in xrange(n)]).sum(0) 
10000 loops, best of 3: 169 us per loop 

i, aby mieć pewność, ich wyniki są identyczne:

In [65]: np.testing.assert_allclose(method_outer, method_einsum) 

Ale, jak na bok, nie uważam, że A.T * B lub A * B.T transmisję pomyślnie.

+0

Powtarza obiekty 'np.matrix', a nie' np.ndarray's. 'A * B.T' jest wtedy równoznaczne z' np.dot (A, B.T) 'i' A.T * B' na 'np.dot (A.T, B)'. Powinien działać bardzo, bardzo blisko 'np.einsum'. – Jaime

+0

+1 za dobre porównanie obu metod – elaRosca

Powiązane problemy