Einführung
Tulip Vision ist eine no-code Computervision Lösung für dieArbeit in der Werkstatt. Sie ermöglicht die Erstellung von Tulip Apps , die Computervision zur Steuerung und Überwachung von Vorgängen verwendet. Tulip Vision kann zur Erkennung von Aktivitäten am Arbeitsplatz, zur Verfolgung von Objekten und Personen eingesetzt werden. Die Bildverarbeitungssignale können zur Überwachung der Sicherheit, der manuellen Montage Operationen, des Kitting und der Kommissionierung und vieler anderer Anwendungen eingesetzt werden, die die Zuverlässigkeit erhöhen und die Fehlerquote senken. Im Mittelpunkt von Vision for the shop-floor stehen Computervision Algorithmen, die auf tiefen neuronalen Netzen basieren. Die Algorithmen sind so konzipiert, dass sie auf der vorhandenen Hardware in den Werkshallen laufen, bei der es sich oft um einen einfachen PC mit Windows handelt. Um die allerneueste KI auf den leistungsschwachen Computern in den Werkshallen einzusetzen, verwenden wir den Intel Neural Compute Stick Version 2 (NCS v2), auch bekannt als Movidius Vision Processing Unit (VPU). Dabei handelt es sich um ein USB-Gerät mit Berechnungshardware, das für die Ausführung von tiefen neuronalen Netzen entwickelt wurde und der CPU oder GPU des PCs die Rechenarbeit abnimmt. Die NCS ist eine kostengünstige und stromsparende Lösung für KI am Arbeitsplatz, die zudem Plug-and-Play-fähig ist.
Warum ist eine Optimierung erforderlich?
Wir haben festgestellt, dass der Intel NCS ein sehr leistungsfähiger Prozessor für unsere Bedürfnisse bei Tulip Vision ist. Wir konzentrieren uns auf die Erkennung von Menschen und deren Aktivitäten auf der Strecke, daher ist es wichtig, Hände und Personen in einem eingehenden Kamerastrom erkennen zu können. Die neuesten Modelle zur Erkennung von Menschen verwenden tiefe neuronale Netze und schwere Modelle, die den NCS in Bezug auf die Leistung herausfordern.
Mit der Vanilla-Ausführung eines Handerkennungsmodells konnten wir eine Geschwindigkeit von 14 Bildern pro Sekunde (FPS) für die Inferenz erreichen. Es sind einige Optimierungen erforderlich, damit wir unser Ziel erreichen können, menschliche Bewegungen in Echtzeit zu erkennen (umgangssprachlich als 30 FPS und mehr bezeichnet, die übliche Laufgeschwindigkeit der meisten Kameras). Wir wollten auch das Beste aus der NCS-Hardware herausholen, deren Kosten im Voraus bezahlt werden. Die NCS-Spezifikationen geben eine theoretische Verarbeitungsrate von 100 GFLOP/s (Giga-Fließkomma-Operationen pro Sekunde) an, während wir anfangs nur 20-25 GFLOP/s (mit einem 1,5 GFLOP-Netzwerk bei 14 FPS) mit erheblicher Latenz erreichen konnten.
In diesem Artikel besprechen wir die Optimierungstechniken, die wir untersucht haben, und diejenige, die für uns den Unterschied ausmachte und uns in den Bereich der Echtzeit-Inferenz brachte. Intel hat bereits einen nützlichen Leitfaden zur Optimierung von Netzwerken für NCSv2 bereitgestellt, den wir bei unserer Arbeit verwendet haben.
Konvertieren eines Modells zur Ausführung auf dem NCS
Zu Beginn haben wir den Graphen und die Gewichte für ein Handerkennungsnetzwerk erstellt. Wir trainieren unsere eigenen Modelle für die Handerkennung, die auf die Leistung in Werkstattszenen abgestimmt sind, aber es gibt frei verfügbare Modelle im Internet, die erstaunlich gut funktionieren. Hier ist ein Beispielmodell auf GitHub, das wir für Tests und Vergleiche verwendet haben. Mit einem vortrainierten Modell können Sie eine Feinabstimmung für Ihre Zwecke und Daten vornehmen. Wir haben eine Reihe von Tools aus Googles TensorFlow verwendet, um die Feinabstimmung und Transfer-Learning-Techniken zu testen.
Damit ein bestimmtes Modell auf dem NCS laufen kann, muss es in das richtige Format konvertiert werden. Intel Die NCS verwendet OpenVINO, um für die NCS zu entwickeln. Dabei handelt es sich um ein sehr umfassendes Toolkit, das die Ausführung von Modellen in heterogenen Umgebungen (z.B. CPU, GPU, VPU), die Konvertierung aus vielen Quellarchitekturen wie TensorFlow, ONYX, PyTorch usw. und die Optimierung von Modellen auf verschiedene Weise ermöglicht.
Um ein Modell zu konvertieren, muss es sich zunächst in einem eingefrorenen Graphenzustand befinden. Das bedeutet, dass nur die Teile des neuronalen Netzwerks, die für die Inferenz benötigt werden, beibehalten werden, während alles andere verworfen wird, und dass sichergestellt wird, dass alle Gewichte des Graphen abgeschlossen sind. Zu den Ausführungsgraphen des neuronalen Netzes gehören mehrere Daten, die mit dem Training des Netzes zu tun haben, aber für die Inferenz nicht benötigt werden und bei der Konvertierung Probleme verursachen können. Um unser Beispiel-Handerkennungsmodell in einen eingefrorenen Graphenzustand zu bringen, verwenden wir das folgende Skript:
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 # Ersetzen Sie xyz durch den Wert des Prüfpunktschritts.
Abbildung 1. Skript zum Exportieren von Inferenzgraphen für Modelle, die mit der Tensorflow Object Detection API trainiert wurden
Für die Konvertierung verwenden wir die DL (Deep Learning) Workbench von OpenVINO. Sie lässt sich leicht auf jedem gängigen Betriebssystem installieren und funktioniert als eigenständige grafische Anwendung (GUI) oder über die Befehlszeile. Wir konzentrieren uns hier auf die Verwendung der GUI zur Visualisierung unserer Operationen. OpenVINO bietet eine hervorragende Anleitung für die DL-Workbench. In der DL-Workbench laden wir das Modell und legen die Formen der Ein- und Ausgabetensoren fest.
Abbildung 2. Intel Deep Learning Workbench Modell-Konfiguration
Die Workbench verfügt auch über sehr nützliche Tools zum Benchmarking der Modellausführung und -leistung sowie über Tests, die sicherstellen, dass das Modell auf dem NCS in Bezug auf die implementierten NN-Schichten funktionsfähig ist.
Abbildung 3. Modell-Benchmarking auf Testdaten (nicht kommentiert) mit Intel i7-8700T CPU
Schließlich macht es die Workbench sehr einfach, das Modell in das von der NCS benötigte Format zu konvertieren:
Abbildung 4. Herunterladen des konvertierten OpenVINO-Modells
Optimieren des Modells für schnelle Inferenz
Für den Anfang haben wir den Beispielcode von OpenVINO für die Objekterkennung verwendet. Er verwendet eine einfache synchrone API, die eine Inferenzanforderung (IR) an das NCS stellt und darauf wartet (den Thread blockiert), dass sie abgeschlossen wird, in der Annahme, dass die Ausführung des Modells einfach einige Zeit in Anspruch nimmt. Dies führte zu unserem ursprünglichen, wenig überzeugenden Leistungswert von etwa 14 FPS. Als wir die Zahlen durchgingen, stellten wir fest, dass dies im Vergleich zu dem, wozu das NCS in der Lage ist, eine stark unterdurchschnittliche Leistung ist.
Wir vermuteten, dass das Modell zu groß ist und dies der Grund für die schlechte Leistung ist. Also versuchten wir zunächst, die Größe des Eingabebildes für das Modell zu reduzieren. Die Theorie war, dass die großen anfänglichen Faltungsschichten bei großen Eingabegrößen vor dem Pooling einen großen Teil der Rechenlast tragen. Wir änderten die Form der Eingabe auf 64x64 und 128x128, statt der ursprünglichen 224x224. Aber das hat auch die Genauigkeit deutlich verringert - und das können wir nicht akzeptieren.
Abbildung 5. Balkendiagramm zur Darstellung der FPS im Vergleich zur Eingabegröße des Modells. Alle Modelle sind Mobilenetv2-basierte SSDLite-Modelle. xy-abc für Mobilenetv2, xy=Tiefenmultiplikator, abc=Eingabegröße.
Wir haben auch verschiedene Backbones und Detektorarchitekturen ausprobiert, z.B. MobileNet V3, EfficientDet, die als Teil des OpenVINO-Modellzoos verfügbar sind. Wir kamen jedoch zu dem Schluss, dass der Kompromiss zwischen Geschwindigkeit und Genauigkeit beim Inferencing auf NCS für unsere Anwendungsfall nicht günstig ist.
Abbildung 6. Modell-Backbone und Architektur im Vergleich zu FPS. Alle Mobilenet-Backbones verwenden SSDLite als Box-Detektoren.
Verblüfft von diesen Ergebnissen haben wir versucht, das Modell zu beschneiden. Beim Pruning entfernen wir Teile des Modells, die nicht viel zu seiner Leistung beitragen, und opfern so die Geschwindigkeit für die Genauigkeit. Wir haben das intelligente Modell Pruning von Tensorflow ausprobiert, das auf der Suche nach "leichten Schichten" basiert. Derzeit unterstützt Tensorflow das Model Pruning nur für Keras-basierte sequentielle Modelle und nicht für Modelle, die mit der Tensorflow Object Detection API trainiert wurden. Dies hat unsere Bemühungen, ein leichtgewichtiges Modell mit Pruning zu erstellen, weiter vereitelt.
Ein weiterer Ansatzpunkt für die Optimierung ist die Quantisierung. Bei der Quantisierung ändern wir die numerische Genauigkeit einiger Schichten im Netzwerk auf einen leichteren, schnelleren Typ. Dabei wird davon ausgegangen, dass schwächere Ausführungshardware, wie z.B. Mobiltelefone, bei der Ausführung von Gleitkommaoperationen (z.B. 32bit Gleitkomma, FLOAT32) langsamer ist als bei Ganzzahloperationen (z.B. 8bit Ganzzahl, INT8). Dies ist einer der besten Tricks zur NN-Optimierung. Aber auch hier unterstützt der NCS keine INT8-Operationen und wir stehen wieder am Anfang.
Asynchrone Ausführung
Schließlich haben wir nach vielen Versuchen mit Optimierungstechniken herausgefunden, dass wir einfach nicht auf den Abschluss der Inferenzanfrage warten und eine weitere parallel laufen lassen können, indem wir die asynchrone API von OpenVINO verwenden (wie in der Anleitung beschrieben). Wir können eine weitere Inferenzanforderung erhalten, während die anderen noch laufen, und diese an ein anderes Bild zur Erkennung weitergeben. Da wir die Bilder von der Kamera in Echtzeit erfassen, führt dies zu einer kleinen Verzögerung bei der Ausgabe, aber zu einem großen Geschwindigkeitsgewinn. Das folgende Diagramm zeigt den Vorteil des asynchronen IR-Streams:
In der Praxis führen wir einen Pool von 4 gleichzeitigen Inferenzanfragen aus. Die Größe des Pools wird durch das Inferenzgerät, d.h. den NCS, bestimmt. Eine CPU hat mehr IRs als das NCS, und ein leistungsstarker Grafikprozessor kann noch viel mehr haben. Wenn ein Modell groß und daher langsam ist und lange braucht, um die Anfrage abzuschließen, kann es sein, dass der Pool an IRs erschöpft ist und die Framerate trotzdem sinkt.
Bewertung und Leistungsergebnisse
Unsere wichtigsten Metriken für die Leistungsbewertung sind FPS und Latenz. Wir wünschen uns eine höhere FPS-Rate und eine geringere Latenz, aber mit dem asynchronen API-Ansatz sind diese beiden Faktoren nur schwer zu vereinbaren. Die Ausführung von mehr gleichzeitigen IRs bedeutet eine längere Aufwärmphase und Latenz, sorgt aber für eine insgesamt schnellere Durchlaufzeit.
Zur Messung der Leistung haben wir interne Tools, aber wir haben auch das verfügbare C++ Benchmark-Tool von OpenVINO verwendet. Es ist in der Lage, die Modelle auf dem NCS auszuführen und liefert sehr nützliche Statistiken. Es handelt sich zwar nicht um eine echte Simulation der Modellinferenz in Tulip Vision, aber es lieferte uns sehr gute Daten, ohne dass wir das Modell tatsächlich in unserem Framework ausführen mussten.
Abbildung 7. Modellleistung für SSDLite MobilenetV2 unter Verwendung asynchroner und synchroner API.
Fazit
Wir fanden das Intel NCSv2 und das OpenVINO-Toolkit für unsere Bedürfnisse sehr nützlich. Abgesehen davon, dass es sich um eine heterogene Plattform für die Ausführung von Modellen handelt, die reibungslos mit der NCS VPU zusammenarbeitet, bietet es auch ziemlich umfangreiche Unterstützung für Konvertierung und Benchmarking sowie nützliche Tools für die Optimierung. Wir haben viele Dinge ausprobiert, bevor wir die Option der asynchronen Inferenz gefunden haben, und dabei eine Menge gelernt. Auf diese Weise liefern wir unseren Kunden mit Tulip Vision erstklassige Leistung zu sehr niedrigen Kosten. Die asynchrone API in OpenVINO brachte die beste Leistungssteigerung im Vergleich zu vielen anderen traditionellen Ansätzen bei der Optimierung von Modellinferenzen, aber diese können sich noch als nützlich erweisen, wenn wir mehr tiefe Modelle in die Vision-Produktion einführen.