Nu ons neurale netwerk  op PC's en laptops volledig functioneert, kunnen we vertrouwen op onze multilayer perceptron-implementatie. Veel toepassingen vereisen het lage stroomverbruik en de minimale latentie die een microcontroller biedt. Anderen willen hun privégegevens eenvoudigweg niet delen met cloud AI-diensten van derden. Hier maken we ons neuraal netwerk ‘Arduino ready’ en verplaatsen we onze verkeerslichtclassificatiecode naar de wereld van embedded systemen.

Embedded MCU toepassing
Tools en platforms voor machinelearning (ML) lijken als paddenstoelen uit de grond te schieten. Hoe complex uw taak ook is of hoe groot uw dataset ook is, er is een clouddienst die het aankan. Er zijn echter veel gevallen waarin een cloud-gebaseerde ML-implementatie ongeschikt is. Als u met gevoelige of persoonlijke gegevens werkt, wilt u deze misschien niet via het internet verzenden om ze door een ML-tool te laten analyseren. Een ander voorbeeld zijn automotive of andere real-time embedded toepassingen. Dergelijke systemen vereisen een onmiddellijke beslissing, dus de latentie van een internetverbinding, of de mogelijkheid om helemaal geen verbinding te hebben, vereist een lokale ML-oplossing. Dit staat ook bekend als ‘ML on the edge’ [1].

Het werken met een neuraal netwerk on the edge betekent dat zelfs eenvoudige microcontrollers ML-algoritmen kunnen uitvoeren. Vanwege de eisen die training aan een processor stelt, wordt het netwerk echter vaak in de cloud of op een krachtige PC getraind. De resulterende gewichten worden dan naar de microcontroller gedownload voor internet-vrije, low-latency werking.

Dit laatste artikel van de serie zet ons multilayer perceptron (MLP) neurale netwerk over op een Arduino. Gekoppeld aan een RGB sensor, leren we het om de kleuren van verkeerslichten te classificeren zoals we deden in Processing op je PC of laptop. Met behulp van een 32-bit Arduino (DUE of M0 Pro), kunnen we de leerfase op de microcontroller uitvoeren. We zullen echter zien dat dat nogal traag is. Daarom zullen we de taak zo verdelen dat het netwerk wordt getraind met een PC, en vervolgens wordt uitgevoerd in de low-latency, low-power omgeving van een embedded microcontroller applicatie.

Een sensor kiezen
Om de kleuren van de verkeerslichten te herkennen, heeft de Arduino een geschikte inputsensor nodig. De TCS34725 is een geschikte RGB-sensor, kant-en-klaar verkrijgbaar bij Adafruit als een 2 × 2 cm (0.8" × 0.8") formaat printje [2]. Hiermee kunnen we RGB data verzamelen net zoals we eerder deden met de camera en deze toepassen op dezelfde MLP-configuratie die gebruikt werd in de vorige PC-gebaseerde voorbeelden. De print is geschikt voor gebruik met zowel 5 V als 3,3 V Arduino's, en de sensorgegevens worden verkregen met behulp van I2C, waarvoor de Wire-library nodig is.

Om een consistente verlichting van het te analyseren monster te garanderen, bevat het bord ook een witte LED die wordt aangestuurd via een digitale uitgang van Arduino. Pen 10 is voor dit doel geselecteerd (figuur 1). Gelukkig wordt het board ondersteund door een goed geconstrueerde library, zodat de ingebruikname eenvoudig en ongecompliceerd is. Net als voorheen zullen we de code gebruiken uit de GitHub repository die voor deze artikelenreeks is voorbereid [3].
 

Figuur 1: Aansluitschema voor TCS34725 RGB-sensor samen met een Arduino DUE.

Alvorens enige code uit te voeren, moeten we de library voor de RGB-sensor installeren. Dat gaat gelukkig ook gemakkelijk, omdat die toegankelijk is via de Library Manager binnen de Arduino IDE. Selecteer in de menubalk Sketch -> Include Library -> Manage Libraries... en voer dan ‘tcs’ in in het zoekveld van de Library Manager. De ‘Adafruit TCS34725’-library moet nu verschijnen. Klik op ‘Install’ om deze te installeren (figuur 2). Mochten er moeilijkheden zijn, dan kan de broncode en het headerbestand worden gedownload van de Adafruit GitHub repository [4] en handmatig aan de projecten worden toegevoegd.

Figuur 2: Installatie van de Adafruit TCS34725 RGB-sensor software library in de Arduino IDE.

Om er zeker van te zijn om met de sensor de RGB-waarden te verkrijgen die we nodig hebben om de ML te trainen, beginnen we met de sketch arduino/tcsrgbsensor/tcsrgbsensor.ino. Na het initialiseren van de RGB-sensor, zet de code de LED aan en begint met het rapporteren van de RGB-waarden via de seriële uitgang (figuur 3).

Figuur 3: RGB-waarde-uitgangen geleverd door tcsrgbsensor.ino van Arduino.

Open nu Tools -> Serial Monitor om ze te bekijken. De ingestelde baudrate is 9600. Om de kwaliteit van de metingen te verbeteren en de invloed van andere lichtbronnen te verminderen, is het de moeite waard een afscherming rond het sensorboard te maken met een strook zwart karton van ongeveer 3 cm hoog en 10 cm lang (figuur 4). De afscherming zorgt er ook voor dat het beeld van de verkeerslichten op een constante afstand van de RGB-sensor kan worden gehouden.

Figuur 4: TCS34725 RGB-sensor met zwart kartonnen afscherming gemonteerd.

Nu de RGB-sensor betrouwbare resultaten oplevert, kunnen we zijn beoordeling van de rode, oranje en groene kleuren verkrijgen met behulp van ons uitgeprinte beeld van het verkeerslicht (van trafficlight/resources). De door de auteur verkregen resultaten zijn weergegeven in tabel 1.

Tabel 1: RGB-waarden vastgelegd met TCS34725 voor de drie kleuren verkeerslichten.
Tabel 2: RGB-waarden bepaald met TCS34725 voor de 'ongewenste' kleuren.

Een MLP-library voor Arduino

Met de nu bepaalde RGB-waarden, hebben we de neurale netwerkimplementatie nodig voor het Arduino platform. Omdat Processing Java gebruikt, kunnen we niet eenvoudigweg de code van de Neuralclass nemen en deze toevoegen aan een Arduino project. Dus werd de Java Neuralclass licht aangepast om er een C++ class van te maken. In de Arduino-wereld kunnen dergelijke herbruikbare code-objecten worden omgezet in ‘libraries’. Deze bestaan uit een C++ class en een extra bestand voor het markeren van de sleutelwoorden van de class. Mocht u uw eigen library willen schrijven of beter willen begrijpen hoe C++ classes werken op Arduino, dan is er een uitstekende tutorial op de Arduinowebsite [5].

De code voor onze Neural-library kan worden gevonden in arduino/neural. De volgende Arduino-projecten omvatten eenvoudig de broncode van de Neuralclass in de sketch om dingen eenvoudig te houden. Het neural.h headerbestand moet ook worden toegevoegd aan de map waar het project is opgeslagen.

Het gebruik van de Neural klasse op een Arduino is grotendeels hetzelfde als het gebruik ervan in Processing. Het creëren van ons netwerk object als een globale variabele is iets anders en wordt als volgt ondernomen:

Neural network;

Om het object met het gewenste aantal input-, verborgen- en output-knooppunten te construeren, voeren wij het volgende in:

network = new Neural(3,6,4);


De basisconfiguratie van de biaswaarden en de leersnelheid worden vervolgens gecodeerd zoals eerder in Processing:
 

network.setLearningRate(0.5);

network.setBiasInputToHidden(0.35);

network.setBiasHiddenToOutput(0.60);

Vanaf hier kunnen we de methodes blijven gebruiken zoals we ze eerder in Processing hebben gebruikt.

Verkeerslichtkleuren detecteren met Arduino

Nu kunnen we beginnen met het verkennen van de MLP op de Arduino. De sketch /arduino/tlight_detect/tlight_detect.ino volgt dezelfde structuur als het Processingproject tlight_detect.pde. Het neurale netwerk (3/6/4) wordt geconfigureerd vanaf regel 40, en het wordt getraind met de RGB-gegevens in een lus vanaf regel 51. Alvorens de code uit te voeren, moeten de eerder verkregen RGB-waarden voor ‘Rood’, ‘Oranje’ en ‘Groen’ worden ingevoerd vanaf regel 56:

teachRed(220, 56, 8);

teachAmber(216, 130, 11);

teachGreen(123, 150, 128);
 

Upload de code en open de Seriële Monitor om de uitvoer te bekijken (afbeelding 5). Net als voorheen moet de baud-instelling 9600 zijn. Het project controleert of de RGB-sensor functioneert alvorens de witte LED uit te schakelen tijdens het leren. Nadat het MLP is geconfigureerd, wordt de leercyclus 30.000 keer doorlopen, waarbij het vermogen om elk van de drie kleuren te classificeren elke keer wordt verbeterd.

Figuur 5: Uitvoer van tlight_detect.ino tijdens het leren.

Om tijdens het leren enige feedback te geven, wordt om de 1000 luscycli (3000 leerepochs) een punt uitgevoerd. Vergeleken met de PC is leren een langzaam proces. Elke aanroep van een leerfunctie (learnRed(), enz.) vergt ongeveer 5,55 ms om te voltooien. Het leren van alle drie de kleuren duurt ongeveer 8,5 minuten op een Arduino M0 Pro met een SAMD21 microcontroller. Als je de uitvoeringstijd van je platform wilt onderzoeken, vink dan het vakje 'Toon Tijdstempel' aan in de Seriële Monitor en vervang regel 66 door:

Serial.println(".");
 

Hiermee wordt aan elke uitgevoerde punt een carriage return-karakter toe.

Zodra het leren volledig is, vertoont Arduino onmiddellijk zijn nieuwe vaardigheid. Telkens wanneer een verkeerslichtkleur wordt gedetecteerd, wordt het uitgevoerd naar de Seriële Monitor (figuur 6). Tijdens de experimenten van de auteur detecteerde het neurale netwerk ook de kleur ‘Oranje’, zelfs wanneer niets voor de sensor werd gehouden. Hoewel dit verband leek te houden met de omgevingsverlichting, wijst het op een zwak punt in de implementatie.

Figuur 6: Output van tlight_detect.ino na het leren en detecteren van kleuren.

Om de code te verbeteren, kunnen we de MLP 'Andere' kleuren leren, zoals we eerder in Processing hebben gedaan. Dit kan ook worden gebruikt om de ‘Oranje’-classificatie te onderdrukken wanneer er geen beeld aanwezig is. De tcsrgbsensor.ino sketch kan worden gebruikt om de sensormetingen te verkrijgen voor de verkeerslicht surround, frame, en beeld achtergrond. Deze kunnen vervolgens worden ingevoerd in de regels 60 en verder in de tlight_detect.ino sketch in de teachOther()-functie-aanroepen.

De waarden in tabel 2 werden bereikt en getest met de tlight_detect.ino sketch. De classificatie verbeterde, maar de foutieve classificatie van geen enkel beeld als ‘Oranje’ werd niet volledig opgelost. Zoals altijd is er ruimte voor verbetering!

Leren met buitenboord motor

Als je het leren van de 'Andere' kleuren toevoegt aan de Arduino-sketch, moet je op een M0-Pro ongeveer 18 minuten wachten op het leren de gewenste classificaties. Er is dus ruimte voor optimalisatie van het proces. Aangezien wij een krachtige PC hebben die de gewichten in minder dan een seconde kan berekenen, zou het zinvol zijn om het leren daar te doen, en dan de resultaten naar de Arduino over te brengen. Met deze gewichten hebben we ook een middel om meerdere microcontrollers met dezelfde 'kennis' te programmeren. Ervan uitgaande dat de RGB-sensoren allemaal hetzelfde functioneren ten opzichte van onze input, zou elke microcontroller het beeld van het verkeerslicht correct moeten classificeren. Dit is dus wat we nu gaan doen.

We gaan even terug naar Processing om het project /arduino/learnfast/learnfast.pde te openen. De hele toepassing draait in de setup()-functie. Het neurale netwerk is geconfigureerd met dezelfde input, hidden, en output nodes als gebruikt op het Arduinoboard (3/6/4). In de leer-lus (regel 36) worden de waarden gebruikt die zijn verkregen van de Arduino met behulp van de RGB-sensor en de tcsrgbsensor.ino. Wanneer de code wordt uitgevoerd, wordt er tekst naar de console gestuurd. De laatste sectie bevat de code die alle input-to-hidden en hidden-to-output gewichten configureert (figuur 7). Kopieer eenvoudigweg de gegenereerde code vanaf // For Input Node =0 tot het einde van de tekstuitvoer.

Figuur 7: Gewichten kunnen snel op een PC worden berekend met learnfast.pde in Processing.
De uitvoer van de tekstconsole kan dan in tlight_weights.ino worden geplakt.

Terug in de Arduino-IDE kunnen we nu de /arduino/tlight_weights/tlight_weights.ino-sketch openen. Dit is dezelfde als de tlight_detect.ino-sketch, maar in plaats van het neurale netwerk te onderwijzen, worden de gewichten voorgeprogrammeerd. Dit gebeurt op regel 51 met de functie importWeights(). Plak gewoon de code van de learnfast.pde uitvoer in de importWeights()-functie op regel 86 in tlight_weights.ino. Programmeer het Arduino-board, en het zou nauwkeurig de kleuren van de verkeerslichten moeten detecteren zoals voorheen.

In feite, nu we dit leerproces-met-buitenboord-motor hebben, kunnen we zelfs dezelfde tlight_weights.ino-sketch programmeren in een Arduino UNO. Sluit de RGB-sensor aan op het board, open de Seriële Monitor, en het zal net zo nauwkeurig werken als het deed op een Arduino M0 Pro of DUE. Ter vergelijking kun je digitale pin 9 monitoren om te zien hoe lang het duurt voordat de calculateOutput()-methode de berekeningen uitvoert.

Hoe verder? Meer Embedded Systemen?

Dus, hoe gaan we nu verder? Welnu, wij hebben een functioneel MLP neuraal netwerk dat zowel op een PC als op een microcontroller werkt. We hebben ook een superieur leerproces om de gewichten te genereren die nodig zijn in microcontrollertoepassingen. U kunt proberen dit MLP toe te passen op andere taken die te moeilijk zijn om op te lossen met behulp van if-else-statements en vaste limieten. Het is misschien zelfs mogelijk een eenvoudig spraakherkenningsproject uit te voeren om een paar woorden te herkennen. U zou ook het volgende kunnen onderzoeken:
 

  • De Neurale klasse gebruikt het gegevenstype double. Kan het sneller met driver en toch nauwkeurig? Hoeveel sneller?
  • De sigmoid-functie gebruikt de wiskundige functie exp() en berekent de exponentiële verhoging van het doorgegeven argument. Kan de activeringsfunctie worden vereenvoudigd door een benadering te gebruiken en toch een nauwkeurige classificatie opleveren?
  • Als u een poging tot spraakherkenning zou willen doen, hoe zou u dan een stemmonster voorbereiden om het aan deze MLP-implementatie voor te leggen?
  • Hoe zit het met enkele belangrijke veranderingen? Hoe zou je een tweede laag van verborgen nodes implementeren? Kun je een andere activeringsfunctie implementeren?

Betere landbouw

De landbouw heeft altijd vertrouwd op de natuur en de seizoenen om de beste tijd te bepalen om te oogsten en te zaaien. De traditie heeft altijd de optimale datum gedicteerd voor het planten van gewassen om te kunnen profiteren van het moessonseizoen. Maar door de veranderende weerpatronen hebben de oogsten daaronder geleden. Dankzij AI komt daar nu verandering in. Indiase boeren die deelnamen aan een proefproject plantten hun grondnotenteelt eind juni, drie weken later dan normaal. De Microsoft Cortana Intelligence Suite zorgde voor deze begeleiding. Aan de hand van historische klimaatgegevens leidden de aanbevelingen die de boeren kregen tot een gemiddeld 30% hogere opbrengst [6].
 


Vragen over embedded neuronen?

Heeft u vragen of opmerkingen over embedded neuronen, embedded toepassingen, of deze artikelenserie? Stuur dan een e-mail naar de auteur op stuart.cording@elektor.com.

Vertaling: Jelle Aarnoudse