NumPy Broadcasting für effiziente Berechnungen

NumPyBeginner
Jetzt üben

Einführung

Broadcasting ist ein grundlegendes Konzept in NumPy, das elementweise arithmetische Operationen auf Arrays unterschiedlicher Formen ermöglicht. Dieses leistungsstarke Feature eliminiert die Notwendigkeit expliziter Schleifen und führt zu prägnanterem und recheneffizienterem Code. In diesem Lab lernen Sie die Regeln des Broadcastings kennen und wenden sie anhand praktischer Beispiele durch Schreiben und Ausführen von Python-Skripten an.

Dies ist ein Guided Lab, das schrittweise Anweisungen bietet, um Ihnen beim Lernen und Üben zu helfen. Befolgen Sie die Anweisungen sorgfältig, um jeden Schritt abzuschließen und praktische Erfahrungen zu sammeln. Historische Daten zeigen, dass dies ein Labor der Stufe Anfänger mit einer Abschlussquote von 97% ist. Es hat eine positive Bewertungsrate von 100% von den Lernenden erhalten.

Broadcasting eines Skalars auf ein Array

Die einfachste Form des Broadcastings tritt auf, wenn Sie eine Operation zwischen einem Array und einer einzelnen Zahl (einem Skalar) durchführen. NumPy "streckt" oder "broadcastet" den Skalar automatisch, um die Form des Arrays anzupassen.

Suchen Sie zuerst die Datei broadcasting.py im Dateiexplorer auf der linken Seite Ihres Bildschirms. Doppelklicken Sie darauf, um sie im Editor zu öffnen.

Ersetzen Sie nun den Inhalt von broadcasting.py durch den folgenden Code. Dieser Code erstellt ein 1D-NumPy-Array und multipliziert es mit einem Skalarwert.

import numpy as np

## Erstelle ein 1D-Array
a = np.array([1.0, 2.0, 3.0])

## Definiere einen Skalar
b = 2.0

## Multipliziere das Array mit dem Skalar
## Der Skalar 'b' wird an die Form von 'a' gebroadcastet
result = a * b

print("Array 'a':", a)
print("Skalar 'b':", b)
print("Ergebnis von a * b:", result)

Um das Ergebnis zu sehen, müssen Sie das Skript ausführen. Öffnen Sie ein Terminal, indem Sie auf das +-Symbol im Terminal-Panel am unteren Bildschirmrand klicken und Terminal auswählen. Führen Sie dann den folgenden Befehl aus:

python broadcasting.py

Sie sollten die folgende Ausgabe sehen, bei der jedes Element des Arrays a mit 2.0 multipliziert wurde.

Array 'a': [1. 2. 3.]
Skalar 'b': 2.0
Ergebnis von a * b: [2. 4. 6.]

Broadcasting zweier Arrays mit kompatiblen Formen

Broadcasting funktioniert auch zwischen zwei Arrays, wenn ihre Formen kompatibel sind. Die allgemeine Regel für Kompatibilität lautet: Beim Vergleichen der Dimensionen zweier Arrays von rechts nach links müssen beide Dimensionen entweder gleich sein oder eine davon muss 1 sein.

Betrachten wir ein Beispiel für die Addition eines 1D-Arrays zu einem 2D-Array. Das 1D-Array wird über jede Zeile des 2D-Arrays gebroadcastet.

Aktualisieren Sie Ihre Datei broadcasting.py mit dem folgenden Code:

import numpy as np

## Erstelle ein 2D-Array (Form: 2, 3)
a = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])

## Erstelle ein 1D-Array (Form: 3,)
b = np.array([10.0, 20.0, 30.0])

## Addiere die beiden Arrays
## 'b' wird auf die Form (2, 3) gebroadcastet, um 'a' anzupassen
## Intern wird es zu [[10. 20. 30.], [10. 20. 30.]]
result = a + b

print("Array 'a' (Form {}):\n{}".format(a.shape, a))
print("Array 'b' (Form {}): {}".format(b.shape, b))
print("Ergebnis von a + b:\n", result)

Führen Sie das Skript erneut im Terminal aus:

python broadcasting.py

Die Ausgabe zeigt, dass das 1D-Array b zu jeder Zeile des 2D-Arrays a addiert wurde.

Array 'a' (Form (2, 3)):
[[1. 2. 3.]
 [4. 5. 6.]]
Array 'b' (Form (3,)): [10. 20. 30.]
Ergebnis von a + b:
 [[11. 22. 33.]
 [14. 25. 36.]]

Verständnis inkompatibler Formen

Broadcasting schlägt fehl, wenn die Formen der Arrays gemäß den Regeln nicht kompatibel sind. Dies führt zu einem ValueError. Zu verstehen, wann dies geschieht, ist entscheidend für die Fehlersuche.

Versuchen wir eine Operation mit inkompatiblen Formen. Hier versuchen wir, ein Array der Form (2, 3) mit einem Array der Form (2,) zu addieren. NumPy vergleicht die nachgestellten Dimensionen (3 und 2), stellt fest, dass sie nicht gleich sind und keine davon 1 ist. Dies führt zu einem Fehler.

Ändern Sie Ihre Datei broadcasting.py so, dass sie den folgenden Code enthält:

import numpy as np

## Erstelle ein 2D-Array (Form: 2, 3)
a = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])

## Erstelle ein inkompatibles 1D-Array (Form: 2,)
b = np.array([1.0, 2.0])

print("Array 'a' (Form {}):\n{}".format(a.shape, a))
print("Array 'b' (Form {}): {}".format(b.shape, b))

## Dies löst einen ValueError aus
try:
    result = a + b
except ValueError as e:
    print("\nError:", e)

Führen Sie das Skript vom Terminal aus:

python broadcasting.py

Wie erwartet fängt das Programm einen ValueError ab und gibt eine Fehlermeldung aus, die erklärt, dass die Formen nicht übereinstimmen. Dies ist das korrekte und erwartete Verhalten für inkompatible Formen.

Array 'a' (Form (2, 3)):
[[1. 2. 3.]
 [4. 5. 6.]]
Array 'b' (Form (2,)): [1. 2.]

Error: operands could not be broadcast together with shapes (2,3) (2,)

Praktisches Beispiel - Vektorisierung

Wenden wir Broadcasting auf ein praktisches Problem an. Vektorquantisierung (VQ) ist eine Technik, die in der Datenkompression und Klassifizierung verwendet wird. Ein wichtiger Schritt ist die Suche nach dem nächstgelegenen "Code"-Vektor aus einem "Codebook" zu einem gegebenen "Beobachtungs"-Vektor. Broadcasting macht diese Berechnung effizient.

Stellen Sie sich vor, wir haben eine Beobachtung (z. B. das Gewicht und die Größe eines Athleten) und ein Codebook mit verschiedenen Athletentypen. Wir möchten herausfinden, welchem Typ unsere Beobachtung am nächsten liegt.

Ersetzen Sie den Code in broadcasting.py durch Folgendes:

import numpy as np

## Ein Beobachtungsvektor (z. B. Gewicht, Größe)
observation = np.array([111.0, 188.0])

## Ein Codebook von Vektoren
codes = np.array([[102.0, 203.0],
                  [132.0, 193.0],
                  [45.0, 155.0],
                  [57.0, 173.0]])

## Verwenden Sie Broadcasting, um die Beobachtung auf einmal von allen Codes zu subtrahieren
## observation (2,) wird auf (4, 2) gebroadcastet
diff = codes - observation

## Berechnen Sie die quadrierte Euklidische Distanz
dist_sq = np.sum(diff**2, axis=-1)

## Finden Sie den Index der minimalen Distanz
closest_index = np.argmin(dist_sq)

## Holen Sie sich den nächstgelegenen Code aus dem Codebook
closest_code = codes[closest_index]

print("Observation:", observation)
print("Codebook:\n", codes)
print("Distances squared:", dist_sq)
print("Closest code index:", closest_index)
print("Closest code:", closest_code)

Führen Sie das Skript in Ihrem Terminal aus:

python broadcasting.py

Die Ausgabe zeigt die quadrierten Distanzen von der Beobachtung zu jedem Code und identifiziert den nächstgelegenen übereinstimmenden Code-Vektor. Diese gesamte Berechnung wurde dank Broadcasting ohne explizite Python-Schleifen durchgeführt.

Observation: [111. 188.]
Codebook:
 [[102. 203.]
 [132. 193.]
 [ 45. 155.]
 [ 57. 173.]]
Distances squared: [ 306.  466. 5445. 3141.]
Closest code index: 0
Closest code: [102. 203.]

Zusammenfassung

In diesem Lab haben Sie die Grundlagen des NumPy-Broadcasting gelernt. Sie begannen mit dem einfachen Fall, einen Skalar auf ein Array zu übertragen, gingen zum Broadcasting zwischen zwei kompatiblen Arrays über und lernten, inkompatible Formen zu erkennen, die Fehler auslösen. Schließlich haben Sie Broadcasting auf ein praktisches Vektorquantisierungsproblem angewendet und seine Leistungsfähigkeit demonstriert, um sauberen, effizienten und schleifenfreien Code für numerische Berechnungen zu schreiben. Die Beherrschung des Broadcastings ist ein wichtiger Schritt zum Schreiben effektiven und professionellen NumPy-Codes.