Niedawno przeniosłem się do Pythona 3.5 i zauważyłem, że nowy operator mnożenia macierzy (@) czasami zachowuje się inaczej niż operator kropki numpy . Na przykład dla tablic 3D:
import numpy as np
a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b # Python 3.5+
d = np.dot(a, b)
@
Operator zwraca tablicę kształcie:
c.shape
(8, 13, 13)
podczas gdy np.dot()
funkcja zwraca:
d.shape
(8, 13, 8, 13)
Jak mogę odtworzyć ten sam wynik za pomocą numpy dot? Czy są jakieś inne istotne różnice?
matmul
funkcji lata temu?@
jako operator wrostek jest nowy, ale funkcja działa równie dobrze bez niego.Odpowiedzi:
@
Operator wywoływany jest konstruktor Array jest__matmul__
metoda, niedot
. Ta metoda jest również obecna w API jako funkcjanp.matmul
.Z dokumentacji:
Ostatni punkt wyjaśnia, że metody
dot
imatmul
metody zachowują się inaczej, gdy przekazywane są tablice 3D (lub wyższego wymiaru). Cytując trochę z dokumentacji:Dla
matmul
:Dla
np.dot
:źródło
Odpowiedź @ajcr wyjaśnia, czym różnią się znaki
dot
imatmul
(wywoływane przez@
symbol). Patrząc na prosty przykład, wyraźnie widać, jak zachowują się one inaczej, gdy operujemy na „stosach matricies” lub tensorach.Aby wyjaśnić różnice, weź tablicę 4x4 i zwróć
dot
produkt imatmul
produkt ze stosem matryc lub tensorem 3x4x2.Produkty każdej operacji przedstawiono poniżej. Zwróć uwagę na iloczyn skalarny,
i jak jest tworzony iloczyn matrycy przez wspólne nadawanie matrycy.
źródło
a = np.arange(24).reshape(3, 4, 2)
byłoby utworzenie tablicy o wymiarach 3x4x2.Po prostu do Twojej wiadomości,
@
i jego ponętnych odpowiednikówdot
imatmul
wszystkie są mniej więcej równie szybkie. (Działka stworzona za pomocą perfplot , mojego projektu).Kod do odtworzenia fabuły:
źródło
W matematyce myślę, że kropka w numpy ma większy sens
ponieważ daje iloczyn skalarny, gdy a i b są wektorami, lub mnożenie macierzy, gdy a i b są macierzami
Jeśli chodzi o operację matmul w numpy, składa się z części wyniku kropkowego i można go zdefiniować jako
> matmul (a, b) _ {i, j, k, c} =
Widzisz więc, że matmul (a, b) zwraca tablicę o małym kształcie, która ma mniejsze zużycie pamięci i ma większy sens w aplikacjach. W szczególności, łącząc się z nadawaniem , możesz uzyskać
na przykład.
Z powyższych dwóch definicji można zobaczyć wymagania dotyczące korzystania z tych dwóch operacji. Załóżmy, że a.shape = (s1, s2, s3, s4) i b.shape = (t1, t2, t3, t4)
Aby użyć kropki (a, b) , potrzebujesz
Aby użyć matmul (a, b) potrzebujesz
Użyj poniższego fragmentu kodu, aby się przekonać.
Przykład kodu
źródło
np.matmul
daje również iloczyn skalarny na wektorach i iloczyn macierzy na macierzach.Oto porównanie z,
np.einsum
aby pokazać, jak prognozowane są wskaźnikiźródło
Moje doświadczenie z MATMUL i DOT
Ciągle otrzymywałem komunikat „ValueError: Kształt przekazywanych wartości to (200, 1), indeksy implikują (200, 3)” podczas próby użycia MATMUL. Chciałem szybkiego obejścia problemu i stwierdziłem, że DOT zapewnia tę samą funkcjonalność. Nie otrzymuję żadnego błędu podczas używania DOT. Mam poprawną odpowiedź
z MATMUL
z DOT
źródło