7.1. Che cos’è una rete neurale

Una rete neurale è un algoritmo il cui comportamento viene appreso dagli esempi anziché scritto a mano. La stessa architettura di rete, alimentata con un milione di immagini di volti, impara a rilevare i volti. La stessa architettura, alimentata con un milione di immagini di mani, impara a rilevare le mani. La stessa architettura, alimentata con un insieme etichettato che copre molte categorie di oggetti, impara a rilevarle tutte contemporaneamente. Tra un obiettivo e l’altro cambiano soltanto i pesi, e i pesi sono prodotti da un processo di addestramento esterno che confronta le predizioni della rete con esempi etichettati e regola i pesi finché non corrispondono.

7.1.1. Il meccanismo

Una rete neurale è una pila di strati. Ogni strato moltiplica l’output dello strato precedente per una matrice di pesi, aggiunge un vettore di bias e applica una funzione non lineare al risultato. L’output di uno strato è l’input del successivo. Un’immagine catturata entra in cima alla pila, scorre verso il basso attraverso decine o centinaia di strati ed emerge dal fondo come un tensore le cui voci descrivono ciò che era presente nell’immagine.

Ciò che i pesi di ciascuno strato fanno dipende da ciò su cui la rete è stata addestrata. In una rete di visione, una matrice di pesi di uno strato iniziale potrebbe attivarsi su un breve bordo orizzontale; una leggermente più profonda potrebbe attivarsi su un angolo; una ancora più profonda potrebbe attivarsi su una forma circolare di un occhio; gli strati più profondi potrebbero attivarsi su configurazioni di un volto intero. Nulla di tutto ciò è stato scritto a mano. Il processo di addestramento ha iterato su milioni di esempi etichettati, ha spinto i pesi verso il basso lungo una funzione di perdita, e la gerarchia bordo-poi-angolo-poi-occhio-poi-volto è emersa dai dati.

Una pila verticale di nove riquadri etichettati che rappresentano gli strati di una piccola rete di classificazione. Il riquadro in alto è etichettato "Input image" con una forma del tensore di (192, 192, 3). Una freccia conduce verso il basso a un riquadro "Conv + ReLU" con forma (96, 96, 32). Un'altra freccia conduce a un secondo riquadro "Conv + ReLU" con forma (48, 48, 64). Segue un riquadro "MaxPool" con forma (24, 24, 64). Seguono altri due riquadri "Conv + ReLU" con forme (12, 12, 128) e (6, 6, 256). Un riquadro "Global average pool" ha forma (256,). Un riquadro "Fully connected" ha forma (1000,). Il riquadro in basso è etichettato "Class scores" con forma (1000,). Il flusso del tensore va dall'alto verso il basso.

Una piccola rete di classificazione come pila di strati. Il tensore di input entra in cima con la forma dell’immagine catturata e scorre verso il basso attraverso gli strati, ciascuno dei quali trasforma le dimensioni del tensore. Il tensore di output in fondo ha una voce per ogni classe. Le reti di rilevamento e di keypoint condividono la stessa forma a pila di strati; cambia soltanto l’interpretazione del tensore di output.

L”architettura della rete – come sono disposti gli strati, quali operazioni li collegano – è ciò che la rete può fare. I pesi sono ciò che la rete ha appreso. Il compito della cam in tutto questo è caricare il file dei pesi prodotto dall’addestramento ed eseguire la stessa aritmetica eseguita dall’addestratore, ma sul frame catturato anziché sul set di addestramento.

7.1.2. Cosa viene dato in input, cosa esce in output

Entrambe le estremità della rete sono tensori – array multidimensionali di numeri, lo stesso tipo di oggetto introdotto nel capitolo su numpy. Il tensore di input per una rete di visione è l’immagine catturata riorganizzata nel formato che la rete si aspetta: tipicamente una forma a 4 elementi (B, H, W, C) dove B è la dimensione del batch (sempre 1 sulla cam, poiché viene elaborato un frame alla volta), H e W sono l’altezza e la larghezza in pixel attese dalla rete e C è il numero di canali (3 per una rete RGB, 1 per la scala di grigi).

Il tensore di output dipende dallo scopo della rete:

  • Una rete di classificazione produce un tensore monodimensionale di punteggi di confidenza, uno per classe. L’indice del punteggio più grande è la classe predetta. Il rilevatore di persone derivato da MobileNet che è fornito sulla maggior parte delle cam è di questa forma: due punteggi, uno per «persona», uno per «non persona».

  • Una rete di rilevamento produce un tensore bidimensionale le cui voci descrivono un elenco di bounding box più le probabilità delle classi. YOLOv8 è di questa forma: un tensore (84, N) dove 4 delle 84 righe sono valori di regressione del box e le altre 80 sono probabilità per classe, ripetute su N posizioni di ancoraggio.

  • Una rete di keypoint produce un tensore le cui voci sono le posizioni in pixel di punti di riferimento denominati. Il modello di landmark facciali MediaPipe è di questa forma: 468 keypoint per ogni volto rilevato.

  • Una rete di segmentazione produce un tensore bidimensionale le cui voci sono etichette di classe per pixel – le stesse dimensioni dell’input, con un indice di categoria in ogni posizione.

  • Una rete di regressione produce un singolo numero o un breve vettore di numeri – una stima di profondità, un angolo, una temperatura.

Ogni forma ha il proprio post-processore sulla cam che riconverte il tensore di output grezzo nella forma di risultato utilizzata dal resto dell’applicazione – bounding box, elenchi di keypoint, etichette di classe, stime numeriche. Il post-processore è codice lato applicazione che conosce il formato di output della rete; la rete stessa è soltanto l’aritmetica che produce il tensore.

7.1.3. Perché funziona su una cam

Due elementi aritmetici rendono tutto questo praticabile su un componente di classe microcontrollore. Il primo è la quantizzazione. L’addestramento avviene in aritmetica in virgola mobile a 32 bit; l’inferenza può essere eseguita in aritmetica intera a 8 bit con una perdita di accuratezza quasi nulla per la maggior parte delle reti. I pesi a 8 bit occupano un quarto dello spazio di memorizzazione e vengono eseguiti diverse volte più velocemente dei float a 32 bit. Ogni modello fornito con la cam è già stato quantizzato esternamente.

Il secondo è l”accelerazione hardware. La stessa aritmetica che la CPU di un microcontrollore esegue faticosamente un’istruzione alla volta, un acceleratore per reti neurali la esegue su centinaia di operazioni in una sola volta. Le cam più recenti (la AE3 e la N6) sono dotate di una neural processing unit (NPU) dedicata – un acceleratore di tensori sul SoC – che trasforma un modello che avrebbe impiegato un secondo per essere eseguito sulla CPU in uno che viene eseguito in decine di millisecondi. Il capitolo sui motori di inferenza descrive come si presenta il compito della cam in tutto questo.

7.1.4. Cosa tratta il capitolo

L’addestramento non è compito della cam. Un modello addestrato arriva sulla cam come file .tflite; la cam lo carica, esegue ogni frame catturato attraverso di esso e decodifica il tensore risultante in un risultato su cui l’applicazione può agire. Tutto ciò che segue riguarda ciascuno di questi passaggi:

  • caricare e ispezionare un modello;

  • la partizione flash in cui risiedono i file dei modelli;

  • le quattro fasi di una chiamata di inferenza;

  • i motori che eseguono effettivamente l’aritmetica;

  • e i post-processori che riconvertono un tensore di output in un elenco di box, keypoint o classi.

I rilevatori nel capitolo sull’immagine erano ciascuno definito per un obiettivo specifico. Quelli trattati nel resto di questo capitolo sono invece addestrati a partire dai dati, con lo stesso motore che esegue qualunque modello lo script carichi. Il cambiamento di flusso di lavoro che ne è derivato – un algoritmo specifico per l’obiettivo sostituito da un file di pesi specifico per l’obiettivo – è la prossima cosa da mettere in evidenza.