2012-08-07 17 views
22

Załóżmy, że masz n macierzy kwadratowych A1, ..., An. Czy mimo to można pomnożyć te macierze w sposób schludny? O ile wiem, kropka w numpy akceptuje tylko dwa argumenty. Jednym z oczywistych sposobów jest zdefiniowanie funkcji wywoływania samej siebie i uzyskania wyniku. Czy istnieje lepszy sposób na zrobienie tego?Pomnóż kilka macierzy w numpy

Odpowiedz

38

To może być stosunkowo nowym elementem, ale lubię:

A.dot(B).dot(C) 

lub jeśli miał długi łańcuch można zrobić:

reduce(numpy.dot, [A1, A2, ..., An]) 

Aktualizacja:

Jest więcej informacje o zmniejszeniu here. Oto przykład, który może pomóc.

>>> A = [np.random.random((5, 5)) for i in xrange(4)] 
>>> product1 = A[0].dot(A[1]).dot(A[2]).dot(A[3]) 
>>> product2 = reduce(numpy.dot, A) 
>>> numpy.all(product1 == product2) 
True 

Aktualizacja 2016: Jak Pythona 3.5, jest nowy matrix_multiply symbol, @:

R = A @ B @ C 
+0

Dzięki za odpowiedź. Pierwsza opcja działa dobrze; ale drugi nie robi; lub przynajmniej nie mogłem sprawić, żeby to działało. Czy mógłbyś rozwinąć to nieco więcej lub może podać przykład? Wielkie dzięki – NNsr

+4

Natknąłem się na to cały czas i zakończyłem pisanie funkcji pomocnika. Żałuję, że to część NumPy: 'def xdot (* args): return reduce (np.dot, args)' – rd11

+0

Po prostu dodając komentarz, który działa, gdy A, B i C są typu numpy.ndarray. To może działać dla innych typów, ale nie sprawdziłem. – OfLettersAndNumbers

3

Jeśli wszystkie macierze są obliczane a priori, należy użyć schematu optymalizacji dla mnożenia łańcuchów macierzy. Zobacz this Wikipedia article.

+2

Dzięki za komentarz; ale nie sądzę, że dla macierzy kwadratowych ma to znaczenie. Dobrze? – NNsr

+0

@Nikandish: Prawidłowo. Opuściłem tę część w pierwotnej odpowiedzi. –

2
A_list = [np.random.randn(100, 100) for i in xrange(10)] 
B = np.eye(A_list[0].shape[0]) 
for A in A_list: 
    B = np.dot(B, A) 

C = reduce(np.dot, A_list) 

assert(B == C) 
16

Resurrecting starą pytanie z aktualizacją:

Od November 13, 2014 jest teraz funkcja np.linalg.multi_dot, która robi dokładnie to, co chcesz. Ma także tę zaletę, że optymalizuje kolejność połączeń, ale nie jest to konieczne w twoim przypadku.

Należy zauważyć, że jest to dostępne począwszy od numpy w wersji 1.10.

0

Innym sposobem na osiągnięcie tego byłoby użycie einsum, która implementuje Einstein summation convention dla NumPy.

bardzo krótko wyjaśnić tę konwencję w odniesieniu do tego problemu: Kiedy piszesz swój wielokrotnego produkt matrycowy jako jednej wielkiej sumy produktów, masz coś takiego:

P_im = sum_j sum_k sum_l A1_ij A2_jk A3_kl A4_lm 

gdzie P jest wynikiem swoje produkt i A1, A2, A3 i A4 są matrycą wejściową. Zwróć uwagę, że sumujesz dokładnie te indeksy, które pojawiają się dwa razy w podsumowaniu, a mianowicie j, k i l. Jako sumę z tą właściwością często pojawia się w fizyce, rachunku wektorowym i prawdopodobnie w innych polach istnieje narzędzie NumPy, a mianowicie einsum.

W powyższym przykładzie, można go użyć do obliczenia produkt matrycowy następująco:

P = np.einsum("ij,jk,kl,lm", A1, A2, A3, A4) 

Tutaj pierwszy argument mówi funkcję którego wskaźniki stosowane do matryc argument i wszystkie współczynniki podwójnie pojawiające są sumowane, dając pożądany wynik.

Należy pamiętać, że wydajność obliczeniowa zależy od kilku czynników (więc są prawdopodobnie najlepiej wyłączyć z testowania go tylko):

Powiązane problemy