Schlauer Zwerg: Maschinelles Lernen mit dem Raspberry Pi Pico, Teil 3: Tuning

Machine-Learning-Modelle lassen sich auf unterschiedliche Weise anpassen, um die Ergebnisse zu optimieren.

In Pocket speichern vorlesen Druckansicht 5 Kommentare lesen
Künstliche Intelligenz, KI

(Bild: Gerd Altmann, gemeinfrei)

Lesezeit: 16 Min.
Von
  • Lars Gregori
Inhaltsverzeichnis

Der Raspberry Pi Pico eignet sich gut für Machine-Learning-Anwendungen. Im Rahmen dieser dreiteiligen Artikelserie entsteht als Beispielanwendung eine einfache XOR-Schaltung (Exklusiv Oder) mit zwei Tastern und einer Leuchtdiode.

Nach der Beschreibung des Schaltungsaufbau im ersten und des Trainings im zweiten Teil beschäftigt sich der dritte und letzte Teil mit Anpassungen und deren Auswirkungen auf die Genauigkeit, Geschwindigkeit und Größe des Modells. Auch wenn das Exklusiv-Oder-Modell einen einfachen Aufbau hat, lassen sich durch ein paar Modifikationen die Werte beeinflussen. Auf GitHub ist das Jupyter Notebook für den dritten Teil zu finden. Die ebenfalls dort verfügbare Anwendung für den Raspberry Pi Pico bringt die Anpassungen mit.

Schlauer Zwerg: ML mit dem Raspberry Pi Pico

Wie im zweiten Teil der Artikelserie gezeigt, berechnet das Training schrittweise die Gewichtungen innerhalb des Modells. Durch immer kleinere Anpassungen nähert sich das Ergebnis den erwarteten Werten von 0 beziehungsweise 1 an. Ein höherer epoch-Wert verbessert das Vorgehen. Das Training berechnet damit genauere Werte, dauert aber länger.

Die Bibliothek time misst mit der gleichnamigen Funktion die aktuelle Zeit. Die Differenz von Anfang und Ende ergibt die Dauer des Trainings, die jedoch von der Umgebung abhängt. Für Durchläufe in derselben Umgebung lassen sich die Zeiten in Relation setzen, wobei sich die Zeiten durch äußere Einflüsse von Lauf zu Lauf unterscheiden können. Daher sind die im Folgenden aufgezeigten Werte nicht deterministisch, sondern lediglich Anhaltspunkte. Um die Zeiten zu messen, ist das Jupyter Notebook wie folgt anzupassen:

import time

t1 = time.time()
model.fit(...
t2 = time.time()
print(t2 - t1)

Das Training benötigt bei den ursprünglichen 500 Epochen 11,2 Sekunden. Der ermittelte loss liegt bei 0,047 und das erste Ergebnis (beide Taster sind nicht gedrückt) weicht um einen Wert von 0,036 ab. Verdoppelt sich der epochs-Wert auf 1000, benötigt das Training ebenfalls doppelt so lang. Der loss reduziert sich auf 0,011 und das erste Ergebnis weicht nur noch um 0,014 ab. Dieser Trend lässt sich mit 5000 und 10.000 Epochs fortführen. Im letzteren Fall beläuft sich die Trainingsdauer auf das zwanzigfache und liegt mit 226 Sekunden bei fast vier Minuten. Der loss ist auf 0,00066 gesunken. Die folgende Ausgabe zeigt die berechneten Werte.

array([[3.4713745e-04],
       [9.9930656e-01],
       [9.9936283e-01],
       [9.6103549e-04]], dtype=float32)

Das Jupyter Notebook verwendet die Exponentialschreibweise: Der erste Wert ist 0,000347.

Eine längere Trainingsdauer hat somit bei dem XOR-Modell einen Einfluss auf das Ergebnis. Das gilt jedoch nur, solange sich in jedem Schritt der loss reduziert. TensorFlow bietet die Option, die Veränderungen bei jedem Schritt zu vergleichen und den Trainingslauf zu stoppen, wenn kein Fortschritt zu erkennen ist.

Für die Testreihe hat sich lediglich der epoch-Wert geändert. Dadurch hat das Training genauere Werte für die Gewichtung berechnet. Der Aufbau und die Größe des Modells sind hingegen gleich geblieben. Die letzte Zeile der Datei model.cpp zeigt für die Variable model_data_len unverändert den Wert von 1576 Bytes an. Die Ausführungszeit auf dem Raspberry Pi Pico ändert sich ebenfalls nicht. Die Zeitmessung auf dem Pico betrachtet der Artikel im späteren Verlauf.

Die Anzahl der Schichten und Knoten beeinflussen das Modell und dessen Größe. Ebenso verändert sich die Zeit für das Training und die Ausführungsgeschwindigkeit auf dem Raspberry Pi Pico. Wie oben zu sehen ist, hängen der loss und die Genauigkeit der berechneten Werte hauptsächlich von der Trainingsdauer ab. Die Berechnungen erreichen jedoch fast nie die idealen Werte von 0 und 1. Daher ist beim Exklusiv-Oder-Modell der Zeitpunkt interessanter, an dem der accuracy-Wert für die Genauigkeit 1,0 erreicht.

Dass dieser Wert erreichbar ist, ist jedoch eine Besonderheit des XOR-Modells. Bei anderen Modellen bleibt er niedriger als 1,0. Das Training spiegelt dabei die tatsächliche Genauigkeit des Modells wider. Üblicherweise deutet ein accuracy-Wert von 1 auf Overfitting hin. Das bedeutet, dass das Modell mit den Trainingsdaten hervorragend zurechtkommt, aber zu realen Daten, die sich von denen für das Training unterscheiden, schlechte Ergebniswerte liefert. Das Training des Exklusiv-Oder-Modells verwendet alle vier möglichen Zustände für die Trainingsdaten. Da die realen Daten ebenfalls auf die vier Zustände begrenzt sind, berechnet das Modell die passenden Werte und erreicht die maximale accuracy.

TensorBoard stellt die Accuracy für die beiden Modelle dar.

Sie gibt den accuracy-Wert bei zwei unterschiedlichen Modellen wieder. Im ersten Fall besteht das Modell aus dem bekannten Aufbau, bei der die innere Schicht acht Knoten aufweist. Sie ist auch als Hidden-Layer bekannt, weil sie sich zwischen der Eingangs- und Ausgangsschicht versteckt. Das zweite Modell hat lediglich drei Knoten innerhalb der inneren Schicht.

Das Modell hat einen Hidden-Layer mit drei Knoten.

Das Modell mit acht Knoten erreicht nach 230 Epochen eine accuracy von 1,0. Die zweite, blaue Kennlinie für das Modell mit drei Knoten im Hidden Layer erreicht den Wert erst bei Epoche 412. Das Training benötigt mehr Zeit, da lediglich drei statt acht Stellschrauben vorhanden sind. Die Änderung eines der Gewichte wirkt sich stärker auf das Modell aus. Dadurch muss das Training häufiger die Werte anpassen.

Das wirkt sich auch auf den loss aus. Während er beim Modell mit acht Knoten nach 500 Epochen bei 0,05 liegt, ist er bei dem Modell mit drei Knoten schlechter und liegt bei 0,18. Entsprechend ungenau sind die im Folgenden aufgeführten berechneten Werte, bei denen insbesondere der letzte Wert abweicht, der den Zustand repräsentiert, bei dem beide Taster gedrückt sind.

array([[0.0909577 ],
       [0.8574549 ],
       [0.8484072 ],
       [0.26555923]], dtype=float32)

Trotz allem ist das Modell auf dem Raspberry Pi Pico weiterhin lauffähig. Da die beiden mittleren Werte für je einen gedrückten Taster über 0,5 liegen, schaltet sich die Leuchtdiode korrekt an. Die anderen beiden Werte liegen darunter und die Leuchtdiode bleibt aus. Andernfalls hätte das Training nicht die accuracy von 1,0 ermittelt. Ein Wert von 0,5 würde bedeuten, dass das Modell lediglich die Hälfte, also zwei von vier Werten richtig zurückgibt. Das ist beispielsweise der Fall, wenn das Modell immer 1 oder immer 0 berechnet. In zwei von vier Fällen ist das Ergebnis richtig und in den anderen beiden falsch.