Het trainen en laten werken van neurale netwerken voor AI-toepassingen vraagt veel energie. Met de juiste algoritmes kan dit energiegebruik heel aardig worden gereduceerd.
Neurale netwerken worden op talloze plaatsen ingezet. Beeldherkenning, handschriftherkenning, spraakherkenning, zelfrijdende wagens en schrijfhulpmiddelen zijn maar enkele toepassingen van deze alomtegenwoordige technologie.
Steeds grotere modellen
In het domein van natuurlijke taalverwerking (natural language processing, nlp) worden de kosten van het trainen van een neuraal netwerk ieder jaar hoger. Dat heeft vooral te maken met het groeiend aantal parameters in neurale netwerken. Het Israëlische nlp-bedrijf AI21 Labs schatte de kosten van het trainen van een BERT-model van 110 miljoen parameters op een corpus van 15GB uit Wikipedia en boeken op 2500 dollar per run.
Als daarbij wordt meegewogen dat een training doorgaans diverse hyperparameters uitprobeert om de optimale combinatie voor het leeralgoritme te vinden (hyperparameter tuning) en er meerdere runs worden uitgevoerd, is de totale kostprijs gemakkelijk een factor twintig hoger. In ons voorbeeld komt hij dan uit op 50.000 dollar. Daarbij gaat het nog om een relatief klein model. Het trainen van een BERT-model van 1,5 miljard parameters kost volgens AI21 Labs 80.000 dollar per run en in totaal 1,6 miljoen dollar. Bij de grootste modellen van vandaag de dag kost het trainen naar schatting tientallen tot honderden miljoenen dollars.
De kosten rijzen de pan uit
De kosten zijn evenredig met de grootte van het model, en in nlp worden modellen alsmaar groter. Als we kijken naar de GPT-familie (Generative Pre-trained Transformer) van OpenAI, zie je de evolutie duidelijk. Terwijl GPT-1 in 2018 nog 117 miljoen parameters had, deed GPT-2 het in 2019 met 1,5 miljard parameters en gebruikte GPT-3 in 2020 maar liefst 175 miljard parameters. Uit een analyse door OpenAI in 2018 blijkt dat de benodigde rekentijd voor het trainen van de grootste gepubliceerde AI-systemen tussen 2012 en 2018 elke drie tot vier maanden verdubbelde. Dat betekent 300.000 keer meer rekenkracht in zes jaar tijd. Ook recentere studies tonen dat de benodigde rekenkracht om modellen te trainende elke zes maanden verdubbelt.
De kosten om modellen voor AI te trainen nemen exponentieel toe. Bron: OpenAI.
Gewichten en activaties
Voordat we kijken naar mogelijke optimalisaties, moeten we even een stapje terugzetten. Waaruit bestaat een neuraal netwerk en met welke parameters kunnen we het beschrijven? Een (kunstmatig) neuraal netwerk is losjes gebaseerd op de werking van onze hersenen. Neuronen zijn met elkaar verbonden en bootsen de werking na van hun biologische evenknieën, de zenuwcellen. Elke verbinding tussen neuronen heeft een gewicht. Dat kan positief of negatief zijn, wat de invoer een stimulerende respectievelijk remmende invloed geeft. De invoer van een neuron is de som van alle binnenkomende verbindingen, elk vermenigvuldigd met hun gewicht. Een neuron heeft ook een activatiefunctie die wordt toegepast op de invoer. Het resultaat wordt dan weer doorgegeven aan andere neuronen.
In de praktijk werken neurale netwerken in lagen, waarbij neuronen in een laag verbonden zijn met neuronen in de laag ervoor en de laag erna. Er zijn daarbij een invoer- en een uitvoerlaag, met allerlei tussenliggende lagen. We spreken van deep learning als dat aantal lagen groot is. Voor beeldherkenning bijvoorbeeld bestaat de invoerlaag uit de pixels van een foto, terwijl de neuronen in de uitvoerlaag de te herkennen categorieën voorwerpen (kat, hond, tafel, banaan) voorstellen.
Je ziet al onmiddellijk wat je kunt doen om een neuraal netwerk efficiënter te maken. Je kunt ingrijpen op de gewichten, de activatiefunctie, de verbindingen en de lagen. Voor al deze gebieden bestaan er inderdaad optimalisaties.
Een neuraal netwerk bestaat uit een invoerlaag, een of meer verborgen lagen en een uitvoerlaag. Bron: Colin M.L Burnet, CC-BY-SA 3.0.
Bits verminderen
Een veel gebruikte techniek om een neuraal netwerk efficiënter te trainen is transfer learning. Het principe erachter is even logisch als krachtig: in plaats van from scratch een model te trainen, hergebruik je een bestaand model dat is getraind voor een gelijkaardige taak en hertrain je het voor je nieuwe taak op een nieuwe dataset. Frameworks zoals TensorFlow bieden heel wat documentatie aan over hoe je zelf transfer learning toepast.
In de praktijk hergebruik je een groot model dat door een bedrijf zoals Google of Facebook is getraind op een algemene dataset. Denk maar aan de ResNet-netwerken die zijn getraind op miljoenen afbeeldingen uit de database ImageNet, samen met hun labels. Hiermee herken je in afbeeldingen allerlei voorwerpen en dieren, zoals een bierglas, goudvis, haan of auto.
De neuronen in een neuraal netwerk zijn in lagen onderverdeeld, en in een typisch neuraal netwerk herkennen de eerste lagen eigenschappen op detailniveau zoals randen, vormen en schaduwen. Slechts de laatste lagen pikken eigenschappen op hoger niveau op, zoals het hoofd of de staart van een hond of kat. Als je een neuraal netwerk wilt trainen om in een camerabeeld honden van katten te onderscheiden, kun je in een ResNet-netwerk de laatste paar lagen hertrainen op een dataset van foto’s van honden en katten. Alleen van die laatste lagen worden dan de parameters aangepast, wat heel wat sneller, goedkoper en energiezuiniger kan dan een volledig netwerk trainen.
Kwantisatie
Doorgaans zijn de parameters in neurale netwerken, zoals de gewichten van de verbindingen tussen neuronen, 32-bits kommagetallen (float32). Door dit aantal bits te verminderen (kwantisatie), hoeven er minder berekeningen te worden uitgevoerd en is het resulterende model kleiner. In veel gevallen boet het algoritme daarbij niet eens zoveel in aan nauwkeurigheid.
Kwantisatie kun je op twee momenten doen. De eerste mogelijkheid is om dit na de training te doen, met volledige precisie (post-training quantization). Dat maakt de training niet efficiënter, maar het laat wel toe om het herkenningsalgoritme daarna efficiënter uit te voeren, bijvoorbeeld op hardware met minder rekenkracht. De andere optie is om het model al met minder bits te trainen (quantization-aware training), waardoor ook het trainen zelf efficiënter verloopt.
Een eerste stap die je kunt zetten, is overstappen naar 16-bits kommagetallen (float16). Je model is daardoor half zo klein, en het verschil in nauwkeurigheid is volgens cijfers van TensorFlow te verwaarlozen; rond de 0,01% voor MobileNet. Je kunt nog een stap verder gaan, door kommagetallen om te zetten naar gehele getallen; 16-bits (int16) of zelfs 8-bits (int8).
Met die laatste verkrijg je een model dat vier keer kleiner is en twee tot vier keer sneller wordt uitgevoerd op een cpu. Het grootste voordeel is echter dat modellen met 8-bits gehele getallen als parameters heel efficiënt draaien op hardwareversnellers zoals de Edge TPU van Google. De nauwkeurigheid van een model zoals MobileNet vermindert door int8-kwantisatie bovendien maar met 1%. De impact van kwantisatie op de nauwkeurigheid wisselt overigens van model tot model.
Door kwantisatie naar 8-bits gehele getallen kan de Edge TPU van Google neurale netwerken efficiënter uitvoeren. Bron: Coral.
Binaire neurale netwerken
Verminder je het aantal bits nog verder, dan neemt de nauwkeurigheid van je algoritme significant af. Als je de kwantisatie tot in het extreme doortrekt, verminder je het aantal bits van de parameters tot 1. Je werkt dan met binaire waardes die -1 of +1 kunnen zijn. BinaryDenseNet is een voorbeeld van zo’n binair neuraal netwerk. Om het verlies aan informatie door de beperking tot binaire waardes te compenseren, voegt BinaryDenseNet extra verbindingen tussen de neuronen toe.
De uitvinders van BinaryDenseNet vergeleken de prestaties met ResNet-18, dat met float32-getallen werkt. Dat model is 46,8MB groot en haalt een nauwkeurigheid van 69,3% bij het classificeren van afbeeldingen. BinaryDenseNet45 (met 45 lagen neuronen) is maar 7,4MB groot en haalt een nauwkeurigheid van 63,7% op dezelfde taak. Maak je de netwerken nog kleiner, dan heb je een model van 5,1MB groot en 62,5% nauwkeurigheid (BinaryDenseNet37) of een model van 4,0MB groot en 60,7% nauwkeurigheid (BinaryDenseNet28).
Over het algemeen kun je met een binair neuraal netwerk het energiegebruik met een factor tien tot twintig verlagen tegen de kostprijs van vijf tot tien procentpunt minder nauwkeurigheid. Of die winst in energiegebruik opweegt tegen de lagere nauwkeurigheid, hangt van de toepassing af. Als een apparaat met weinig resources hierdoor voor het eerst een neuraal netwerk kan draaien, kan het de moeite zijn.
CORDS (COResets and Data Subset selection) traint een model op een optimaal geselecteerde deelverzameling. Bron: DECILE.
Op je gewicht letten
Terwijl kwantisatie de parameters optimaliseert, kun je ook het aantal parameters verkleinen. Die techniek heet weight pruning. Door de gewichten van verbindingen met kleine waarden op 0 te zetten, verwijder je die gewichten. Ze wogen sowieso al niet veel door in de berekeningen, en met deze optimalisatie verwijder je ze dus helemaal. Dat maakt het model kleiner en reduceert het aantal benodigde berekeningen. Je kunt in het hele model kleine gewichten op 0 zetten, of je kunt dit beperken tot specifieke lagen. Doe je dat laatste, dan kun je experimenteren om te zien in welke lagen dat het beste resultaat geeft.
Een andere techniek is weight clustering. Daarbij worden gelijkaardige waarden van gewichten in een laag vervangen door hun gemiddelde. Al die gewichten die dan dezelfde waarde krijgen, worden een cluster genoemd. Je kunt met het aantal clusters kiezen hoeveel je model wordt verkleind. Elk gewicht hoeft nu niet meer als een float32-getal te worden opgeslagen, maar kan volstaan met de index van de clusterwaarde. Die clusterwaarden hoeven dan maar één keer in een afzonderlijke tabel te worden opgeslagen. Door de herhaling van de index kunnen compressiealgoritmen het modelbestand gemakkelijker comprimeren. Een TensorFlow Lite-model kan met weight clustering in gecomprimeerde vorm tot zes maal kleiner worden dan het originele gecomprimeerde model, met - afhankelijk van het model - tot 5% verlies aan nauwkeurigheid.
Met de TensorFlow Model Optimization Toolkit vervang je gewichten van een neuraal netwerk eenvoudig door beter comprimeerbare clusterwaarden. Bron: TensorFlow.
Optimalisaties combineren
Zo zijn er diverse optimalisaties voor neurale netwerken ontwikkeld, en vele daarvan kun je combineren. Maar dat één optimalisatie het algoritme twee keer sneller maakt en een tweede optimalisatie het algoritme drie keer sneller maakt, betekent nog niet dat de combinatie zes keer sneller is. Beide methoden kunnen immers deels hetzelfde deel van het trainingsproces optimaliseren.
Start-up MosaicML introduceerde daarom vorig jaar zijn opensource-bibliotheek Composer. Dit is een Python-bibliotheek voor het framework PyTorch dat meer dan twintig van die optimalisatiemethoden heeft geïmplementeerd voor neurale netwerken in computervisie en taalmodellering. De naam Composer is gebaseerd op het feit dat je met deze bibliotheek eenvoudig al die methoden kunt combineren.
De onderzoekers van MosaicML hebben zelf ook uitgezocht welke combinatie van optimalisatiemethoden goed bij elkaar passen voor enkele populaire neurale netwerken. Zo kun je met een combinatie van zes methoden ResNet-101 drie en een half keer sneller uitvoeren, melden de ontwikkelaars op de GitHub-pagina van Composer. In de MosaicML Explorer kun je zelf uitzoeken met welke combinatie van methoden je het goedkoopste, beste of snelste model verkrijgt zonder aan nauwkeurigheid in te boeten.
In MosaicML Explorer kun je zelf uitzoeken welke combinatie van optimalisatiemethoden het goedkoopst, snelst of nauwkeurigst is. Bron: MosaicML.
Trainen op deelverzamelingen
Voor een andere aanpak wordt gekozen in het project Cords van het onderzoeksteam Decile, dat zich toespitst op het efficiënter leren met minder data. Cords staat voor COResets and Data Subset selection. Met deze techniek wordt van de data een deelverzameling genomen die een soort samenvatting van de hele dataset is. Door vervolgens je model te gaan trainen op de kleinere dataset, verloopt dit veel sneller.
Dit werkt natuurlijk niet zomaar met elke willekeurige deelverzameling. Het idee achter Cords is dan ook om met allerlei dataselectie-strategieën een deelverzameling te kiezen die zoveel mogelijk op de volledige dataset lijkt. Op die manier slaagden de onderzoekers erin om een model voor beeldherkenning op basis van 10% van de Cifar-10-dataset te trainen, met een zes keer zo hoge snelheid en een verlies van slechts 3% aan nauwkeurigheid.
Sneller data laden
Ook zonder je neurale netwerk of de dataset zelf te veranderen, zijn er nog veel optimalisaties mogelijk. Een belangrijke bottleneck is vaak het inladen van de data uit het ram of de opslag. FFCV (Fast Forward Computer Vision) pakt deze bottlenecks aan om de datadoorvoersnelheid tijdens het trainen van een model te verhogen.
Het enige dat je hoeft te doen om de snelheidswinst van FCCV te verkrijgen, is je dataset naar het fccv-formaat om te zetten en je data loader te vervangen door die van FCCV. Het trainen verloopt daarna met exact dezelfde code. FCCV handelt automatisch het lezen, de pre-fetching, de caching en de overdracht van data tussen apparaten op een efficiënte manier af.
De ontwikkelaars van FCCV focussen op computervisie. Je vindt dan ook benchmarks met een tot tien keer snellere training van ResNet dan met de standaard PyTorch-code. De optimalisaties zijn echter algemeen genoeg om ervoor te zorgen dat ook netwerken in andere domeinen ermee zijn te optimaliseren.
TinyML
We hebben het tot nu toe vooral over het optimaliseren van de training van neurale netwerken gehad, maar ook het uitvoeren van die netwerken kan efficiënter. Een aanpak die de laatste jaren furore heeft gemaakt, is TinyML. De bedoeling van deze vorm van machinelearning is om modellen op apparaten met weinig resources te draaien, zoals een smartwatch of zelfs een microcontroller. Vaak gaat het om apparaten die op batterijen werken en dus zo min mogelijk energie mogen gebruiken.
Een populair framework voor TinyML is TensorFlow Lite, dat ook op singleboard-computers zoals een Raspberry Pi draait. Er is een nog zuinigere versie, TensorFlow Lite for Microcontrollers, die zelfs in de 16KB van een Arm Cortex M3 past. Dit framework werkt onder andere op een Arduino Nano 33 BLE Sense of een Espressif ESP-EYE. TensorFlow Lite en zijn kleinere broertje realiseren hun efficiëntie door kleinere modellen te gebruiken en die te combineren met optimalisaties van berekeningen en geheugengebruik.
Afnemende meeropbrengsten
Er zijn dus al veel optimalisaties mogelijk om de CO₂-uitstoot en kosten van het trainen van een model voor machinelearning te verminderen. De AI-gemeenschap focust zich echter nog altijd louter op de prestaties. In leaderboards van het Allen Institute for AI en andere klassementen worden modellen per toepassing gerangschikt op basis van hun nauwkeurigheid. Andere overwegingen, zoals kosten, efficiëntie en CO₂-uitstoot zijn helemaal geen criteria om hoog te kunnen scoren. Als die prestigieuze klassementen zich op één aspect richten, is het logisch dat onderzoekers er alles aan doen om zo hoog mogelijk op dat aspect te scoren. Een onderzoeker die een model ontwikkelt dat tien keer minder energie gebruikt dan de nummer 1 op de lijst maar 3% minder nauwkeurig is, zal daar geen eer uit halen.
Onderzoekers van ditzelfde Allen Institute for AI stelden al in 2019 voor om onderzoek naar groene AI te stimuleren door de efficiëntie van een algoritme mee te nemen als evaluatiecriterium voor de publicatie van AI-papers. Zij wezen erop dat voor een lineaire verbetering in nauwkeurigheid een exponentieel groter model nodig is. Gelijkaardige relaties vind je tussen de nauwkeurigheid en de hoeveelheid trainingsdata, tussen de nauwkeurigheid en het aantal benodigde experimenten voor hyperparameter-tuning, of tussen de nauwkeurigheid en het aantal benodigde berekeningen. Zo haalt ResNext een 0,5% hogere nauwkeurigheid dan ResNet, maar heeft het daarvoor 35% meer floating-point operations nodig. Dit is duidelijk een voorbeeld van afnemende meeropbrengsten.
Je kunt dan ook de vraag stellen of het nog wel verantwoord is om die steeds kleiner wordende verbeteringen van fracties van een procent nog na te jagen als het elke keer zoveel extra kost. Vanaf welk punt kun je zeggen dat het sop de kool niet meer waard is?
Papers op AI-conferenties richten zich voornamelijk op nauwkeurigheid en veel minder op efficiëntie. Bron: Roy Schwartz, Jesse Dodge, Noah A. Smith, Oren Etzioni, “Green AI”.
Leuk artikel, al moet je wel wat achtergrond op dit vlak hebben.
Zelf heb ik wel complexe modellen gemaakt die zichzelf wat bij kunnen sturen. Dat krijgt tegenwoordig al snel de naam AI, maar de lerende kant is daarvoor te beperkt. In veel van dat soort modellen zitten "constanten" die zo nu en dan iets bijgesteld moeten worden.
De generatie programmeurs die nog op langzame computers met weinig geheugen moesten werken en op elke byte moesten bezuinigen om iets op een computer gedaan te krijgen, is helaas aan het uitsterven. Toch was dat de manier om modellen heel efficiënt te bouwen en toch redelijk accuraat te krijgen.
Nu gebruikt men gewoon wat men ter beschikking heeft en is bezuinigen op benodigde resources niet meer nodig om een model (AI) te bouwen. Eigenlijk kan je nu onbeperkt parameters toevoegen en die in de hoogst mogelijke resolutie verwerken. Het zou goed zijn dat de AI ontwikkelaars ook bewust worden gemaakt van het gebruik van resources (inclusief energie) en gaan kijken of resoluties niet teruggebracht kunnen worden (van 64bit tot 32, 16, 8 bit of indexen). Een grafiek die de nauwkeurigheid uitzet tegen de gebruikte resources is daarbij inderdaad heel nuttig. Helaas wordt dat vaak in een laat stadium gedaan en wordt tegenwoordig niet heel serieus genomen. De modellen werken immers goed en bezuinigingen kunnen ook leiden tot (veel) minder functioneren en wellicht mindere geschiktheid voor hergebruik. Bovendien wordt het model als "af" gezien. Voor een verbetering van de prestatie kan men altijd meer resources inzetten.
In de oude praktijk moest je onderdelen van modellen al gaan optimaliseren omdat je anders later in de knoop kon komen. De meeste hier genoemde technieken werden daarbij ook gebruikt. Het zou heel goed zijn als ook de huidige AI ontwikkelaars deze technieken weer volop gaan gebruiken en de uiteindelijke modellen met de helft van de resources (of minder) kunnen gaan werken. Angsten voor verminderde prestatie of herbruikbaarheid zijn in het verleden zelden bevestigd.
Twee leuke punten heb je.
Inderdaad krijgt iets tegenwoordig snel de term AI (KI in het Nederlands), terwijl het naar mijn mening een geavanceerde routine is eerder dan intelligentie.
En de vergelijking met de code tovenaars van voeger die met trucjes zoals de achtergrond spiegelen of een level achterstevoren spelen, zo toch alles in dat kleine stukje geheugen kwijt konden.
Maar hier is wel een kritisch verschil en meteen ook een vraag.
Hoever kunnen wij nu inschatten hoeveel het zal kosten om te leren een auto of telefoon te herkennen?
Ook is de onzekerheid (vanwege ruis en/of false-positive) aanwezig dan een gewone applicatie op C64 of NES.
Inschattingen maken voor de toekomst is haast niet te doen. Een telefoon van 25 jaar geleden bestond nog uit een telefoon met draaischijf of toetsen en een hoorn met daartussen een krulsnoer. Dat herkennen is niet zo moeilijk. Diezelfde routine zal de huidige mobiele telefoons absoluut niet herkennen als telefoon.
Een auto herkennen als de software al weet waar wegen en parkeerplaatsen zijn is ook gemakkelijk, maar een zelfde auto als auto op het strand herkennen is een stuk lastiger, zeker als er ook (omgewaaide) kliko's staan.
Op een oude C64 zullen zaken als object herkenning lastig zijn. Het geheugen is domweg te klein om een compleet beeld te kunnen bevatten. Met een Arduino of Raspberry Pico kan ik met een 2 MP camera of een lidar wel een heel eind komen.
Ik bedoelde C64 apsoluut als device om vision reconigion op te doen.
Alleen maar om maar aan te geven hoe efficent programmeurs daarop moesten zijn.
Excuus voor dat misverstand.
De generatie programmeurs die nog op langzame computers met weinig geheugen moesten werken en op elke byte moesten bezuinigen om iets op een computer gedaan te krijgen, is helaas aan het uitsterven.
Ik denk dat je hier gelijk in hebt. Er is ondertussen echter ook een andere beweging in opkomst, namelijk zij die embedded systems leren programmeren. Tegenwoordig wordt je als middelbare scholier met een NT profiel al in contact gebracht met microcontrollers als die van Arduino. Technische hbo opleidingen gaan daar nog wel eens een stapje verder in met andere MCUs die net iets meer kunnen.
Wat naar mijn idee ook meespeelt in deze trend van toenemende inefficiëntie, zijn de programmeertalen die aangeleerd worden en in de industrie leidend zijn. Python (vanilla) is gigantisch inefficiënt, maar erg makkelijk voor heel veel doeleinden. Je hoeft bijvoorbeeld bijna nooit na te denken over data types en precision, wat in C standaard wel moet. En ondanks dat er veel packages zijn die die efficiëntie kunnen opkrikken, stimuleren ze efficiënt programmeren niet. Misschien komt het doordat ik een achtergrond heb in embedded systems en C, maar ik vraag me nog steeds constant af hoe mijn code het meest efficiënt en het snelste draait, ongeacht of ik in Python, Java of wat dan ook werk.
De moderne talen zijn gemakkelijk te leren, maar wat mij betreft zijn die talen niet echt geschikt om AI mee te schrijven. Ze zijn dermate inefficiënt dat alleen overschakelen naar C een routine twee à drie keer zo snel kan maken. In C kan je ook het geheugen veel beter beheren door bijvoorbeeld (tijdelijke) data die niet meer nodig is uit het geheugen te gooien.
Die kleine computertjes als Arduino en Raspberry zijn eigenlijk ideaal om AI op te leren programmeren. Als je handig kan programmeren, kan je zelfs die kleine dingen behoorlijk veel laten doen.
Jep, dat ben ik met je eens. Zou mooi zijn als we binnenkort een samenwerking zien tussen bijvoorbeeld Texas Instruments en Mythic AI, met als resultaat een microcontroller bordje met een analog matrix processor chip erop.
Maar goed ik denk dat er in de toekomst zeker meer aandacht zal zijn voor het efficiënt trainen en draaien van AI modellen. Nu al ervaren we de limiet van onze energieopwekking. Dat, ervaren als oplopende kosten per kWh, zal als gevolg hebben dat efficiëntie het nieuwe domein wordt wat onderzoekers gaan uitputten (i.p.v. hoe groot en sterk kunnen we het maken).
Hogere prijzen voor fossiele brandstoffen hebben zo ook een voordeel. Ook met duurzame energie moeten we overigens opletten dat we niet te veel warmte direct in de atmosfeer gaan pompen, anders levert de CO2 besparing nog niets op.
Interresant artikel, dank! Ik hoop dat 't Allen Institute for AI met z'n tijd meegaat en inderdaad een efficienty-eis of score gaat gebruiken bij het bepalen of tonen van scores op de ranglijst!