7.1. Vad är ett neuronnät

Ett neuronnät är en algoritm vars beteende lärs in från exempel i stället för att kodas för hand. Samma nätverksarkitektur lär sig att detektera ansikten om den får en miljon ansiktsbilder. Samma arkitektur lär sig att detektera händer om den får en miljon handbilder. Samma arkitektur lär sig att detektera dem allihop på en gång om den får en etiketterad uppsättning som täcker många objektkategorier. Endast vikterna ändras mellan olika mål, och vikterna produceras av en träningsprocess utanför enheten som jämför nätverkets förutsägelser med etiketterade exempel och justerar vikterna tills de stämmer överens.

7.1.1. Mekanismen

Ett neuronnät är en stapel av lager. Varje lager multiplicerar det föregående lagrets utdata med en matris av vikter, adderar en biasvektor och tillämpar en icke-linjär funktion på resultatet. Utdatan från ett lager är indata till nästa. En infångad bild kommer in högst upp i stapeln, flödar nedåt genom tiotals eller hundratals lager och kommer ut längst ned som en tensor vars element beskriver vad som fanns i bilden.

Vad varje lagers vikter gör beror på vad nätverket tränades på. En viktmatris i ett tidigt lager i ett synnätverk kan aktiveras på en kort horisontell kant; en något djupare kan aktiveras på ett hörn; en djupare kan aktiveras på en cirkulär ögonform; de djupaste lagren kan aktiveras på hela ansiktskonfigurationer. Inget av detta skrevs för hand. Träningsprocessen itererade över miljontals etiketterade exempel, knuffade vikterna nedför en förlustfunktion, och hierarkin kant-sedan-hörn-sedan-öga-sedan-ansikte föll ut ur datan.

En lodrät stapel av nio etiketterade rutor som representerar lagren i ett litet klassificeringsnätverk. Den översta rutan är etiketterad "Input image" med en tensorform (192, 192, 3). En pil leder nedåt till en "Conv + ReLU"-ruta med formen (96, 96, 32). En annan pil leder till en andra "Conv + ReLU"- ruta med formen (48, 48, 64). En "MaxPool"-ruta följer med formen (24, 24, 64). Ytterligare två "Conv + ReLU"-rutor följer med formerna (12, 12, 128) och (6, 6, 256). En "Global average pool"-ruta har formen (256,). En "Fully connected"-ruta har formen (1000,). Den nedersta rutan är etiketterad "Class scores" med formen (1000,). Tensorflödet går uppifrån och ned.

Ett litet klassificeringsnätverk som en stapel av lager. Indatatensorn kommer in högst upp med den infångade bildens form och flödar nedåt genom lagren, där vart och ett transformerar tensorns dimensioner. Utdatatensorn längst ned har ett element per klass. Detekterings- och nyckelpunktsnätverk delar samma form med en stapel av lager; endast tolkningen av utdatatensorn ändras.

Nätverkets arkitektur – hur lagren är ordnade, vilka operationer som kopplar samman dem – är vad nätverket kan göra. Vikterna är vad nätverket har lärt sig. Kamerans del av detta är att ladda viktfilen som producerats av träningen och köra samma aritmetik som tränaren körde, men på den infångade bildrutan i stället för på träningsmängden.

7.1.2. Vad som matas in, vad som kommer ut

Båda ändarna av nätverket är tensorer – flerdimensionella talmatriser, samma sorts objekt som numpy-kapitlet just introducerade. Indatatensorn för ett synnätverk är den infångade bilden omorganiserad till den layout nätverket förväntar sig: typiskt en 4-tupelform (B, H, W, C) där B är batchdimensionen (alltid 1 på kameran, eftersom en bildruta bearbetas i taget), H och W är nätverkets förväntade höjd och bredd i pixlar, och C är antalet kanaler (3 för ett RGB-nätverk, 1 för gråskala).

Utdatatensorn beror på vad nätverket är till för:

  • Ett klassificeringsnätverk producerar en 1-D-tensor av konfidenspoäng, en per klass. Indexet för den högsta poängen är den förutsagda klassen. MobileNet-härledda persondetektorn som levereras med de flesta kameror har denna form: två poäng, en för ”person”, en för ”inte person”.

  • Ett detekteringsnätverk producerar en 2-D-tensor vars element beskriver en lista med begränsningsrutor plus klassannolikheter. YOLOv8 har denna form: en (84, N)-tensor där 4 av de 84 raderna är värden för boxregression och de andra 80 är klassvisa sannolikheter, upprepade över N ankarpositioner.

  • Ett nyckelpunktsnätverk producerar en tensor vars element är pixelpositioner för namngivna landmärken. MediaPipe-modellen för ansiktslandmärken har denna form: 468 nyckelpunkter per detekterat ansikte.

  • Ett segmenteringsnätverk producerar en 2-D-tensor vars element är klassetiketter per pixel – samma dimensioner som indatan, med ett kategoriindex på varje position.

  • Ett regressionsnätverk producerar ett enda tal eller en kort vektor av tal – en djupuppskattning, en vinkel, en temperatur.

Varje form har sin egen efterbehandlare på kameran som konverterar den råa utdatatensorn tillbaka till den resultatform som resten av applikationen använder – begränsningsrutor, nyckelpunktslistor, klassetiketter, numeriska uppskattningar. Efterbehandlaren är kod på applikationssidan som känner till nätverkets utdatalayout; nätverket självt är bara aritmetiken som producerar tensorn.

7.1.3. Varför detta fungerar på en kamera

Två aritmetiska delar gör detta praktiskt genomförbart för en del i mikrokontrollerklass. Den första är kvantisering. Träning sker i 32-bitars flyttalsaritmetik; inferens kan köras i 8-bitars heltalsaritmetik med nästan ingen noggrannhetsförlust för de flesta nätverk. Åttabitars vikter tar en fjärdedel av lagringsutrymmet och körs flera gånger snabbare än 32-bitars flyttal. Varje modell som kameran levereras med har redan kvantiserats utanför enheten.

Den andra är hårdvaruacceleration. Samma aritmetik som en mikrokontrollers CPU traskar igenom en instruktion i taget kör en neuronnätsaccelerator hundratals operationer samtidigt. De nyare kamerorna (AE3 och N6) bär en dedikerad neural bearbetningsenhet (NPU) – en tensoraccelerator på SoC:n – som förvandlar en modell som skulle ha tagit en sekund att köra på CPU:n till en som körs på tiotals millisekunder. Kapitlet om inferensmotorer beskriver hur kamerans del av detta ser ut.

7.1.4. Vad kapitlet täcker

Träning är inte kamerans uppgift. En tränad modell anländer till kameran som en .tflite-fil; kameran laddar den, kör varje infångad bildruta genom den och avkodar den resulterande tensorn till ett resultat som applikationen kan agera på. Allt som följer handlar om vart och ett av dessa steg:

  • att ladda och inspektera en modell;

  • flashpartitionen där modellfiler lagras;

  • de fyra stegen i ett inferensanrop;

  • motorerna som faktiskt utför aritmetiken;

  • och efterbehandlarna som omvandlar en utdatatensor tillbaka till en lista med rutor, nyckelpunkter eller klasser.

Detektorerna i bildkapitlet var var och en avgränsade till ett särskilt mål. De som resten av detta kapitel täcker tränas i stället från data, med samma motor som kör vilken modell skriptet än laddar. Arbetsflödesförändringen som kom med dem – en målspecifik algoritm ersatt av en målspecifik viktfil – är nästa sak att belysa.