Matrizenmultiplikation in Python: Eine umfassende Anleitung
In dieser Anleitung werden Sie die verschiedenen Methoden zur Multiplikation von Matrizen in Python kennenlernen. Zunächst werden wir die notwendigen Bedingungen für eine gültige Matrizenmultiplikation definieren und anschließend eine individuelle Python-Funktion erstellen, die Matrizen multipliziert. Danach werden wir die gleiche Operation mithilfe von verschachtelten Listenkomprehensionen ausführen.
Abschließend werden wir untersuchen, wie die in NumPy integrierten Funktionen verwendet werden können, um die Matrizenmultiplikation effizienter durchzuführen.
Gültigkeit der Matrizenmultiplikation überprüfen
Bevor wir uns dem Python-Code zuwenden, wollen wir die grundlegenden Regeln für die Matrizenmultiplikation wiederholen.
Eine Matrizenmultiplikation zwischen zwei Matrizen, A und B, ist nur dann zulässig, wenn die Anzahl der Spalten in Matrix A mit der Anzahl der Zeilen in Matrix B übereinstimmt.
Diese Regel ist wahrscheinlich bekannt, aber haben Sie sich jemals gefragt, warum dies notwendig ist?
Der Grund dafür liegt in der Art und Weise, wie die Matrizenmultiplikation funktioniert. Betrachten Sie das folgende Diagramm:
In diesem allgemeinen Beispiel hat Matrix A m Zeilen und n Spalten, während Matrix B n Zeilen und p Spalten hat.
Die Dimensionen der Produktmatrix
Das Element an der Position (i, j) in der resultierenden Matrix C wird als Skalarprodukt der Zeile i von Matrix A und der Spalte j von Matrix B berechnet.
Um ein bestimmtes Element in der Produktmatrix C zu erhalten, berechnen wir das Skalarprodukt der entsprechenden Zeile und Spalte der Matrizen A bzw. B.
Durch Wiederholung dieses Prozesses erhalten wir die Produktmatrix C mit den Dimensionen m x p, d. h. m Zeilen und p Spalten, wie unten dargestellt.
Das Skalarprodukt (oder Punktprodukt) zweier Vektoren a und b wird durch die folgende Gleichung definiert.
Zusammenfassend:
- Das Skalarprodukt ist nur für Vektoren gleicher Länge definiert.
- Um ein Skalarprodukt zwischen einer Zeile und einer Spalte zu berechnen, müssen beide die gleiche Anzahl an Elementen haben.
- Im Beispiel oben hat jede Zeile in Matrix A n Elemente, und jede Spalte in Matrix B hat ebenfalls n Elemente.
Daher ist n die Anzahl der Spalten in Matrix A und gleichzeitig die Anzahl der Zeilen in Matrix B. Dies ist der Grund, warum die Anzahl der Spalten von A gleich der Anzahl der Zeilen von B sein muss.
Ich hoffe, dies verdeutlicht, warum die Bedingung für die Matrizenmultiplikation gültig sein muss und wie jedes Element der Produktmatrix berechnet wird.
Lassen Sie uns nun mit dem Schreiben von Python-Code zur Multiplikation von Matrizen fortfahren.
Eine benutzerdefinierte Python-Funktion zur Matrizenmultiplikation
Im ersten Schritt werden wir eine Funktion erstellen, die Matrizen multipliziert.
Diese Funktion soll:
- Zwei Matrizen, A und B, als Eingabe akzeptieren.
- Überprüfen, ob die Matrizenmultiplikation zwischen A und B zulässig ist.
- Wenn zulässig, die Matrizen A und B multiplizieren und die Produktmatrix C zurückgeben.
- Andernfalls eine Fehlermeldung zurückgeben, die besagt, dass die Matrizen A und B nicht multipliziert werden können.
Schritt 1: Wir generieren zwei Matrizen mit ganzen Zahlen unter Verwendung der Funktion random.randint() von NumPy. Alternativ können Sie Matrizen auch als verschachtelte Python-Listen definieren.
import numpy as np np.random.seed(27) A = np.random.randint(1,10,size = (3,3)) B = np.random.randint(1,10,size = (3,2)) print(f"Matrix A:\n {A}\n") print(f"Matrix B:\n {B}\n") # Ausgabe Matrix A: [[4 9 9] [9 1 6] [9 2 3]] Matrix B: [[2 2] [5 7] [4 4]]
Schritt 2: Definieren wir die Funktion multiply_matrix(A,B). Diese Funktion nimmt zwei Matrizen A und B als Eingabe und gibt die Produktmatrix C zurück, sofern die Matrizenmultiplikation gültig ist.
def multiply_matrix(A,B): global C if A.shape[1] == B.shape[0]: C = np.zeros((A.shape[0],B.shape[1]),dtype = int) for row in range(A.shape[0]): for col in range(B.shape[1]): for elt in range(B.shape[0]): C[row, col] += A[row, elt] * B[elt, col] return C else: return "Die Matrizen A und B können nicht multipliziert werden."
Funktionsdefinition verstehen
Lassen Sie uns die Funktionsdefinition im Detail analysieren:
C als globale Variable deklarieren: In Python haben Variablen innerhalb einer Funktion standardmäßig einen lokalen Gültigkeitsbereich. Um von außerhalb der Funktion auf die Produktmatrix C zugreifen zu können, müssen wir sie als globale Variable deklarieren. Dies geschieht mit dem Schlüsselwort ‚global‘ vor dem Variablennamen.
Prüfung der Gültigkeit der Matrizenmultiplikation: Wir verwenden das Attribut shape, um zu überprüfen, ob A und B multipliziert werden können. Für ein Array arr gibt arr.shape[0] bzw. arr.shape[1] die Anzahl der Zeilen bzw. Spalten an. Wenn A.shape[1] == B.shape[0] ist, ist die Matrizenmultiplikation gültig. Nur wenn diese Bedingung erfüllt ist, wird die Produktmatrix berechnet. Andernfalls gibt die Funktion eine Fehlermeldung aus.
Berechnung mit verschachtelten Schleifen: Um die Elemente der Produktmatrix zu berechnen, müssen wir die Zeilen der Matrix A durchlaufen, was durch die äußere for-Schleife geschieht. Die innere for-Schleife durchläuft die Spalten der Matrix B, und die innerste for-Schleife greift auf jedes Element in der gewählten Spalte zu.
▶️ Nachdem wir verstanden haben, wie die Python-Funktion zur Matrizenmultiplikation funktioniert, können wir sie mit den zuvor generierten Matrizen A und B aufrufen.
multiply_matrix(A,B) # Ausgabe array([[ 89, 107], [ 47, 49], [ 40, 44]])
Da die Matrizenmultiplikation zwischen A und B gültig ist, gibt die Funktion multiply_matrix() die Produktmatrix C zurück.
Matrizenmultiplikation mit verschachtelten Listenkomprehensionen
Im vorherigen Abschnitt haben wir eine Python-Funktion zur Multiplikation von Matrizen entwickelt. Nun werden wir sehen, wie dies mit verschachtelten Listenkomprehensionen erreicht werden kann.
Hier ist die verschachtelte Listenkomprehension zur Matrizenmultiplikation:
Dies mag anfangs komplex erscheinen, aber wir werden die verschachtelte Listenkomprehension Schritt für Schritt analysieren.
Konzentrieren wir uns auf jede einzelne Listenkomprehension und verstehen, was sie bewirkt.
Wir verwenden das folgende allgemeine Schema für Listenkomprehensionen:
[<do-this> for <item> in <iterable>] wobei, <do-this>: Die auszuführende Operation oder der Ausdruck <item>: Jedes Element, auf das die Operation angewendet wird <iterable>: Das zu durchlaufende Element (Liste, Tuple etc.)
▶️ Lesen Sie unsere Anleitung zu Listenkomprehensionen in Python, um ein tieferes Verständnis zu erhalten.
Beachten Sie, dass wir die resultierende Matrix C zeilenweise erstellen möchten.
Die verschachtelte Listenkomprehension erklärt
Schritt 1: Einen einzelnen Wert in Matrix C berechnen
Für eine gegebene Zeile i von Matrix A und Spalte j von Matrix B berechnet der folgende Ausdruck den Eintrag an Position (i, j) in Matrix C:
sum(a*b for a,b in zip(A_row, B_col)) # zip(A_row, B_col) erzeugt einen Iterator von Tupeln # Wenn A_row = [a1, a2, a3] & B_col = [b1, b2, b3] # erzeugt zip(A_row, B_col) (a1, b1), (a2, b2) usw.
Wenn i = j = 1, gibt der Ausdruck den Eintrag c_11 in Matrix C zurück. Damit können wir ein einzelnes Element in einer Zeile erhalten.
Schritt 2: Eine Zeile in Matrix C erstellen
Unser nächstes Ziel ist es, eine ganze Zeile zu erstellen.
Für Zeile 1 in Matrix A müssen wir alle Spalten in Matrix B durchlaufen, um eine komplette Zeile in Matrix C zu erhalten.
Wir gehen zurück zum Schema der Listenkomprehension:
- Ersetzen Sie <do-this> durch den Ausdruck aus Schritt 1, da dies die gewünschte Operation ist.
- Ersetzen Sie als Nächstes <item> durch B_col – jede Spalte in Matrix B.
- Ersetzen Sie schließlich <iterable> durch zip(*B) – die Liste, die alle Spalten von Matrix B enthält.
Hier ist die erste Listenkomprehension:
[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] # zip(*B): * ist der Unpacking-Operator # zip(*B) gibt eine Liste von Spalten in Matrix B zurück
Schritt 3: Alle Zeilen erstellen und Matrix C erhalten
Nun müssen wir die Produktmatrix C vervollständigen, indem wir die restlichen Zeilen berechnen.
Dafür müssen wir alle Zeilen in Matrix A durchlaufen.
Wir gehen wieder zurück zum Schema der Listenkomprehension:
- Ersetzen Sie <do-this> durch die Listenkomprehension aus Schritt 2. Hier wurde eine gesamte Zeile berechnet.
- Ersetzen Sie nun <item> durch A_row – jede Zeile in Matrix A.
- Und <iterable> ist die Matrix A selbst, da wir ihre Zeilen durchlaufen.
Hier ist die endgültige verschachtelte Listenkomprehension! 🎉
[[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] for A_row in A]
Es ist Zeit, die Ergebnisse zu überprüfen! ✔
# Umwandlung in ein NumPy-Array mit np.array() C = np.array([[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] for A_row in A]) # Ausgabe: [[ 89 107] [ 47 49] [ 40 44]]
Dies entspricht den zuvor verwendeten verschachtelten for-Schleifen, jedoch in einer kompakteren Form.
Mit einigen eingebauten Funktionen kann dies noch effizienter gestaltet werden. Schauen wir uns diese im nächsten Abschnitt an.
Matrizenmultiplikation mit NumPy matmul()
np.matmul() akzeptiert zwei Matrizen als Eingabe und gibt deren Produkt zurück, sofern die Matrizenmultiplikation gültig ist.
C = np.matmul(A,B) print(C) # Ausgabe: [[ 89 107] [ 47 49] [ 40 44]]
Diese Methode ist einfacher als die beiden vorherigen. Anstelle von np.matmul() kann auch der äquivalente @-Operator verwendet werden, wie wir gleich sehen werden.
Verwendung des @-Operators zur Matrizenmultiplikation
In Python ist @ ein binärer Operator, der für die Matrizenmultiplikation verwendet wird.
Er wirkt auf zwei Matrizen (allgemein auch N-dimensionale NumPy-Arrays) und gibt die Produktmatrix zurück.
Beachten Sie, dass Python 3.5 oder neuer erforderlich ist, um den @-Operator verwenden zu können.
So wird er verwendet:
C = A @ B print(C) # Ausgabe array([[ 89, 107], [ 47, 49], [ 40, 44]])
Die Produktmatrix C ist identisch mit der zuvor berechneten.
Kann np.dot() zur Matrizenmultiplikation verwendet werden?
Falls Sie jemals auf Code gestoßen sind, der np.dot() zur Multiplikation zweier Matrizen verwendet, hier eine Erklärung, wie dies funktioniert.
C = np.dot(A,B) print(C) # Ausgabe: [[ 89 107] [ 47 49] [ 40 44]]
np.dot(A, B) gibt ebenfalls die erwartete Produktmatrix zurück.
Laut NumPy-Dokumentation sollte np.dot() jedoch nur für die Berechnung des Skalarprodukts zweier eindimensionaler Vektoren und nicht zur Matrizenmultiplikation verwendet werden.
Wir erinnern uns, dass das Element an der Position (i, j) der Produktmatrix C das Skalarprodukt der Zeile i von Matrix A und der Spalte j von Matrix B ist.
Da NumPy diese Punktproduktoperation implizit auf alle Zeilen und Spalten anwendet, erhalten wir die resultierende Produktmatrix. Um den Code lesbar und verständlich zu halten, verwenden Sie stattdessen np.matmul() oder den @-Operator.
Schlussfolgerung
🎯 In diesem Tutorial haben Sie Folgendes gelernt:
- Die Bedingung für eine gültige Matrizenmultiplikation: Die Spaltenanzahl in Matrix A muss gleich der Zeilenanzahl in Matrix B sein.
- Eine benutzerdefinierte Python-Funktion schreiben, die überprüft, ob eine Matrizenmultiplikation gültig ist, und die Produktmatrix zurückgibt. Das Herzstück der Funktion verwendet verschachtelte for-Schleifen.
- Ebenfalls haben Sie gelernt, wie man verschachtelte Listen verwendet, um Matrizen zu multiplizieren. Diese sind kompakter, aber weniger leicht verständlich.
- Schließlich haben Sie gelernt, die in NumPy integrierte Funktion np.matmul() zu verwenden, um Matrizen zu multiplizieren, was in Bezug auf die Geschwindigkeit die effizienteste Methode ist.
- Sie haben auch den @-Operator zur Multiplikation zweier Matrizen in Python kennengelernt.
Damit endet unsere Diskussion über die Matrizenmultiplikation in Python. Als Nächstes können Sie lernen, wie man in Python eine Primzahl prüft oder interessante Probleme mit Python-Strings löst.
Viel Spaß beim Lernen!🎉