Resumen

Este codelab fue creado para explorar el framework TensorFlow Lite como principal herramienta para implementar los modelos de optimización de parámetros en Sistemas Embebidos. Este framework permite realizar inferencias de modelos de aprendizaje automático en dispositivos con recursos limitados. Se espera que usted al finalizar esté en capacidad de:

  • Identificar los pasos necesarios para usar este Framework y poder optimizar los modelos.

Fecha de Creación:

2024/03/01

Última Actualización:

2024/03/01

Requisitos Previos:

Adaptado de:

Referencias:

Escrito por:

Fredy Segura-Quijano

TensorFlow Lite es una biblioteca de TensorFlow diseñada específicamente para realizar inferencias de modelos de aprendizaje automático en dispositivos con recursos limitados, como teléfonos móviles, microcontroladores y otros Sistemas Embebidos (https://www.tensorflow.org/lite) (https://ai.google.dev/edge/lite). TensorFlow Lite facilita la ejecución de modelos de inteligencia artificial en estos dispositivos, ofreciendo una solución ligera y eficiente que optimiza tanto el rendimiento como el consumo de energía. Desarrollado por Google, TensorFlow Lite es parte del ecosistema TensorFlow y está diseñado para integrarse fácilmente con las herramientas y flujos de trabajo existentes de TensorFlow.

La arquitectura de TensorFlow Lite se compone de varias capas que permiten la ejecución eficiente de modelos en dispositivos embebidos. Estas capas incluyen:

Converter: Transforma un modelo de TensorFlow entrenado (generalmente en formato SavedModel o Keras) en un modelo optimizado y compacto en formato TensorFlow Lite (.tflite). Este proceso puede incluir técnicas de optimización como la cuantización y la fusión de operaciones.

Interpreter: Ejecuta el modelo TensorFlow Lite en el dispositivo objetivo. El intérprete es responsable de asignar tensores, ejecutar operaciones y gestionar los recursos de hardware. Está diseñado para ser ligero y eficiente, permitiendo una rápida ejecución de inferencias.

Delegates: Mejoran el rendimiento del intérprete delegando partes del gráfico de operaciones a hardware específico, como GPUs, DSPs y TPUs. Los delegados permiten que TensorFlow Lite aproveche las capacidades especializadas de estos aceleradores para mejorar la velocidad y la eficiencia.

El proceso de conversión de un modelo TensorFlow a TensorFlow Lite implica varias etapas. Primero, se entrena el modelo utilizando TensorFlow. Una vez entrenado, se utiliza el TFLiteConverter para convertir el modelo. Este convertidor aplica optimizaciones, como la cuantización, para reducir el tamaño del modelo y mejorar su eficiencia. Aquí hay un ejemplo básico de cómo se realiza esta conversión:

import tensorflow as tf

# Cargar el modelo entrenado
model = tf.keras.models.load_model('model.h5')

# Convertir el modelo a TensorFlow Lite
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

# Guardar el modelo TensorFlow Lite
with open('model.tflite', 'wb') as f:
    f.write(tflite_model)

TensorFlow Lite Micro: TensorFlow Lite Micro es una versión de TensorFlow Lite diseñada para funcionar en microcontroladores con muy pocos recursos, como el ESP32. Esta versión es extremadamente ligera y está optimizada para dispositivos con memoria y capacidad de procesamiento limitadas. TensorFlow Lite Micro permite la implementación de modelos de IA en aplicaciones de IoT y otros dispositivos embebidos pequeños. (https://github.com/tensorflow/tflite-micro)

Implementación en Dispositivos Móviles: TensorFlow Lite es ampliamente utilizado en aplicaciones móviles para tareas como el reconocimiento de imágenes, la detección de objetos y la clasificación de texto. Al optimizar los modelos para su ejecución en dispositivos móviles, TensorFlow Lite permite que estas aplicaciones ofrezcan funcionalidades avanzadas de IA con un rendimiento rápido y un uso eficiente de la energía. Las bibliotecas de soporte para Android e iOS facilitan la integración de TensorFlow Lite en aplicaciones móviles.

TensorFlow Lite Model Maker: TensorFlow Lite Model Maker es una herramienta que simplifica el proceso de creación y optimización de modelos TensorFlow Lite. Proporciona una interfaz de alto nivel para entrenar modelos con datos personalizados y convertirlos a TensorFlow Lite. Model Maker soporta varias tareas de machine learning, incluyendo la clasificación de imágenes, la detección de objetos y el procesamiento de texto. Esta herramienta es especialmente útil para desarrolladores que buscan implementar rápidamente modelos de IA optimizados en dispositivos embebidos. (https://www.tensorflow.org/lite/models/modify/model_maker)

En este ejemplo, se mostrará cómo entrenar un modelo simple de TensorFlow, convertirlo a TensorFlow Lite, cuantizarlo y luego implementarlo en un ESP32 utilizando TensorFlow Lite Micro.

1. Entrenamiento y Conversión del Modelo:

Primero, se entrena un modelo simple en TensorFlow. Para este ejemplo, usaremos un modelo de clasificación de dígitos escritos a mano (MNIST).

import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.utils import to_categorical

# Cargar el dataset MNIST
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# Preprocesar los datos
x_train, x_test = x_train / 255.0, x_test / 255.0
y_train, y_test = to_categorical(y_train), to_categorical(y_test)

# Definir el modelo
model = Sequential([
    Flatten(input_shape=(28, 28)),
    Dense(128, activation='relu'),
    Dense(10, activation='softmax')
])

# Compilar el modelo
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# Entrenar el modelo
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))

# Guardar el modelo
model.save('mnist_model.h5')

2. Conversión y Cuantización del Modelo

Se convierte el modelo entrenado a formato TensorFlow Lite y se cuantiza.

# Convertir el modelo a TensorFlow Lite con cuantización
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

# Guardar el modelo cuantizado
with open('mnist_model_quant.tflite', 'wb') as f:
    f.write(tflite_quant_model)

3. Código para ESP32

En la ESP32, se usa TensorFlow Lite Micro para cargar y ejecutar el modelo cuantizado.

Instalación de TensorFlow Lite Micro: Se debe asegurar el tener las librerías necesarias. Se pueden añadir TensorFlow Lite Micro en el archivo platformio.ini si se usa PlatformIO:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps = 
    https://github.com/tensorflow/tflite-micro-arduino-examples.git

Opcional: en caso de tener problemas con la librería tflite-micro-arduino-examples.git; use lib_deps = tanakamasayuki/TensorFlowLite_ESP32@^1.0.0

Código de Inferencia en ESP32: A continuación se presenta el código para cargar el modelo y realizar inferencias.

#include <TensorFlowLite.h>
#include "mnist_model_quant.h"

// Definir los buffers para el modelo
constexpr int kTensorArenaSize = 2 * 1024;
uint8_t tensor_arena[kTensorArenaSize];

// Modelo de referencia global
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output = nullptr;

void setup() {
  Serial.begin(115200);

  // Cargar el modelo cuantizado
  model = tflite::GetModel(mnist_model_quant);
  if (model->version() != TFLITE_SCHEMA_VERSION) {
    Serial.println("Modelo incompatible");
    while (1);
  }

  // Configurar el intérprete
  static tflite::MicroMutableOpResolver<10> resolver;
  tflite::MicroInterpreter static_interpreter(
      model, resolver, tensor_arena, kTensorArenaSize, nullptr);
  interpreter = &static_interpreter;

  // Asignar tensores
  interpreter->AllocateTensors();

  // Obtener referencias a los tensores de entrada y salida
  input = interpreter->input(0);
  output = interpreter->output(0);
}

void loop() {
  // Preprocesar los datos de entrada
  // En un caso real, aquí se capturan y preprocesan los datos de entrada

  // Ejecutar la inferencia
  TfLiteStatus invoke_status = interpreter->Invoke();
  if (invoke_status != kTfLiteOk) {
    Serial.println("Error en la inferencia");
    return;
  }

  // Procesar la salida
  for (int i = 0; i < 10; i++) {
    Serial.print("Clase ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(output->data.f[i], 6);
  }

  delay(2000);  // Esperar antes de la siguiente inferencia
}

Finalmente se puede compilar y subir el código a la ESP32 y realizar las validaciones.