“If you can run a neural network model at an energy cost of below 1 mW, it makes a lot of entirely new applications possible. This might seem like a somewhat arbitrary number, but if you translate it into concrete terms, it means a device running on a coin battery has a time of a year. That results in a product that’s small enough to fit into any environment and able to run for a useful amount of time without any human intervention.”
Es muy difícil leer EL LIBRO de Pete Warden y Daniel Situnayake y no ilusionarse con el potencial de llevar ML a dispositivos que sean capaces de dar ubicuidad a la AI en nuestro día a día. La situación es la siguiente, no necesitamos tantos Vatios, ni GPUs extraordinarias para aprovechar gran parte de los avances realizados en el campo del ML durante los últimos años, y estas son algunas de las máximas de esta disciplina y que hace que podamos tener redes neuronales artificiales y funcionales en el espacio que ocupa una moneda.
Otro aspecto con especial relevancia es el impacto ecológico que podría tener la adopción generalizada de estas prácticas con consciencia de consumo de energía durante las siguientes décadas. Es un tema que trataré de forma concreta en futuros artículos 🌱.
Los conceptos mencionados giran en torno al concepto que da nombre a este artículo, TinyML, que se puede traducir de forma poco agraciada como Machine Learning pequeño, es decir, modelos de Machine Learning que son capaces de funcionar con un muy bajo consumo en procesadores como los mencionados anteriormente donde no se destaca por la capacidad de cómputo. Todo modelo de TinyML debe estar optimizado para correr en dispositivos “humildes”.
Todo ese entusiasmo me hizo buscar un buen cajón de sastre para prototipar proyectos sobre TinyML, pero de cara a su evangelización, tenía también un ojo puesto en encontrar las herramientas ideales para una formación ágil y completa.
Por otra parte, está siendo complicado demostrar a perfiles no técnicos dentro de campos como IoT e IoT Industrial (IIoT) que esto realmente es un paradigma revolucionario para el momento actual en el que nos encontramos, y dispositivos con el pack completo como este sirve para enseñarlo sin muchos tecnicismos.
Después de una búsqueda intensiva, llegué aWio Terminal, un producto deSeeed Studio, y precisamente, lo que me atrajo no fue tanto una exhaustiva comparativa entre distintos productos, sino la comunidad que existe alrededor de Wio Terminal, la cual va mucho más allá de compañías específicas y que nace en los foros makers más conocidos. Se ha creado una comunidad para la divulgación y el aprendizaje muy única y llena de amor en la que merece la pena estar.
Lo más relevante de Wio Terminal para con el contexto TinyML es que funciona con una MCU Cortex M4F, un componente pequeño, de baja potencia, especialmente barato y con un muy pequeño impacto energético, por lo que estamos hablando en todo momento de reducir los modelos ML la mínima expresión. Se está demostrando cómo realizar ML en dispositivos con restricciones es como la típica historia sobre resiliencia, en la que se muestran como se puede sacar el máximo partido a un campo cuando los recursos son muy escasos o cuando simplemente necesitas unas capacidades que seansuficientemente buenas.
En este artículo quiero presentar este dispositivo y abrir el camino para futuros artículos que profundicen en el contexto TinyML y su adopción/democratización, por ello, después de realizar un “Hello World”, voy a crear un modelo usando la plataforma de democratización de TinyML en microcontroladores Edge Impulse y basado en el micrófono que lleva integrado Wio Terminal.
Hands-On Wio TerminalWio Terminal se puede programar tanto con Arduino como con MicroPython, sin embargo, este primer vistazo va a hacer uso de la IDE de Arduino.
En primer lugar, es necesario tener instalada la IDE compatible con tu equipo, se puede descargar en la página oficial y su instalación es intuitiva independientemente del SO que uses, en el caso de este artículo, verás muchas capturas de MacOS.
El siguiente aspecto que tendremos que tener en cuenta es la lista de Boards disponibles, queremos que la IDE de Arduino sea capaz de reconocer Wio Terminal para poder compilar para el dispositivo. Para ello necesitaremos añadir la lista de dispositivos de Seeed Studio a la lista de repositorios para Boards, eso se puede encontrar en Arduino > Preferencias > Gestor de URLs Adicionales de Tarjetas.
Esos repositorios que hay que referenciar son JSON que elaboran los propios fabricantes para compatibilizar sus dispositivos con el software (IDE) de Arduino, en este caso se trata de la siguiente URL:
https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
Ahora podremos instalar las herramientas para disponibilizar en la IDE de Arduino las distintas placas de Seeed Studio, para ello vamos a Herramientas > Placa > Gestor de Tarjetas. El buscador se las arregla para encontrar el paquete si escribimos cualquiera de las placas de Seeed Studio, en este caso Wio Terminal.
Volvemos al menú de selección de placas y ta-dah!! 🎉🎉🎉
Desde este punto podemos comenzar a programar para nuestra Wio Terminal. Voy a ir al grano para realizar un "Hello World" que de vida al dispositivo y que nos sirva de lienzo, pero si se quiere entrar más en detalle, Seeed Studio ha preparado un fantástico Get Started que da un repaso por todos los recursos de la A a la Z.
La finalidad de este Hello World pone a prueba el sensor de luminosidad que la Wio Terminal lleva integrado y con el cual podemos interactuar desde la parte trasera gracias a una parte descubierta, de esa forma es sencillo observar a través del monitor serial como los valores varían en función de la luminosidad que detecte.
#include "TFT_eSPI.h"
#define THRESHOLD 25
#define TFT_CUSTOM_BROWN 0xA42B
TFT_eSPI tft;
bool lightsOn = false;
int light = 0;
void setup() {
pinMode(WIO_MIC, INPUT);
pinMode(WIO_LIGHT, INPUT);
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
tft.setFreeFont(&FreeSansBoldOblique24pt7b);
light = analogRead(WIO_LIGHT);
if (light < LIGHT_THRESHOLD) {
lightsOn = false;
sleeped();
} else {
lightsOn = true;
awake();
}
}
void loop() {
light = analogRead(WIO_LIGHT);
Serial.print("Light value: ");
Serial.println(light);
delay(500);
if (!lightsOn && light >= LIGHT_THRESHOLD) {
lightsOn = true;
awake();
} else if (lightsOn && light < LIGHT_THRESHOLD) {
lightsOn = false;
sleeped();
}
}
void sleeped() {
tft.fillScreen(TFT_BLACK);
tft.drawString("zzz", 160, 60);
}
void awake() {
tft.fillScreen(TFT_CYAN);
tft.fillEllipse(80, 120, 50, 100, TFT_BLACK);
tft.fillEllipse(240, 120, 50, 100, TFT_BLACK);
tft.fillEllipse(80, 120, 48, 98, TFT_WHITE);
tft.fillEllipse(240, 120, 48, 98, TFT_WHITE);
tft.fillCircle(67, 125, 35, TFT_CUSTOM_BROWN);
tft.fillCircle(227, 125, 35, TFT_CUSTOM_BROWN);
tft.fillCircle(67, 125, 26, TFT_BLACK);
tft.fillCircle(227, 125, 26, TFT_BLACK);
}
Ahora que sabemos que nuestra Wio Terminal está viva, podemos empezar a poner las manos en la masa con TinyML. El ejemplo es muy simple, vamos a modelar un “aplausómetro 👏” que va a clasificar distintos tipos de aplauso, una herramienta que puede ser de utilidad para gente con el don de la ironía roto.
Vamos a basar la generación de este modelo en la plataforma Edge Impulse. En mis artículos haré menciones frecuentes a Edge Impulse porque están teniendo uno de los papeles más importantes en la actualidad en la democratización del ML en dispositivos embebidos, personalmente recomiendo seguirles muy de cerca, están aportando mucho a esta comunidad con conferencias como Imagine, una dosis de state of the art de Edge AI de lo más completa.
Tendremos que instalar el CLI de Edge Impulse:
npm install -g edge-impulse-cli
El CLI va a jugar un papel muy relevante en todas la fases, tanto en la recolección de datos para generar los sets de train y test, como para hacer el posterior despliegue en dispositivos, por lo que llegados a este punto, hay que asegurarse de que se tienen instaladas tanto la compatibilidad en la IDE de Arduino con Wio Terminal como el CLI que acabo de mencionar.
Es tan sencillo como que el CLI de Edge Impulse tiene la capacidad de obtener la información imprimida en el Serial para hacer la ingesta de datos que cree nuestro dataset para training y para testing del modelo.
Como parte de la compatibilidad con Wio Terminal, el CLI de Edge impulse es capaz de arrancar un daemon que permite la colecta de datos en tiempo real desde el propio dispositivo, seleccionando en un dropdown de la plataforma de cuál de los sensores integrados queremos recoger información, en este caso, el micrófono.
Hay que tener en cuenta que no podremos realizar esta obtención de datos desde el micrófono si Wio Terminal no tiene un firmware que lo permita, ya que su versión original no valoraba este escenario dentro de Edge Impulse. Por suerteDmitry Maslovnos tiene cubiertos:
“La obtención de datos a través del micrófono necesita unfirmware en estado alphacon el que tendremos que resetear nuestro dispositivo.”
Una vez reseteada la Wio Terminal con este firmware en fase alpha, ya podemos lanzar el daemon con la confianza de que Edge Impulse detectará el micrófono para la colecta de datos en tiempo real desde la plataforma web.
edge-impulse-data-daemon
La interfaz habla por sí sola, basta con acceder a la sección Data acquisition en la plataforma, y si hemos vinculado el dispositivo correctamente veremos como aparece una interfaz desde la cual podremos grabar nuestras muestras especificando el intervalo de tiempo y lo más importante, el label de cada una de las muestras con el que queremos clasificar (en este caso) cada tipo de aplauso.
Para el propósito de este artículo voy a clasificar 3 tipos de aplauso:
- Irónico (ironic)
- Felicitaciones (congratulations)
- RÍtmico (flamenco 💃)
La colecta de datos puede ser la fase más tediosa, sobre todo si se tratan de datos que estamos generando manualmente, caso que es poco común, sin embargo es una fase crucial para el proyecto, y la precisión del modelo va a depender de como definamos estos cimientos, por lo que los datos deben estar bien cuidados y se debe asegurar que los mismos generalizan el dominio completo del problema que queremos resolver para escapar de una problemática que resumiré en el siguiente párrafo.
La propia plataforma de Edge Impulse da algunos consejos a lo largo de todas las fases, pero hay uno de los aspectos clave que no se menciona y que por lo tanto creo que hay que hacer un pequeño stop, se trata de estar al tanto de los conceptos de underfitting y overfitting. Debido a que se va a elaborar el dataset de manera manual y con un muestreo de criterio propio, estos conjuntos van a ser de un tamaño más bien pequeño y muy sesgados, así que lo más probable es que se caiga en underfitting.
No podemos detenernos en cada uno de los aspectos relevantes a la hora de entrenar un modelo, pero este aspecto es extremadamente relevante y sobre todo en este ciclo, así que veamos de qué se tratan.
- Underfitting: Una mala generalización de los datos debida a la pequeña cantidad de datos en el set de entrenamiento y al desconocimiento. Es necesario que todas las clases se vean representadas con un volumen relevante en el conjunto de entrenamiento.
- Overfitting: Cuando surge una mala generalización de los datos con un volumen considerable, pero con un grado de especificidad muy alto. La variedad dentro de cada clase es clave para escapar del overfitting.
Otro aspecto importante a tener en cuenta en esta fase, es la depuración de los datos, en esta fase podremos deshacernos de las partes prescindibles de las muestras para nuestros modelos definitivos. Si alguna de las muestras tiene contenido anómalo, este sería el momento para recortar esas partes, la plataforma da algunas herramientas para hacer este proceso, como Crop y Split de los audios en crudo.
En esta parte del proceso también se dan las herramientas para diseñar la ventana de tiempo en la que se seleccionarán fragmentos de audio para su clasificación.
Llegados a este punto, es hora de pasar a la fase de entrenamiento del modelo, es realmente aquí donde Edge Impulse nos abstrae de la parte especializada que podría hacer un Machine Learning Engineer con un sistema de selección basado en cajas que acaban por generar un impulse, es decir, un modelo ya preparado la inferencia en dispositivos low-power.
Definición de los bloques de un ImpulsePara comenzar, tenemos que ir a la sección “Create Impulse” para ver ese sistema de cajas que secuencialmente recoge información en crudo a través de ventanas del tamaño que hemos definido, extrae las características de los datos en base al algoritmo que escojamos para el contexto de nuestro modelo.
Por último, se añade un “learning block” que define el tipo de algoritmo de aprendizaje más adecuado para nuestro problema. La propia plataforma da algunas recomendaciones en función de los inputs que se estén usando.
Como estamos trabajando con un input basado en audio, nos interesa añadir un bloque de procesamiento del input que extraiga la información en un formato adecuado para que se pueda generar un output, aquí deberemos tener en cuenta varias opciones de las que nos proporcionan para extraer características o features, estas son son Mel Frequency Cepstral Coefficients (MFCC) o Mel-filterbank Energy (MFE).
La respuesta correcta en este caso es MFE. Este proceso extrae un espectrograma del audio que posteriormente se usará como input de laRed Neuronal Convolucional(CNN). Tal y como se indica en la plataforma, mientras MFCC destaca para reconocimiento de voz humana y MFE lo hace en los casos contrarios, en los que no se desea ningún tipo de característica que tenga que ver con la voz humana, por lo que se puede deducir por el contexto del "problema" que este es el bloque de procesamiento adecuado.
Por último, tendremos que definir el algoritmo de aprendizaje en su bloque. Como en este caso nos encontramos ante un problema claro de clasificación en el que queremos saber a qué tipo corresponde un aplauso, la opción de entre las sugerencias será la de clasificación con Keras, no estamos resolviendo un problema de regresión.
Tras seguir todos los pasos, tendremos un impulse completo con el potencial de reconocer las clases que queremos clasificar y que corresponden a las de los labels definidos (ironic, congratulations, flamenco y background). Si seleccionamos Save Impulse podremos pasar a la fase de configuración de los bloques uno por uno.
En la fase de preprocesado extraemos el espectrograma de los sonidos grabados, la información proporcionada por este bloque será la que alimente a la red neuronal convolucional que crearemos en el bloque de entrenamiento.La preparación de los datos en todas las fases es una de las tareas más importantes cuando se prepara un modelo. Edge Impulse parametriza cada uno de los bloques de forma que se puedan afinar todas las variables relevantes hasta conseguir los resultados óptimos.
En el bloque MFE que hemos seleccionado podemos ajustar los siguientes atributos del espectrograma si fuese necesario:
- Frame length: La longitud de cada frame en segundos.
- Frame stride: La separación entre frames en segundos.
- Filter: Número de filtros en el “filter-bank”.
- Low/High Frequency: Límite de Hz en cotas inferiores/superiores.
- Noise floor: Límite de decibelios (dB) inferiormente
En este caso no se han modificado los valores genéricos que aparecen MFE. Por lo que una vez se comprueba el espectrograma, solamente queda clicar en Save parameters y después en Generate features para extraer las características de nuestros datos que alimentarán a la CNN.
El siguiente paso será el de entrenar la CNN partiendo de las series temporales que se han procesado en otros bloques. Edge Impulse lo pone fácil en este caso a la hora de hacer el tuning adecuado de todas las variables desde una única interfaz.
En este paso también podríamos aplicar un proceso de data augmentationpara enriquecer y aumentar la cantidad de datos para el input a partir de los datos de los que ya disponemos.
Antes de lanzar el proceso de entrenamiento clicando el botón “Start training” podremos ver la estructura de la CNN con la que vayamos a entrenar nuestro modelo, si estás familiarizado con con los frameworks típicos o con la teoría de las redes neuronales, podrás modificar los parámetros con confianza. En este caso, por ejemplo, se observa un Dropout que en otros contextos podría ser excesivo, llegando incluso a “lobotomizar” nuestra red neuronal.
En esta primera aproximación vamos a confiar en estos valores por defecto en las aplicaciones de Dropout para paliar (mínimamente) el posible overfitting debido a que soy la única persona que se ha aplaudido a sí misma para conseguir los datos de train/test.
Una vez acabado el proceso de entrenamiento de la CNN, Edge Impulse mostrará las métricas que nos darán una idea de la precisión y fiabilidad de nuestro modelo antes de realizar cualquier a los dispositivos.
En este caso se puede ver en la matriz de confusión como los aplausos de felicitaciones pueden ser confundidos por aplausos de flamenco, no es nada que no se solucione enriqueciendo la toma de datos con un posterior tunning. Como he comentado, la colecta de datos puede estar siendo muy sesgada al ser básicamente manual, pero nos hará la faena para este artículo.
Llega el momento de la verdad. Para probarlo en Wio Terminal solamente nos queda acceder a la sección Deploy, en la cual veremos que existen varias opciones, una de ellas te permite generar un binario con el que podemos desplegar directamente sobre el firmware, pero en este caso no existe esa opción para la Wio Terminal, de hecho necesitaremos modificar el código fuente que invoca la inferencia del modelo o impulso que hemos diseñado.
Deberemos seleccionar la opción de descargar como librería de arduino (Arduino library) que nos proporcionará un fichero comprimido con las fuentes de las librerías necesarias para ejecutar la inferencia del modelo en distintos dispositivos. Las opciones proporcionadas cubren básicamente gran parte del espectro de posibilidades en el mercado, por lo que obviando las pequeñas modificaciones que habrá que hacer para adaptarlo a ciertos firmwares, podemos estar tranquilos.
El código proporcionado por la plataforma es muy completo y prácticamente está listo para realizar la inferencia de una forma muy básica desde el input del micrófono, pero hay varios aspectos que debemos tener en cuenta para que el código sea compatible con Wio Terminal, vamos a tener que hacer un par de modificaciones.
Los cambios que se tienen que realizar tienen que ver directamente con la librería PDM.h (Pulse-density modulation), se trata de la librería encargada de procesar el input del micrófono en placas MP34DT05 como la del Arduino nano BLE Sense 33, y es un aspecto en el que no coincide con Wio Terminal, por lo que tendremos que eliminar todas sus dependencias para sustituirlo la entrada en crudo de Wio Terminal. Os tengo cubiertos en gran parte porque Dmitry Maslov expuso el problema, el código completo se puede encontrar en mi repositorio de GitHub.
Ya solo nos queda compilar el código para que Wio Terminal realice el proceso de inferencia de nuestro modelo, veremos como el modelo clasifica los distintos tipos de aplauso que hemos enseñado a la CNN, y todo con un peso en memoria de menos de 15K.
Ahora que hemos comprobado que el aplausómetro funciona en dispositivos low cost con usos de 36K de memoria Flash y 13K de RAM, podemos asumir que funcionará en dispositivos que se encuentren en cualquier lugar y con prácticamente cualquier tamaño, las ARM Cortex-Mx van a estar en todas partes, así que estamos cubiertos
Se podría extraer información agregada y en tiempo real sobre el estado de ánimo del público en un espectáculo, ponencia o cualquier tipo de escenario en el que nos interese conocer aspectos sobre la aceptación. O simplemente si eres un tipo tratando de aprender sobre comunicación 🙋♂️, no se te dan muy bien las indirectas y necesitas un helper.
También puede ser una ayuda para personas con deficiencias auditivas, en otro tipo de dispositivo sería adecuado ejecutar esta inferencias en algún tipo de wearable, por su bajo consumo podríamos hacer que tuviese una larga autonomía con una simple pila de botón.
ConclusionesEspero que este artículo sirva para que mucha gente vea el potencial de este emocionante campo y comunidad en torno a las tecnologías que he mencionado. Creo firmemente en que nos encontramos en una era clave para el impulso de la inteligencia de las cosas, hacer que pequeños dispositivos ubicuos de nuestro entorno sean inteligentes y aprovechen los avances realizados a lo largo de estos años en el campo de ML.
Herramientas de democratización de la AI para dispositivos limitados como Edge Impulse van a ser actores claves para seguir avanzando en esta dirección. Esta desmitificación o simplificación de la AI eficiente va a hacer que el proceso se sienta muy orgánico.
Para cerrar, considero que el panorama de la formación maker está teniendo uno de sus momentos dorados ahora mismo, y realmente existen muchas alternativas a las propuestas, pero admito que para mi, descubrir el tridente Wio Terminal, TinyML y Edge Impulse ha sido crucial, sin duda es algo que tenía que compartir con mi colegas en Sngular.
Comments