Introduction
Tulip Vision est une solution de vision par ordinateur sans code pour les opérations en atelier. Elle permet de créer des Tulip Appsqui utilisent la vision par ordinateur pour piloter et surveiller les opérations. Tulip Vision peut être utilisé pour détecter l'activité sur le poste de travail, suivre les objets ainsi que les personnes. Les signaux de vision peuvent être construits pour surveiller la sécurité, les opérations d'assemblage manuel, le kitting et le picking, et de nombreuses autres applications qui augmentent la fiabilité et réduisent les erreurs. Les algorithmes de vision par ordinateur basés sur des réseaux neuronaux profonds sont au cœur de la vision pour l'atelier. Ces algorithmes sont conçus pour fonctionner sur le matériel existant dans les ateliers, qui est souvent un modeste PC fonctionnant sous Windows. Afin d'apporter la toute dernière IA aux ordinateurs sous-puissants des ateliers, nous utilisons la cléIntel Neural Compute Stick version 2 (NCS v2), aussi appelée Movidius Vision Processing Unit (VPU). Il s'agit d'un périphérique USB doté d'un matériel de calcul conçu pour l'exécution de réseaux neuronaux profonds, qui décharge le CPU ou le GPU du PC des tâches arithmétiques. Le NCS est une solution à faible coût et à faible consommation pour l'IA en périphérie, qui est également prête à l'emploi.
Pourquoi l'optimisation est-elle nécessaire ?
Nous avons constaté que le NCS d'Intel était un processeur très performant pour nos besoins à Tulip Vision. Nous nous concentrons sur la détection des humains et de leurs opérations sur la ligne, il est donc important de pouvoir détecter les mains et les personnes dans un flux de caméras entrant. Les derniers modèles de détection humaine utilisent des réseaux neuronaux profonds et des modèles lourds, qui mettent le NCS au défi en termes de performances.
Avec l'exécution à la vanille d'un modèle de détection des mains, nous avons pu atteindre une vitesse de 14 images par seconde (FPS) pour l'inférence. Une certaine optimisation est nécessaire pour atteindre nos objectifs de détection des opérations humaines en temps réel (ce qui est considéré comme 30 images par seconde et plus, soit la vitesse de fonctionnement habituelle de la plupart des caméras). Nous cherchions également à tirer le meilleur parti du matériel NCS, dont le coût est payé d'avance. Les spécifications du NCS prévoient un taux de traitement théorique de 100 GFLOP/s (Giga opérations en virgule flottante par seconde), alors qu'initialement nous n'avons pu obtenir que 20-25 GFLOP/s (avec un réseau de 1,5 GFLOP à 14 FPS) avec une latence considérable.
Dans cet article, nous discutons des techniques d'optimisation que nous avons explorées, et de celle qui a fait la différence pour nous et nous a permis d'atteindre un taux d'inférence en temps réel. Intel a déjà fourni un guide utile sur l'optimisation des réseaux pour le NCSv2, que nous avons utilisé dans notre travail.
Convertir un modèle pour le faire fonctionner sur le SOC
Pour commencer, nous avons obtenu le graphe et les poids d'un réseau de détection des mains. Nous formons nos propres modèles de détection des mains, adaptés aux performances des scènes d'atelier, mais il existe des modèles disponibles gratuitement en ligne qui fonctionnent étonnamment bien. Voici un exemple de modèle sur GitHub que nous avons utilisé pour les tests et les comparaisons de base. Avec un modèle pré-entraîné, on peut vouloir l'affiner pour son objectif et ses données. Nous avons utilisé une suite d'outils de TensorFlow de Google pour tester les techniques de réglage fin et d'apprentissage par transfert.
Pour qu'un modèle donné puisse fonctionner sur le NCS, il doit être converti au bon format. Intel NCS utilise OpenVINO pour développer pour le NCS. Il s'agit d'une boîte à outils très complète qui permet d'exécuter des modèles dans des environnements hétérogènes (par exemple, CPU, GPU, VPU), de convertir de nombreuses architectures sources telles que TensorFlow, ONYX, PyTorch, etc. et d'optimiser les modèles de diverses manières.
Pour convertir un modèle, il doit d'abord être dans un état de graphe gelé. Cela signifie que seules les parties du réseau neuronal nécessaires à l'inférence sont conservées, tandis que tout le reste est éliminé, et que tous les poids du graphe doivent être finalisés. Plusieurs données accompagnant les graphes d'exécution du réseau neuronal sont liées à sa formation, mais ne sont pas nécessaires à l'inférence et peuvent même causer des problèmes lors de la conversion. Pour amener notre modèle de détection des mains à un état de graphe figé, nous utilisons le script suivant :
python3 /content/models/research/object_detection/export_inference_graph.py \ --input_type=image_tensor \ --pipeline_config_path=/path/to/pipeline.config \ --output_directory=/path/to/output_directory \ --trained_checkpoint_prefix=/path/to/model.ckpt-xyz # Remplacez xyz par la valeur de l'étape du point de contrôle.
Figure 1. Script d'exportation du graphe d'inférence pour les modèles formés avec Tensorflow Object Detection API
Pour la conversion, nous utilisons le DL (Deep Learning) Workbench, d'OpenVINO. Il s'installe facilement sur n'importe quel système d'exploitation majeur et fonctionne comme une application graphique autonome (GUI) ou en ligne de commande. Nous nous concentrons ici sur l'utilisation de l'interface graphique pour visualiser nos opérations. OpenVINO fournit un excellent guide de démarrage pour le banc d'essai DL. Sur le banc d'essai DL, nous chargeons le modèle et spécifions les formes des tenseurs d'entrée et de sortie.
Figure 2. Configuration du modèle Intel Deep Learning Workbench
Le banc d'essai dispose également d'outils très utiles pour évaluer l'exécution et les performances du modèle, ainsi que des tests pour s'assurer que le modèle est exploitable sur le SOC en termes de couches NN implémentées.
Figure 3. Benchmarking du modèle sur des données de test (non annotées) en utilisant un CPU Intel i7-8700T
Enfin, le banc d'essai permet de convertir très facilement le modèle au format requis par le SOC :
Figure 4. Téléchargement du modèle OpenVINO converti
Optimiser le modèle pour une inférence rapide
Pour commencer, nous avons utilisé le code d'exemple d'OpenVINO pour la détection d'objets. Il utilise une simple API synchrone qui envoie une demande d'inférence (IR) au NCS et attend (bloque le thread) qu'elle se termine, en supposant que l'exécution du modèle prend simplement un certain temps pour se terminer. Cela nous a donné notre performance initiale décevante d'environ 14 FPS. En faisant le calcul, nous avons compris que cette performance était très inférieure à ce que le NCS est capable de faire.
Nous avons supposé que le modèle était trop grand et que c'était la raison de cette mauvaise performance. Nous avons donc d'abord essayé de réduire la taille de l'image d'entrée du modèle. La théorie en cours était que les grandes couches convolutionnelles initiales sur les grandes tailles d'entrée avant la mise en commun portent une grande partie du poids de calcul. Nous avons modifié la forme de l'image d'entrée en 64x64 et 128x128, par rapport à la taille originale de 224x224. Mais cela a également réduit la précision par une marge importante - ce qui est quelque chose que nous ne pouvons pas accepter.
Figure 5. Diagramme à barres représentant les FPS en fonction de la taille d'entrée du modèle. Tous les modèles sont des modèles SSDLite basés sur Mobilenetv2. Pour mobilenetv2 xy-abc, xy=Multiplicateur de profondeur, abc=Taille d'entrée.
Nous avons également essayé différentes architectures de backbones et de détecteurs, par exemple MobileNet V3, EfficientDet, qui sont disponibles dans le zoo des modèles OpenVINO. Mais nous avons conclu que le compromis vitesse/précision lors de l'inférence sur NCS n'est pas favorable pour notre cas d'utilisation.
Figure 6. Modèle de backbone et d'architecture par rapport au FPS. Tous les backbones Mobilenet utilisent SSDLite comme détecteurs de boîtes.
Stupéfaits par ces résultats, nous avons essayé d'élaguer le modèle. Lors de l'élagage, nous supprimons les parties du modèle qui ne contribuent pas beaucoup à ses performances, en sacrifiant la vitesse à la précision. Nous avons essayé l'élagage de modèle intelligent de Tensorflow, basé sur la recherche de "couches légères". Actuellement, Tensorflow ne prend en charge l'élagage des modèles que pour les modèles séquentiels basés sur Keras et ne prend pas en charge les modèles formés à l'aide de l'API de détection d'objets de Tensorflow. Cela a encore contrarié nos efforts pour créer un modèle élagué léger.
La quantification est un autre angle d'optimisation. Dans la quantification, nous changeons la précision numérique de certaines couches du réseau en un type plus léger et plus rapide. Cela suppose que le matériel d'exécution plus faible, comme les téléphones mobiles, est plus lent à exécuter des opérations arithmétiques en virgule flottante (par exemple, virgule flottante 32 bits, FLOAT32) que des opérations entières (par exemple, entier 8 bits, INT8). C'est l'une des meilleures astuces pour l'optimisation du NN. Cependant, une fois encore, le NCS ne supporte pas les opérations INT8 et nous sommes revenus à la case départ.
Exécution asynchrone
Finalement, après de nombreux essais de techniques d'optimisation, nous avons découvert que nous pouvons simplement ne pas attendre la fin de la requête d'inférence et en exécuter une autre en parallèle en utilisant l'API asynchrone d'OpenVINO (comme décrit dans le guide). Nous pouvons obtenir une autre requête d'inférence pendant que les autres sont encore en cours d'exécution, et la passer dans une autre image pour la détection. Puisque nous avons une capture d'image en temps réel de la caméra, cela introduit un petit décalage dans la sortie mais un très grand gain en vitesse. Le diagramme suivant montre l'avantage du flux IR asynchrone :
En pratique, nous utilisons un pool de 4 demandes d'inférence simultanées. La taille du pool est déterminée par le dispositif d'inférence, c'est-à-dire le NCS. Un CPU aura plus d'IRs que le NCS, et un GPU puissant peut en avoir beaucoup plus encore. Quoi qu'il en soit, si un modèle est gros et donc lent, prenant beaucoup de temps pour compléter la requête, nous pouvons épuiser le pool d'IRs et avoir encore une réduction du framerate.
Évaluation et résultats des performances
Nos principaux paramètres d'évaluation des performances sont le nombre d'images par seconde et la latence. Nous voulons un taux d'images par seconde plus élevé et un temps de latence plus faible, mais avec l'approche API asynchrone, ces deux éléments font l'objet d'un compromis. L'exécution d'un plus grand nombre d'IR simultanés implique une période de préchauffage et une latence plus longues, mais elle permet un temps d'exécution global plus rapide.
Pour mesurer les performances, nous disposons d'outils internes, mais nous avons également utilisé l'outil de benchmark C++ disponible chez OpenVINO. Il est capable d'exécuter les modèles sur le NCS et fournit des statistiques très utiles. Bien qu'il ne s'agisse pas d'une véritable simulation de l'inférence du modèle dans Tulip Vision, il nous a fourni de très bonnes données sans qu'il soit nécessaire d'exécuter le modèle dans notre cadre.
Figure 7. Performance du modèle pour SSDLite MobilenetV2 en utilisant l'API asynchrone et synchrone.
Conclusion
Nous avons trouvé l'Intel NCSv2 et la boîte à outils OpenVINO très utiles pour nos besoins. En plus d'être une plateforme hétérogène pour l'exécution de modèles, fonctionnant sans problème avec le VPU NCS, elle dispose également d'un support assez étendu pour la conversion et le benchmarking et d'outils utiles pour l'optimisation. Nous avons essayé de nombreuses choses avant de trouver l'option d'inférence asynchrone, et nous avons beaucoup appris au cours de ce processus. C'est ainsi que nous fournissons des performances de premier ordre à nos clients en utilisant Tulip Vision à un coût très faible. L'API asynchrone dans OpenVINO a donné la meilleure augmentation de performance par rapport à de nombreuses autres approches traditionnelles dans les astuces d'optimisation de l'inférence de modèle, mais celles-ci peuvent encore s'avérer utiles lorsque nous déployons des modèles plus profonds dans la production de Vision.