Introducción
Tulip es una solución de visión artificial sin código paraoperaciones en planta. Permite crearApps Tulip Apps utilizan la visión artificial para gestionar y supervisar las operaciones. Tulip se puede utilizar para detectar actividad en el puesto de trabajo y realizar el seguimiento tanto de objetos como de personas. Las señales de visión se pueden configurar para supervisar la seguridad, las operaciones de montaje manual, la preparación de kits y la recogida de piezas, así como muchas otras aplicaciones que aumentan la fiabilidad y reducen los errores. En el centro de Vision para la planta de producción se encuentran algoritmos de visión artificial basados en redes neuronales profundas. Los algoritmos están diseñados para ejecutarse en el hardware existente en las plantas de producción, que a menudo es un modesto PC con Windows. Para llevar la IA más avanzada a los ordenadores de baja potencia de la planta de producción, utilizamos el Intel Compute Stick versión 2 (NCS v2), también conocido como la Unidad de Procesamiento de Visión (VPU) de Movidius. Se trata de un dispositivo USB con hardware de cálculo diseñado para ejecutar redes neuronales profundas, que libera a la CPU o la GPU del PC del trabajo aritmético. El NCS es una solución de bajo coste y bajo consumo para la IA en el borde, que además es plug-and-play.
¿Por qué es necesaria la optimización?
Hemos comprobado que el Intel es un procesador muy eficaz para las necesidades de Tulip . Nos dedicamos a detectar personas y sus movimientos en la línea de producción, por lo que es fundamental poder detectar manos y personas en el flujo de imágenes de las cámaras. Los últimos modelos de detección de personas utilizan redes neuronales profundas y modelos de gran complejidad, lo que supone un reto para el NCS en cuanto a rendimiento.
Con la ejecución básica de un modelo de detección de manos, logramos una velocidad de 14 fotogramas por segundo (FPS) en la inferencia. Es necesario realizar algunas optimizaciones para alcanzar nuestros objetivos de detectar movimientos humanos en tiempo real (lo que coloquialmente se considera a partir de 30 FPS, la velocidad habitual de la mayoría de las cámaras). También buscábamos sacar el máximo partido al hardware NCS, cuyo coste se abona por adelantado. Las especificaciones del NCS indican una velocidad de procesamiento teórica de 100 GFLOP/s (gigaoperaciones de coma flotante por segundo), mientras que inicialmente solo conseguíamos alcanzar unos escasos 20-25 GFLOP/s (con una red de 1,5 GFLOP a 14 FPS) con una latencia considerable.
En este artículo analizamos las técnicas de optimización que hemos estudiado, así como aquella que realmente marcó la diferencia para nosotros y nos permitió situarnos dentro del rango de inferencia en tiempo real. Intel había publicado una guía muy útil sobre la optimización de redes para el NCSv2, que utilizamos en nuestro trabajo.
Adaptación de un modelo para su ejecución en el NCS
Para empezar, obtuvimos el gráfico y los pesos de una red de detección de manos. Entrenamos nuestros propios modelos para la detección de manos, optimizados para su rendimiento en entornos de taller, pero existen modelos disponibles gratuitamente en línea que funcionan sorprendentemente bien. Aquí hay un modelo de ejemplo en GitHub que utilizamos para las pruebas y las comparaciones de referencia. Con un modelo preentrenado, es posible que se desee ajustarlo a medida para adaptarlo a los propios fines y datos. Utilizamos un conjunto de herramientas de TensorFlow de Google para probar técnicas de ajuste fino y aprendizaje por transferencia.
Para que un modelo pueda ejecutarse en el NCS, debe convertirse al formato adecuado. Intel utiliza OpenVINO para desarrollar aplicaciones para el NCS. Se trata de un conjunto de herramientas muy completo que permite ejecutar modelos en entornos heterogéneos (por ejemplo, CPU, GPU, VPU), convertirlos desde numerosas arquitecturas de origen, como TensorFlow, ONYX, PyTorch, etc., y optimizarlos de diversas formas.
Para convertir un modelo, este debe encontrarse primero en un estado de gráfico congelado. Esto significa que solo se conservan las partes de la red neuronal necesarias para la inferencia, mientras que todo lo demás se descarta, además de asegurarse de que todos los pesos del gráfico estén finalizados. Hay varios datos que acompañan a los gráficos de ejecución de la red neuronal relacionados con su entrenamiento, que no son necesarios para la inferencia y que, de hecho, pueden causar problemas en la conversión. Para llevar nuestro modelo de detección de manos de ejemplo a un estado de gráfico congelado, utilizamos el siguiente script:
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 # Sustituye xyz por el valor del paso del punto de control.
Figura 1. Script del gráfico de inferencia de exportación para modelos entrenados con la API de detección de objetos de TensorFlow
Para la conversión utilizamos el DL (Deep Learning) Workbench, de OpenVINO. Se instala fácilmente en cualquier sistema operativo principal y funciona como una aplicación gráfica independiente (GUI) o se puede manejar desde la línea de comandos. Aquí nos centramos en el uso de la GUI para visualizar nuestras operaciones. OpenVINO ofrece una excelente guía de «introducción» para el DL Workbench. En el DL Workbench cargamos el modelo y especificamos las formas de los tensores de entrada y salida.
Figura 2. Configuración del modelo en Intel Learning Workbench
El entorno de trabajo también cuenta con herramientas muy útiles para evaluar la ejecución y el rendimiento del modelo, así como pruebas para garantizar que el modelo sea compatible con el NCS en lo que respecta a las capas de redes neuronales implementadas.
Figura 3. Evaluación comparativa del modelo con datos de prueba (sin anotar) utilizando una CPU Intel
Por último, el entorno de trabajo facilita enormemente la conversión del modelo al formato exigido por el NCS:
Figura 4. Descarga del modelo OpenVINO convertido
Optimización del modelo para una inferencia rápida
Para empezar, utilizamos el código de ejemplo de OpenVINO para la detección de objetos. Utiliza una sencilla API síncrona que envía una solicitud de inferencia (IR) al NCS y espera (bloquea el hilo) a que se complete, asumiendo que la ejecución del modelo simplemente tarda un tiempo en finalizar. Esto nos dio nuestro rendimiento inicial, bastante decepcionante, de unos 14 FPS. Tras analizar los datos, nos dimos cuenta de que se trata de un rendimiento muy por debajo de lo que el NCS es capaz de ofrecer.
Planteamos la hipótesis de que el modelo era demasiado grande y que esa era la razón del bajo rendimiento. Así que, en primer lugar, probamos a reducir el tamaño de la imagen de entrada al modelo. La teoría que barajábamos era que las grandes capas convolucionales iniciales, aplicadas a imágenes de gran tamaño antes de la agrupación, suponían una gran parte de la carga computacional. Cambiamos la forma de la entrada a 64x64 y 128x128, desde los 224x224 originales. Pero esto también redujo la precisión en gran medida, algo que no podemos aceptar.
Figura 5. Gráfico de barras que muestra la relación entre FPS y el tamaño de entrada del modelo. Todos los modelos son modelos SSDLite basados en Mobilenetv2. En el caso de Mobilenetv2 xy-abc, xy = multiplicador de profundidad y abc = tamaño de entrada.
También probamos diferentes arquitecturas de redes de base y detectores, como MobileNet V3 o EfficientDet, que están disponibles en el «model zoo» de OpenVINO. Sin embargo, llegamos a la conclusión de que la relación entre velocidad y precisión durante la inferencia en NCS no resulta favorable para nuestro caso de uso.
Figura 6. Estructura y arquitectura del modelo frente a los FPS. Todas las estructuras de Mobilenet utilizan SSDLite como detectores de cajas.
Ante estos resultados, decidimos probar a podar el modelo. La poda consiste en eliminar aquellas partes del modelo que no contribuyen significativamente a su rendimiento, sacrificando la velocidad en favor de la precisión. Probamos la poda inteligente de modelos de TensorFlow, basada en la búsqueda de «capas ligeras». Actualmente, TensorFlow solo admite la poda de modelos para modelos secuenciales basados en Keras y no admite modelos entrenados con la API de detección de objetos de TensorFlow. Esto frustró aún más nuestros esfuerzos por crear un modelo podado y ligero.
Otro aspecto que se puede optimizar es la cuantificación. En la cuantificación, modificamos la precisión numérica de algunas capas de la red para utilizar un tipo más ligero y rápido. Esto parte de la base de que el hardware de ejecución más débil, como el de los teléfonos móviles, es más lento a la hora de ejecutar operaciones aritméticas en coma flotante (por ejemplo, coma flotante de 32 bits, FLOAT32) que operaciones con números enteros (por ejemplo, enteros de 8 bits, INT8). Este es uno de los mejores trucos para la optimización de las redes neuronales. Sin embargo, una vez más, el NCS no admite operaciones INT8 y volvemos al punto de partida.
Ejecución asíncrona
Finalmente, tras numerosas pruebas con técnicas de optimización, descubrimos que podemos, sencillamente, no esperar a que finalice la solicitud de inferencia y ejecutar otra en paralelo utilizando la API asíncrona de OpenVINO (tal y como se describe en la guía). Podemos recibir otra solicitud de inferencia mientras las demás aún se están ejecutando y pasarla a otra imagen para su detección. Dado que capturamos fotogramas en tiempo real desde la cámara, esto introduce un pequeño retraso en la salida, pero supone una ganancia muy grande en velocidad. El siguiente diagrama muestra la ventaja del flujo de IR asíncrono:
En la práctica, gestionamos un conjunto de 4 solicitudes de inferencia simultáneas. El tamaño de este conjunto viene determinado por el dispositivo de inferencia, es decir, el NCS. Una CPU tendrá más solicitudes de inferencia que el NCS, y una GPU potente puede tener muchas más aún. En cualquier caso, si un modelo es grande y, por lo tanto, lento, y tarda mucho tiempo en completar la solicitud, es posible que agotemos el conjunto de solicitudes de inferencia y sigamos sufriendo una reducción en la tasa de fotogramas.
Evaluación y resultados de rendimiento
Nuestros indicadores clave para la evaluación del rendimiento son los FPS y la latencia. Queremos una mayor tasa de FPS y una menor latencia; sin embargo, con el enfoque de la API asíncrona, ambos aspectos suponen una disyuntiva. Ejecutar más IR simultáneas implica un periodo de calentamiento más largo y una mayor latencia, pero permite reducir el tiempo de respuesta global.
Para medir el rendimiento contamos con herramientas internas, pero también utilizamos la herramienta de evaluación de rendimiento en C++ que ofrece OpenVINO. Esta herramienta permite ejecutar los modelos en el NCS y proporciona estadísticas muy útiles. Aunque no se trata de una simulación real de la inferencia de modelos en Tulip , nos proporcionó datos muy valiosos sin necesidad de ejecutar el modelo en nuestro marco de trabajo.
Figura 7. Rendimiento del modelo SSDLite MobilenetV2 utilizando la API asíncrona y la API síncrona.
Conclusión
Hemos comprobado que Intel y el kit de herramientas OpenVINO resultan muy útiles para nuestras necesidades. Además de ser una plataforma heterogénea para ejecutar modelos, que funciona a la perfección con la VPU de NCS, también ofrece una amplia compatibilidad con herramientas de conversión y evaluación comparativa, así como útiles herramientas de optimización. Probamos muchas cosas antes de dar con la opción de inferencia asíncrona y aprendimos mucho en el proceso. Así es como ofrecemos un rendimiento de primera categoría a nuestros clientes utilizando Tulip a un coste muy bajo. La API asíncrona de OpenVINO proporcionó el mayor aumento de rendimiento en comparación con muchos otros enfoques tradicionales en cuanto a trucos de optimización de la inferencia de modelos, aunque estos últimos pueden seguir resultando útiles a medida que implementamos más modelos profundos en la producción de Vision.