Da unser neuronales Netz auf PCs und Laptops voll funktionsfähig ist, können wir auf die Implementierung des mehrschichtigen Perzeptrons vertrauen. Viele Anwendungen erfordern eine geringe Leistungsaufnahme und eine minimale Latenzzeit, die ein Mikrocontroller bietet. Andere möchten ihre privaten Daten einfach nicht mit fremden Cloud-KI-Diensten teilen. Deshalb machen wir unser neuronales Netz „Arduino-fähig“ und übertragen den Ampelklassifizierungscode in die Welt der eingebetteten Systeme.
 

Eingebettete MCU-Applikation

Tools und Plattformen für maschinelles Lernen (ML) scheinen wie Pilze aus dem Boden zu schießen. Ist die Aufgabe noch so komplex und der Datensatz noch so groß, es gibt immer einen Cloud-Dienst, der diese Aufgabe bewältigen kann. Dennoch gibt es viele Fälle, in denen eine Cloud-basierte ML-Implementierung ungeeignet ist. Wenn Sie sensible oder persönliche Daten verarbeiten, möchten Sie diese vielleicht nicht über das Internet übertragen, um sie von einem ML-Tool analysieren zu lassen. Ein weiteres Beispiel sind eingebettete Anwendungen für die Automobilindustrie oder andere Echtzeitanwendungen. Solche Systeme erfordern eine sofortige Entscheidung, so dass die Latenzzeit einer Internetverbindung oder die Gefahr, überhaupt keine Verbindung zu haben, eine lokale ML-Lösung erfordert. Dies wird auch als „On-Edge Machine Learning“ bezeichnet.
 
Der Betrieb eines neuronalen Netzes On-Edge erfordert, dass selbst einfache Mikrocontroller ML-Algorithmen ausführen können. Aufgrund der für das Training erforderlichen Prozessorleistung wird das Netz jedoch häufig in der Cloud oder auf einem leistungsstarken PC trainiert. Die resultierenden Gewichte werden anschließend auf den Mikrocontroller heruntergeladen, um einen internetfreien Betrieb mit geringer Latenz zu ermöglichen.
 
Dieser letzte Artikel der Serie überträgt unser Netzwerk mit mehrschichtigen neuronalen Perzeptronen (MLP) auf einen Arduino. In Verbindung mit einem RGB-Sensor bringen wir ihm bei, die Ampelfarben zu klassifizieren, wie wir es mit Processing auf dem PC oder Laptop getan haben. Mit einem 32-Bit-Arduino (Due oder M0 Pro) könnten wir die Lernphase zwar auf dem Mikrocontroller durchführen, werden dabei jedoch feststellen, dass dieser Vorgang ziemlich langwierig ist. Daher teilen wir die Aufgabe auch so auf, dass das Netz mit der Leistung eines PCs trainiert und dann in der latenzarmen, stromsparenden Umgebung einer eingebetteten Mikrocontroller-Anwendung ausgeführt wird.

Auswahl des Sensors

Zur Erkennung der Ampelfarben benötigt der Arduino einen geeigneten Sensor am Eingang. Der TCS34725 ist eine geeignete RGB-Sensorlösung, die von Adafruit auf einem Platinchen von 2 × 2 cm einsatzbereit erhältlich ist. Damit können wir RGB-Daten genau so erfassen, wie wir es zuvor mit der Kamera getan haben, und sie auf die gleiche MLP-Konfiguration anwenden, die in den vorherigen PC-basierten Beispielen verwendet wurde. Das Board kann sowohl mit 5-V- als auch mit 3,3-V-Arduinos verwendet werden. Die Sensordaten werden über I2C erfasst, wofür die Wire-Bibliothek erforderlich ist.
 
Um die "Ampel" gleichmäßig auszuleuchten, enthält das Board auch eine weiße LED, die über einen digitalen Arduino-Ausgang (Pin 10) gesteuert wird (Bild   1). Glücklicherweise wird das Board von einer gut aufgebauten Bibliothek unterstützt, sodass der Einstieg einfach und unkompliziert ist. Wie zuvor werden wir den Code aus dem GitHub-Repository verwenden, der für diese Artikelserie vorbereitet wurde.

Wiring diagram for TCS34725 RGB sensor with Arduino DUE - Embedded Neurons article
Bild 1. Schaltplan für den RGB-Sensor TCS34725 in Verbindung mit einem Arduino Due.

Vor der Ausführung des Codes müssen wir die Bibliothek für den RGB-Sensor installieren. Dies dürfte zum Glück auch einfach sein, da sie über den Bibliotheksmanager in der Arduino-IDE zugänglich ist. Wählen Sie in der Menüleiste einfach Sketch -> Bibliothek einbinden -> Bibliotheken verwalten und geben Sie dann „tcs“ in das Suchfeld des Bibliotheksmanagers ein. Es sollte die Bibliothek Adafruit TCS34725 erscheinen. Klicken Sie zur Installation einfach auf Installieren (Bild 2). Sollten Schwierigkeiten auftreten, können der Quellcode und die Header-Datei vom Adafruit GitHub-Repository heruntergeladen und manuell zu den Projekten hinzugefügt werden.
 

Installing the Adafruit TCS34725 RGB sensor software library
Bild 2. Installation der Adafruit-Softwarebibliothek für den RGB-Sensor TCS34725 in der Arduino IDE.

Damit der Sensor und die Erfassung der RGB-Werte für das ML-Training richtig funktioniert, ist der Sketch arduino/tcsrgbsensor/tcsrgbsensor.ino erforderlich.       

Nach der Initialisierung des RGB-Sensors schaltet der Code die LED ein und beginnt, die RGB-Werte über den seriellen Ausgang auszugeben (Bild 3).
 

RGB value outputs provided by tcsrgbsensor.ino
Bild 3. Ermittelte RGB-Werte, die von tcsrgbsensor.ino ausgegeben werden.

Öffnen Sie Werkzeuge -> Serieller Monitor, um sie anzuzeigen. Die Baudrate ist auf 9600 eingestellt. Zur Verbesserung der Qualität der Messwerte und zur Verringerung des Einflusses anderer Lichtquellen lohnt es sich, eine mechanische Abschirmung um das Sensorboard herum zu bauen. Ein etwa 3 cm hoher und 10 cm langer Streifen aus schwarzem Karton ist dafür ideal (Bild 4). Die Abschirmung sorgt auch dafür, dass das Bild der Ampel in einem gleichmäßigen Abstand zum RGB-Sensor gehalten werden kann.
 

TCS34725 RGB sensor with black card shield
Bild 4. RGB-Sensor TCS34725 mit montierter schwarzer Kartonblende.

Da der RGB-Sensor zuverlässige Ergebnisse liefert, können wir nun seine Bewertung der roten, gelben und grünen Farben anhand unseres ausgedruckten Ampelbildes (aus trafficlight/resources) erfassen. Die vom Autor erzielten Ergebnisse sind in Tabelle 1 dargestellt.
 

RGB values captured using TCS34725 3 traffic light colors (Table 1) and ‘unwanted’ colors (Table 2). Embedded Neurons article
Tabelle 1. Mit TCS34725 erfasste RGB-Werte für die drei Ampelfarben.
Tabelle 2 Mit TCS34725 erfasste RGB-Werte für die „unerwünschten“ Farben.

Eine MLP-Bibliothek für den Arduino

Nachdem wir die RGB-Werte bestimmt haben, implementieren wir das neuronale Netz für die Arduino-Plattform. Da Processing Java verwendet, können wir den Code der Neural-Klasse nicht einfach in ein Arduino-Projekt einfügen. Daher wurde die Java-Neural-Klasse leicht modifiziert, um sie in eine C++-Klasse zu verwandeln. In der Arduino-Welt können solche wiederverwendbaren Code-Objekte in „Bibliotheken“ umgewandelt werden. Diese bestehen aus einer C++-Klasse und einer zusätzlichen Datei zur Hervorhebung der Schlüsselwörter der Klasse. Wenn Sie Ihre eigene Bibliothek schreiben oder besser verstehen möchten, wie C++-Klassen auf Arduino funktionieren, finden Sie auf der Arduino-Website ein hervorragendes Tutorial.
 
Der Code für unsere Neural-Bibliothek ist in arduino/neural zu finden. Die folgenden Arduino-Projekte enthalten der Einfachheit halber nur den Quellcode der Neural-Klasse in Sketch. Die Header-Datei neural.h muss ebenfalls dem Ordner hinzugefügt werden, in dem das Projekt gespeichert ist.
 
Die Verwendung der Neural-Klasse auf einem Arduino ist größtenteils identisch mit der Verwendung in Processing Das Erstellen unseres network-Objekts als globale Variable ist etwas anders und wird wie folgt durchgeführt:
 
Neural network;
 
Zur Erstellung des Objekts mit der gewünschten Anzahl von Eingangs-, verborgenen und Ausgangsknoten geben wir Folgendes ein:
 
network = new Neural(3,6,4);
 
Die Grundkonfiguration der Bias-Werte und der Lernrate wird dann wie zuvor in Processing kodiert:
 
network.setLearningRate(0.5);
network.setBiasInputToHidden(0.35);
network.setBiasHiddenToOutput(0.60);

 
Von hier aus können wir die Methoden weiter verwenden, wie wir sie zuvor in Processing verwendet haben.

Arduino erkennt Ampelfarben

Jetzt können wir mit der Erforschung des MLP auf dem Arduino beginnen. Der Sketch /arduino/tlight_detect/tlight_detect.ino folgt der gleichen Struktur wie das Processing-Projekt tlight_detect.pde. Das neuronale Netz (3/6/4) wird ab Zeile 40 konfiguriert und in einer Schleife ab Zeile 51 mit den RGB-Daten trainiert. Bevor der Code ausgeführt wird, müssen die zuvor erfassten RGB-Werte für „Rot“, „Gelb“ und „Grün“ ab Zeile 56 eingegeben werden:

teachRed(220, 56, 8);
teachAmber(216, 130, 11);
teachGreen(123, 150, 128);

 
Laden Sie den Code hoch und öffnen Sie den Serial Monitor, um die ausgegebenen Werte zu sehen (Bild 5). Wie zuvor sollte die Baud-Einstellung 9600 betragen. Das Projekt prüft, ob der RGB-Sensor funktionsfähig ist, bevor es die weiße LED während des Lernprozesses ausschaltet. Sobald MLP konfiguriert ist, durchläuft sie den Lernzyklus 30.000 Mal und verbessert dabei jedes Mal ihre Fähigkeit, alle drei Farben zu klassifizieren.

Output of tlight_detect.ino during learning
Bild 5. Ausgabe von tlight_detect.ino während des Lernens.

Zur Kontrolle des Lernprozesses wird alle 1.000 Zyklen (3.000 Lernepochen) ein Punkt ausgegeben. Im Vergleich zum PC ist der Lernprozess wirklich langsam: Jeder Aufruf einer Lernfunktion (learnRed(), etc.) benötigt etwa 5,55 ms bis zum Abschluss. Das Erlernen aller drei Farben benötigt auf einem Arduino M0 Pro mit einem SAMD21-Mikrocontroller etwa 8,5 Minuten. Wenn Sie die Ausführungszeit Ihrer Plattform überprüfen möchten, aktivieren Sie das Kontrollkästchen Zeitstempel anzeigen im Seriellen Monitor und ersetzen Sie Zeile 66 durch:
 
Serial.println(".");
 
Dadurch wird das Zeilenumbruchzeichen hinzugefügt und für jedes ausgegebene '.'-Zeichen ein Zeitstempel erzeugt.         
 
Sobald der Lernprozess abgeschlossen ist, macht sich der Arduino sofort daran, seine neuen Fähigkeiten unter Beweis zu stellen Immer, wenn eine Ampelfarbe erkannt wird, wird sie an den seriellen Monitor ausgegeben (Bild 6). Beim Experimentieren des Autors erkannte das neuronale Netz auch dann die Farbe „Gelb“, wenn nichts vor den Sensor gehalten wurde. Obwohl dies mit der Umgebungsbeleuchtung zusammenzuhängen schien, zeigt es eine Schwachstelle in der Implementierung auf.

Output of tlight_detect.ino after learning and detecting colors
Bild 6. Ausgabe von tlight_detect.ino nach dem Lernen und Erkennen von Farben.

Zur Verbesserung des Codes können wir dem MLP „andere“ Farben beibringen, wie wir es zuvor in Processing getan haben. Dies kann auch verwendet werden, um die Klassifizierung „Gelb“ zu unterdrücken, wenn kein Bild vorhanden ist. Der Sketch tcsrgbsensor.ino kann verwendet werden, um die Messwerte des Sensors für die Ampelumgebung, den Rahmen und den Bildhintergrund zu erfassen. Diese können dann ab Zeile 60 im Sketch tlight_detect.ino in den teachOther()-Funktionsaufrufen eingegeben werden.
 
Mit dem Sketch tlight_detect.ino wurden die in Tabelle 2 gezeigten Werte erreicht und getestet. Die Klassifizierung hat sich verbessert, aber die falsche Klassifizierung keines Bildes als „Gelb“ wurde nicht vollständig behoben. Wie immer gibt es Raum für Verbesserungen!

Optimiertes Lernen

Beim Erlernen der „anderen“ Farben im Arduino-Sketch dauert es etwa 18 Minuten, bis ein M0 Pro die gewünschten Klassifizierungen gelernt hat. Das lässt definitiv Raum für eine Optimierung des Prozesses. Da unser leistungsfähiger PC die Gewichte in weniger als einer Sekunde berechnen kann, wäre es sinnvoll, das Lernen dort durchzuführen und die Ergebnisse erst danach auf den Arduino zu übertragen. Mit diesen Gewichten haben wir auch die Möglichkeit, mehrere Mikrocontroller mit demselben „Wissen“ zu programmieren. In der Annahme, dass die RGB-Sensoren in Bezug auf unsere Eingabe alle ähnlich funktionieren, sollte jeder Mikrocontroller das Ampelbild korrekt klassifizieren. Dies werden wir also als Nächstes in Angriff nehmen.
 
Wir kehren aber kurz zu Processing zurück, um das Projekt /arduino/learnfast/learnfast.pde zu öffnen. Die gesamte Anwendung wird in der Funktion setup() ausgeführt. Das neuronale Netz wird mit denselben Eingangs-, versteckten und Ausgangsknoten konfiguriert, die auf dem Arduino-Board verwendet werden (3/6/4). In der Lernschleife (Zeile 36) werden die Werte verwendet, die vom Arduino mit dem RGB-Sensor und dem Sketch tcsrgbsensor.ino erfasst wurden. Wenn der Code ausgeführt wird, gibt er Text auf seiner Konsole aus. Der letzte Abschnitt enthält den Code, der alle Gewichte (Eingang zu versteckten Knoten und versteckte Knoten zu Ausgang) konfiguriert (Bild 7). Kopieren Sie einfach den generierten Code, beginnend bei // For Input Node =0 bis zum Ende der Textausgabe.

 
 Weights can be quickly calculated on a PC using learnfast.pd
Bild 7. Mit learnfast.pde in Processing können Gewichte schnell auf einem PC berechnet werden.
Die Ausgabe der Textkonsole kann dann in tlight_weights.ino eingefügt werden.

Zurück in der Arduino-IDE können wir nun den Sketch /arduino/tlight_weights/tlight_weights.ino öffnen. Dies ist derselbe wie der Sketch tlight_detect.ino, aber anstatt das neuronale Netz zu lehren, werden die Gewichte vorprogrammiert. Dies geschieht in Zeile 51 mit der Funktion importWeights(). Fügen Sie einfach den Code aus der learnfast.pde Ausgabe in die importWeights()-Funktion in Zeile 86 in tlight_weights.ino ein. Nach der Programmierung des Arduino-Boards sollte es die Ampelfarben wie zuvor genau erkennen.
 
Tatsächlich können wir jetzt, da wir diesen optimierten Lernprozess haben, sogar denselben tlight_weights.ino-Sketch in einen Arduino Uno programmieren. Schließen Sie einfach den RGB-Sensor an das Board an, öffnen Sie den seriellen Monitor und beobachten Sie, wie dies genau so gut funktioniert wie auf einem Arduino M0 Pro oder Due. Zum Vergleich können Sie den digitalen Pin 9 überwachen, um zu sehen, wie lange es dauert, bis die Methode calculateOutput() die Berechnungen durchführt.        

Was kommt als Nächstes?

Und wie geht es jetzt weiter? Mehr eingebettete Systeme? Nun, wir haben ein funktionierendes neuronales MLP-Netzwerk, das sowohl auf einem PC als auch auf einem Mikrocontroller funktioniert. Außerdem verfügen wir über einen optimierten Lernprozess, um die Gewichte zu erzeugen, die in Mikrocontroller-Anwendungen benötigt werden. Sie könnten versuchen, diese MLP auf andere Aufgaben anzuwenden, die zu schwierig sind, um sie mit if-else-Anweisungen und festen Grenzwerten zu lösen. Vielleicht ist es sogar möglich, ein einfaches Spracherkennungsprojekt zu implementieren, um ein paar Wörter zu erkennen. Sie könnten auch das Folgende erforschen:

  • Die Neural-Klasse verwendet den Datentyp Double. Kann sie mit Float beschleunigt werden und trotzdem die Genauigkeit beibehalten? Wie viel schneller kann sie laufen?
  • Die Sigmoid-Funktion verwendet die mathematische Funktion exp() und berechnet den Exponentialwert, der auf das übertragene Argument bezogen wird. Kann die Aktivierungsfunktion durch eine Näherung vereinfacht werden und trotzdem eine genaue Klassifizierung liefern?
  • Wenn Sie einen Versuch zur Spracherkennung durchführen: Wie würden Sie eine Sprachprobe vorbereiten, um sie dieser MLP-Implementierung zu präsentieren?
  • Wie wäre es mit einigen bedeutenden Veränderungen? Wie würden Sie eine zweite Schicht mit versteckten Knoten implementieren? Können Sie eine andere Aktivierungsfunktion implementieren? 

In dieser Reihe von Artikeln haben wir eine Menge Themen behandelt. Wir haben die Oberfläche der frühen Forschung zu künstlichen Neuronen angekratzt. Danach haben wir untersucht, wie MLPs mit Hilfe von Backpropagation lernen, und wir haben ihre Funktionsweise unter Verwendung der leistungsstarken Verarbeitungsmöglichkeiten eines PCs untersucht. Anschließend haben wir den MLP als Beispiel für Edge ML auf einen Mikrocontroller transferiert. Wenn Sie diese Beispiele weiterentwickeln möchten, können Sie Ihre Ergebnisse gerne mit uns hier bei Elektor teilen.

Bessere Landwirtschaft

Die Landwirtschaft hat sich schon immer auf die Natur und die Jahreszeiten verlassen, um den besten Zeitpunkt zum Ernten und Säen zu bestimmen. Die Tradition diktierte schon immer den optimalen Zeitpunkt für die Aussaat, um zum Beispiel von der Monsunzeit zu profitieren. Doch mit den sich ändernden Klimabedingungen haben die Ernteerträge gelitten. All dies ändert sich dank der KI. Indische Landwirte, die an einem Pilotprojekt teilnahmen, planten ihre Erdnussernte Ende Juni, drei Wochen später als üblich. Die Microsoft Cortana Intelligence Suite lieferte diese Anleitung. Dank historischer Klimadaten führten die Empfehlungen, die die Landwirte erhielten, zu einem durchschnittlich 30% höheren Ertrag [6].
 

Better farming - Embedded Neurons article
 

Haben Sie Fragen zu eingebetteten Neuronen?

Haben Sie Fragen oder Kommentare zu eingebetteten Neuronen? Dann schreiben Sie bitte dem Autor eine E-Mail an: stuart.cording@elektor.com.

 

Übersetzung: Textmaster