7.1. Qu’est-ce qu’un réseau de neurones

Un réseau de neurones est un algorithme dont le comportement est appris à partir d’exemples plutôt que codé à la main. La même architecture de réseau, alimentée par un million d’images de visages, apprend à détecter des visages. La même architecture, alimentée par un million d’images de mains, apprend à détecter des mains. La même architecture, alimentée par un jeu de données étiqueté couvrant de nombreuses catégories d’objets, apprend à les détecter toutes à la fois. Seuls les poids changent d’une cible à l’autre, et ces poids sont produits par un processus d’entraînement hors carte qui compare les prédictions du réseau à des exemples étiquetés et ajuste les poids jusqu’à ce qu’ils correspondent.

7.1.1. Le mécanisme

Un réseau de neurones est une pile de couches. Chaque couche multiplie la sortie de la couche précédente par une matrice de poids, ajoute un vecteur de biais et applique une fonction non linéaire au résultat. La sortie d’une couche est l’entrée de la suivante. Une image capturée entre en haut de la pile, descend à travers des dizaines ou des centaines de couches et ressort en bas sous la forme d’un tenseur dont les éléments décrivent ce que contenait l’image.

Ce que font les poids de chaque couche dépend de ce sur quoi le réseau a été entraîné. Dans un réseau de vision, une matrice de poids des premières couches peut s’activer sur un court contour (arête) horizontal ; une couche un peu plus profonde peut s’activer sur un coin ; une couche encore plus profonde peut s’activer sur une forme d’œil circulaire ; les couches les plus profondes peuvent s’activer sur des agencements de visage entier. Rien de tout cela n’a été écrit à la main. Le processus d’entraînement a itéré sur des millions d’exemples étiquetés, a déplacé les poids vers le bas d’une fonction de perte, et la hiérarchie contour-puis-coin-puis-œil-puis-visage a émergé des données.

Une pile verticale de neuf cases étiquetées représentant les couches d'un petit réseau de classification. La case du haut est étiquetée « Input image » avec une forme de tenseur de (192, 192, 3). Une flèche descend vers une case « Conv + ReLU » de forme (96, 96, 32). Une autre flèche mène à une seconde case « Conv + ReLU » de forme (48, 48, 64). Une case « MaxPool » suit avec une forme (24, 24, 64). Deux autres cases « Conv + ReLU » suivent avec les formes (12, 12, 128) et (6, 6, 256). Une case « Global average pool » a une forme (256,). Une case « Fully connected » a une forme (1000,). La case du bas est étiquetée « Class scores » avec une forme (1000,). Le flux du tenseur va de haut en bas.

Un petit réseau de classification sous forme de pile de couches. Le tenseur d’entrée entre en haut avec la forme de l’image capturée et descend à travers les couches, chacune transformant les dimensions du tenseur. Le tenseur de sortie en bas comporte un élément par classe. Les réseaux de détection et de points clés partagent la même forme de pile de couches ; seule l’interprétation du tenseur de sortie change.

L”architecture du réseau – la façon dont les couches sont agencées, les opérations qui les relient – est ce que le réseau peut faire. Les poids sont ce que le réseau a appris. Le rôle de la caméra est de charger le fichier de poids produit par l’entraînement et d’exécuter le même calcul que l’entraîneur, mais sur la trame capturée plutôt que sur le jeu d’entraînement.

7.1.2. Ce qui entre, ce qui sort

Les deux extrémités du réseau sont des tenseurs – des tableaux multidimensionnels de nombres, le même type d’objet que celui que le chapitre sur numpy vient d’introduire. Le tenseur d’entrée d’un réseau de vision est l’image capturée réorganisée selon la disposition attendue par le réseau : typiquement une forme à 4 éléments (B, H, W, C)B est la dimension du lot (toujours 1 sur la caméra, puisqu’une seule trame est traitée à la fois), H et W sont la hauteur et la largeur en pixels attendues par le réseau, et C est le nombre de canaux (3 pour un réseau RGB, 1 pour les niveaux de gris).

Le tenseur de sortie dépend de l’objectif du réseau :

  • Un réseau de classification produit un tenseur 1-D de scores de confiance, un par classe. L’indice du score le plus élevé est la classe prédite. Le détecteur de personnes dérivé de MobileNet livré sur la plupart des caméras est de cette forme : deux scores, un pour « personne », un pour « pas une personne ».

  • Un réseau de détection produit un tenseur 2-D dont les éléments décrivent une liste de boîtes englobantes ainsi que des probabilités de classe. YOLOv8 est de cette forme : un tenseur (84, N) où 4 des 84 lignes sont des valeurs de régression de boîte et les 80 autres sont des probabilités par classe, répétées à travers N positions d’ancrage.

  • Un réseau de points clés produit un tenseur dont les éléments sont les positions en pixels de repères nommés. Le modèle MediaPipe de repères faciaux est de cette forme : 468 points clés par visage détecté.

  • Un réseau de segmentation produit un tenseur 2-D dont les éléments sont des étiquettes de classe par pixel – les mêmes dimensions que l’entrée, avec un indice de catégorie à chaque position.

  • Un réseau de régression produit un seul nombre ou un court vecteur de nombres – une estimation de profondeur, un angle, une température.

Chaque forme a son propre post-processeur sur la caméra qui convertit le tenseur de sortie brut en la forme de résultat utilisée par le reste de l’application – boîtes englobantes, listes de points clés, étiquettes de classe, estimations numériques. Le post-processeur est du code côté application qui connaît la disposition de sortie du réseau ; le réseau lui-même n’est que le calcul qui produit le tenseur.

7.1.3. Pourquoi cela fonctionne sur une caméra

Deux éléments de calcul rendent cela réalisable pour un composant de classe microcontrôleur. Le premier est la quantification. L’entraînement se fait en arithmétique à virgule flottante 32 bits ; l’inférence peut s’exécuter en arithmétique entière 8 bits avec presque aucune perte de précision pour la plupart des réseaux. Les poids 8 bits occupent un quart du stockage et s’exécutent plusieurs fois plus vite que les flottants 32 bits. Chaque modèle livré avec la caméra a déjà été quantifié hors carte.

Le second est l”accélération matérielle. Le même calcul qu’un processeur de microcontrôleur effectue péniblement une instruction à la fois, un accélérateur de réseau de neurones exécute des centaines d’opérations simultanément. Les caméras plus récentes (l’AE3 et la N6) embarquent une unité de traitement neuronal dédiée (NPU) – un accélérateur de tenseurs sur le SoC – qui transforme un modèle qui aurait mis une seconde à s’exécuter sur le CPU en un modèle qui s’exécute en quelques dizaines de millisecondes. Le chapitre sur les moteurs d’inférence couvre à quoi ressemble le rôle de la caméra dans ce domaine.

7.1.4. Ce que couvre le chapitre

L’entraînement n’est pas le rôle de la caméra. Un modèle entraîné arrive sur la caméra sous la forme d’un fichier .tflite ; la caméra le charge, fait passer chaque trame capturée à travers lui et décode le tenseur résultant en un résultat sur lequel l’application peut agir. Tout ce qui suit concerne chacune de ces étapes :

  • le chargement et l’inspection d’un modèle ;

  • la partition de mémoire flash où résident les fichiers de modèle ;

  • les quatre étapes d’un appel d’inférence ;

  • les moteurs qui effectuent réellement le calcul ;

  • et les post-processeurs qui transforment un tenseur de sortie en une liste de boîtes, de points clés ou de classes.

Les détecteurs du chapitre sur l’image étaient chacun limités à une cible particulière. Ceux que couvre le reste de ce chapitre sont plutôt entraînés à partir de données, le même moteur exécutant quel que soit le modèle que le script charge. Le changement de flux de travail qui les a accompagnés – un algorithme spécifique à une cible remplacé par un fichier de poids spécifique à une cible – est la prochaine chose à mettre en évidence.