Con el auge de la Inteligencia Artificial y todo lo que ello conlleva, son muchos los fabricantes que han apostado por hacer sistemas y software específico para tareas de aprendizaje profundo. Es el caso de Nvidia y su plataforma de cómputo paralelo llamada CUDA (Compute Unified Device Architecture). Con dicha plataforma, es posible programar software para que corra directamente sobre una GPU aprovechando todo el potencial de estas en cuanto a procesamiento paralelo se refiere. Además, proporciona una capa de abstracción en la complejidad del paralelismo pudiendo desarrollar programas paralelos usando librerías en lenguajes como C/C++, Python o Java.

También es el caso de Google, que ha desarrollado TPUs: circuitos integrados personalizados específicos que se usan para acelerar las cargas de trabajo de aprendizaje automático. Este hardware, aparte de específico, es bastante costoso y, normalmente, se encuentra en centros de datos gigantescos con un enorme consumo de energía.

¿Por qué es importante el edge computing?

Para entender por qué las cargas de trabajo de aprendizaje automático se realizan en centros de datos, primero vamos a entender qué es el deep learning y por qué las redes neuronales convolucionales requieren de dicho hardware específico.

El Deep Learning es una rama del machine learning que se centra en el uso de redes neuronales profundas para resolver problemas complejos.

En este artículo nos centraremos en las redes neuronales convolucionales que son un tipo especial de redes neuronales que han demostrado adaptarse muy bien a sistemas de visión artificial.

En un proceso de Deep Learning, típicamente a alto nivel, se distinguen dos fases:

Los procesos de entrenamiento e inferencia requieren de hardware y software especializado para llevar a cabo la tarea ya que son procesos bastante costosos (computacionalmente hablando). El proceso de entrenamiento de una red neuronal convolucional desde cero suele realizarse en inmensos centros de datos de manera paralela y haciendo uso de GPUs (estos procesos pueden tardar días e incluso semanas en terminar). Sin embargo, el proceso de inferencia (recordemos, clasificar una imagen en una red ya entrenada) es relativamente menos costoso y es en este proceso de inferencia donde entra en juego el edge computing.

Para ver cómo de importante es este término, pensemos en el caso de la conducción autónoma. Un coche necesita procesar los datos de sus múltiples sensores (tales como cámaras, sensor de ultrasónicos, radares... ) en tiempo real y sin necesidad de comunicarse con centros de datos remotos que hagan la fase de inferencia por él. Es un tiempo crítico que puede verse afectado por numerosos factores:

El edge computing hace referencia al procesamiento de datos de manera local y sin necesidad de comunicación con ningún centro de datos remoto. De esta manera se pueden sacar resultados a partir del análisis de los datos recogidos por los distintos sensores IoT sin tener que enviarlos a través de la red.

Ahora que sabemos qué es el edge computing y cómo funcionan las redes neuronales (a muy alto nivel), nos centraremos en la parte principal de este artículo: ¿Qué es la Nvidia Jetson Nano?, ¿cómo le sacamos provecho?

Nvidia Jetson Nano

La Nvidia Jetson Nano es una placa de desarrollo del estilo de la Raspberry Pi pero diseñada expresamente para el deep learning ya que incorpora una GPU que hace que los procesos de inferencia se puedan llevar de manera local y en tiempo real. Esta placa también sirve para entrenar una red neuronal, si bien, no está diseñada expresamente para ello.

¿Dónde encaja la Jetson Nano en el edge computing? Gracias a sistemas como estos, capaces de procesar información de manera rápida sin tener que comunicarse con servidores externos, permite desarrollar aplicaciones IoT integradas ya que lleva la Inteligencia Artificial a sistemas de tamaño reducido, económicos y de bajo consumo de energía.

En este caso en particular, su hardware específico hacen que la Jetson Nano sea capaz de realizar la fase de inferencia de una red neuronal en tiempo real. Es capaz de correr los principales frameworks de procesamiento de deep learning tales como TensorFlow, PyTorch o Keras. Algo que, si bien también es posible correr dichos frameworks en una Raspberry Pi, esta no cuenta con hardware específico por lo que los procesos serían muy lentos e inviables de ejecutar.

Además, la Jetson Nano es de propósito general ya que corre un sistema operativo Linux, en concreto Ubuntu, que la hace perfecta para desarrollar proyectos “Do it Yourself” de Inteligencia Artificial. Para hacerla aún más potente, se le pueden acoplar distintos accesorios (como se ven en las imágenes posteriores). En este caso le hemos montado una cámara gran angular de 160º y un ventilador para refrigerar el módulo disipador de la CPU/GPU.

Caso de uso: clasificación de objetos en tiempo real

Para demostrar la potencia de la Jetson Nano, vamos a desarrollar un caso de uso en Python en el que, gracias a una cámara conectada a nuestra placa, analizaremos los datos en tiempo real y determinaremos los distintos objetos que son recogidos en las imágenes.

El flujo de datos procedente de la cámara se pasará como “input” a 2 redes neuronales previamente entrenadas, capaces de distinguir distintos objetos en una imagen y además localizarlos dentro de la misma.

El código fuente del proyecto se encuentra en mi página de Github, que es una bifurcación del código proporcionado por Nvidia para ejecutar procesos de inferencia en los distintos productos Jetson. Mi versión modificada incluye el reconocimiento de objetos adaptado a distinguir distintos tipos de frutas en tiempo real, como veremos posteriormente.

La red neuronal que utilizaremos para el procesado y clasificado de las imágenes será la arquitectura GoogleNet. La ventaja de utilizar dicha red es que podemos descargarla ya entrenada para aplicar solamente la parte de inferencia desde nuestro terminal embebido (es decir, nuestra placa Jetson Nano), de manera local y sin conexión a internet. Los pesos de esta red neuronal ya han sido entrenados sobre un conjunto de datos para ser capaces de distinguir entre 1000 clases posibles (ImageNet). En el proceso de inferencia que realizaremos en la Jetson Nano intentaremos distinguir en tiempo real los distintos objetos que pongamos delante de la cámara.

La instalación y puesta en marcha del proyecto en nuestra placa escapa del alcance de este artículo, ya que se centra en demostrar las ventajas del edge computing por medio de sistemas embebidos.

#!/usr/bin/python

import jetson.inference
import jetson.utils

#Classify a live camera stream using an image recognition DNN
# load the recognition network
net = jetson.inference.imageNet("googlenet") # pre-trained model to load

# create the camera and display
font = jetson.utils.cudaFont()
camera = jetson.utils.gstCamera(1280, 720, 0) # (width, height, index of the MIPI CSI camera)
display = jetson.utils.glDisplay()

while display.IsOpen():

    img, width, height = camera.CaptureRGBA() # capture the image
    class_idx, confidence = net.Classify(img, width, height) # classify the image
    class_desc = net.GetClassDesc(class_idx) # find the object description
    # overlay the result on the image    
    font.OverlayText(img, width, height, "{:05.2f}% {:s}".format(confidence * 100, class_desc), 5, 5, font.White, font.Gray40)
    display.RenderOnce(img, width, height) # render the image
    # update the title bar
    display.SetTitle("{:s} | Network {:.0f} FPS".format(net.GetNetworkName(), 1000.0 / net.GetNetworkTime()))
    net.PrintProfilerTimes() # print out performance info

Aquí tenéis una imagen del código con el número de línea:

Aspectos importantes a tener en cuenta en diversas líneas:

Ejemplos del proceso de inferencia y los tiempos de ejecución

Ejecutamos el script imagenet-console.py y le pasamos 2 argumentos: la imagen que será procesada por la red neuronal (inferencia) y como segundo argumento el path donde guardará la imagen con la clase predecida. Red neuronal: googlenet.

$ jetbot@jetbot:~/jetson-projects/jetson-inference/build/aarch64/bin$ ./imagenet-console.py ~/Pictures/tractor.jpg ~/Pictures/tractor_out.jpg

class 0561 - 0.024102  (forklift)
class 0595 - 0.046457  (harvester, reaper)
class 0621 - 0.131314  (lawn mower, mower)
class 0866 - 0.755659  (tractor)
imagenet-camera:  75.56585% class #866 (tractor)

[TRT]   ------------------------------------------------
[TRT]   Timing Report networks/bvlc_googlenet.caffemodel
[TRT]   ------------------------------------------------
[TRT]   Pre-Process   CPU   0.05089ms  CUDA   0.35948ms
[TRT]   Network       CPU  34.88473ms  CUDA  15.33505ms
[TRT]   Post-Process  CPU   0.38747ms  CUDA   0.13750ms
[TRT]   Total         CPU  35.32309ms  CUDA  15.83203ms
[TRT]   ------------------------------------------------

Ejecutamos el script detectnet-console.py. En este caso, la red neuronal nos devolverá la clase predecida junto con la localización del objeto dentro de la imagen. Red neuronal: ssd_mobinet_v2_coco.

jetbot@jetbot:~/jetson-projects/jetson-inference/build/aarch64/bin$ ./detectnet-console.py ~/Pictures/ktmexc300.jpg ~/Pictures/ktmexc300_out.jpg

detectNet -- maximum bounding boxes:  100
detectNet -- loaded 91 class info entries
detectNet -- number of object classes:  91
detected 1 objects in image
<detectNet.Detection object>
   -- ClassID: 4
   -- Confidence: 0.991716
   -- Left:    52.2139
   -- Top:     66.4655
   -- Right:   990.884
   -- Bottom:  629.089
   -- Width:   938.67
   -- Height:  562.624
   -- Area:    528118
   -- Center:  (521.549, 347.777)

[TRT]   ------------------------------------------------
[TRT]   Timing Report networks/SSD-Mobilenet-v2/ssd_mobilenet_v2_coco.uff
[TRT]   ------------------------------------------------
[TRT]   Pre-Process   CPU   0.07553ms  CUDA   2.33667ms
[TRT]   Network       CPU 154.37157ms  CUDA 151.44020ms
[TRT]   Post-Process  CPU   0.05719ms  CUDA   0.05693ms
[TRT]   Visualize     CPU  52.22006ms  CUDA  52.47854ms
[TRT]   Total         CPU 206.72435ms  CUDA 206.31235ms
[TRT]   ------------------------------------------------

jetbot@jetbot:~/jetson-projects/jetson-inference/build/aarch64/bin$ ./detectnet-console.py ~/Pictures/pedestrians.jpg ~/Pictures/pedestrians_out.jpg

detectNet -- maximum bounding boxes:  100
detectNet -- loaded 91 class info entries
detectNet -- number of object classes:  91
detected 8 objects in image
<detectNet.Detection object>
   -- ClassID: 1
   -- Confidence: 0.842863
   -- Left:    700.918
   -- Top:     268.546
   -- Right:   1086.31
   -- Bottom:  1239.46
   -- Width:   385.39
   -- Height:  970.911
   -- Area:    374179
   -- Center:  (893.613, 754.002)
<detectNet.Detection object>
   -- ClassID: 1
   -- Confidence: 0.984094
   -- Left:    1160.61
   -- Top:     167.221
   -- Right:   1434.48
   -- Bottom:  903.691
   -- Width:   273.87
   -- Height:  736.469
   -- Area:    201697
   -- Center:  (1297.54, 535.456)
<detectNet.Detection object>
   -- ClassID: 1
   -- Confidence: 0.656658
   -- Left:    1642.03
   -- Top:     233.591
   -- Right:   1699.17
   -- Bottom:  382.301
   -- Width:   57.1382
   -- Height:  148.71
   -- Area:    8497.03
   -- Center:  (1670.6, 307.946)

[TRT]   ------------------------------------------------
[TRT]   Timing Report networks/SSD-Mobilenet-v2/ssd_mobilenet_v2_coco.uff
[TRT]   ------------------------------------------------
[TRT]   Pre-Process   CPU   0.10532ms  CUDA   5.87875ms
[TRT]   Network       CPU 181.78275ms  CUDA 175.31844ms
[TRT]   Post-Process  CPU   0.21455ms  CUDA   0.21443ms
[TRT]   Visualize     CPU 433.58691ms  CUDA 434.22238ms
[TRT]   Total         CPU 615.68951ms  CUDA 615.63403ms
[TRT]   ------------------------------------------------

Veamos ahora un ejemplo de clasificación en tiempo real con la cámara activada. Vamos a clasificar distintas frutas en tiempo real. Mayor tasa de fotogramas por segundo requiere una mayor potencia de cómputo.

Como se puede observar, la red neuronal no está exenta de errores ya que una naranja en determinados fotogramas la clasifica como una pelota de ping-pong.

Conclusión

Hemos visto la potencia que tiene el edge computing y por qué es importante en ciertos casos de uso como la conducción autónoma. La aparición de hardware asequible y software compatible ha propiciado un incremento de los proyectos relacionados y pruebas de concepto, que junto con los distintos sensores IoT y la IA, hacen un ecosistema mucho más enriquecido y potente.

La placa Nvidia Jetson Nano agrupa esta propiedad de hardware especializado junto con código customizable que nos abren un mundo de posibilidades y un sin fín de proyectos de Inteligencia Artificial que podemos desarrollar en nuestra propia casa y a un bajo coste. Es ideal para prototipar rápidamente y poner en práctica pruebas de concepto en un entorno real y controlado.

El edge computing llega para quedarse.

Apéndice

Si te interesa saber todos los proyectos que se pueden hacer con la placa Jetson Nano, o indagar más en cómo aplicar la inteligencia artificial en casos de uso cotidianos, dejo unos links para futuras lecturas:

Cuéntanos qué te parece.

Enviar.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete