TensorFlow.js: Convierte un modelo guardado de Python en un formato de TensorFlow.js

1. Introducción

Ya diste tus primeros pasos con TensorFlow.js, probaste nuestros modelos prediseñados o incluso creaste el tuyo propio, pero viste que se publicó una investigación de vanguardia en Python y tienes curiosidad por saber si se ejecutará en el navegador web para que esa idea genial que tuviste se convierta en realidad para millones de personas de forma escalable. ¿Te suena familiar? Si es así, este es el codelab para ti.

El equipo de TensorFlow.js creó una herramienta conveniente para convertir modelos en formato SavedModel a TensorFlow.js a través de un conversor de línea de comandos, de modo que puedas disfrutar del uso de estos modelos con el alcance y la escala de la Web.

Qué aprenderás

En este lab de código, aprenderás a usar el convertidor de línea de comandos de TensorFlow.js para transferir un SavedModel generado en Python al formato model.json que se requiere para la ejecución del lado del cliente en un navegador web.

Específicamente, son las siguientes:

  • Cómo crear un modelo de AA simple en Python y guardarlo en el formato requerido por el convertidor de TensorFlow.js
  • Cómo instalar y usar el convertidor de TensorFlow.js en el modelo guardado que exportaste desde Python
  • Toma los archivos resultantes de la conversión y úsalos en tu aplicación web de JS.
  • Comprende qué hacer cuando algo sale mal (no todos los modelos se convertirán) y qué opciones tienes.

Imagina poder tomar una investigación recién publicada y poner ese modelo a disposición de millones de desarrolladores de JS en todo el mundo. O tal vez lo uses tú mismo en tu propia creación, que cualquier persona del mundo podrá experimentar si se ejecuta en el navegador web, ya que no se requieren dependencias complejas ni configuración del entorno. ¿Todo listo para comenzar a hackear? ¡Vamos!

Comparte con nosotros lo que conviertas.

Puedes usar lo que aprendamos hoy para intentar convertir algunos de tus modelos favoritos de Python. Si logras hacerlo con éxito y creas un sitio web de demostración funcional del modelo en acción, etiquétanos en las redes sociales con el hashtag #MadeWithTFJS para tener la oportunidad de que se incluya tu proyecto en el Blog de TensorFlow o, incluso, en futuros eventos de Show & Tell. Nos encantaría ver más investigaciones increíbles portadas a la Web y permitir que una mayor cantidad de personas usen esos modelos de formas innovadoras o creativas, como en este gran ejemplo.

2. ¿Qué es TensorFlow.js?

1aee0ede85885520.png

TensorFlow.js es una biblioteca de aprendizaje automático de código abierto que se puede ejecutar en cualquier lugar donde se pueda ejecutar JavaScript. Se basa en la biblioteca original de TensorFlow escrita en Python y tiene como objetivo recrear esta experiencia del desarrollador y este conjunto de APIs para el ecosistema de JavaScript.

¿Dónde se puede usar?

Gracias a la portabilidad de JavaScript, ahora puedes escribir en 1 idioma y realizar aprendizaje automático en todas las siguientes plataformas con facilidad:

  • Lado del cliente en el navegador web con JavaScript estándar
  • Dispositivos del servidor y hasta de IoT, como Raspberry Pi, con Node.js
  • Apps para computadoras que usan Electron
  • Apps nativas para dispositivos móviles con React Native

TensorFlow.js también admite varios backends dentro de cada uno de estos entornos (los entornos basados en hardware real en los que se puede ejecutar, como la CPU o WebGL, por ejemplo). En este contexto, un "backend" no significa un entorno del servidor (por ejemplo, el backend para la ejecución podría ser del cliente en WebGL) para garantizar la compatibilidad y mantener todo en funcionamiento rápido. Actualmente, TensorFlow.js admite lo siguiente:

  • Ejecución de WebGL en la tarjeta gráfica del dispositivo (GPU): Esta es la forma más rápida de ejecutar modelos más grandes (de más de 3 MB) con aceleración de GPU.
  • Ejecución de WebAssembly (WASM) en la CPU: Para mejorar el rendimiento de la CPU en todos los dispositivos, incluidos los teléfonos celulares de generaciones anteriores, por ejemplo. Esto es más adecuado para modelos más pequeños (menos de 3 MB de tamaño) que pueden ejecutarse más rápido en la CPU con WASM que con WebGL debido a la sobrecarga de subir contenido a un procesador de gráficos.
  • Ejecución de CPU: Es la alternativa en caso de que no esté disponible ninguno de los otros entornos. Es el más lento de los tres, pero siempre está disponible.

Nota: Puedes forzar uno de estos backends si sabes en qué dispositivo se ejecutará el código o, simplemente, dejar que TensorFlow.js decida por ti si no especificas esta opción.

Superpoderes del cliente

Ejecutar TensorFlow.js en el navegador web de la máquina del cliente puede generar varios beneficios que vale la pena tener en cuenta.

Privacidad

Puedes entrenar y clasificar datos en la máquina del cliente sin enviar datos a un servidor web de terceros. En ocasiones, esto puede ser un requisito para cumplir con las leyes locales, como el RGPD, por ejemplo, o cuando se procesan datos que el usuario puede querer conservar en su máquina y no enviar a un tercero.

Velocidad

Como no tienes que enviar datos a un servidor remoto, la inferencia (el acto de clasificar los datos) puede ser más rápida. Aún mejor, tienes acceso directo a los sensores del dispositivo, como la cámara, el micrófono, el GPS, el acelerómetro y muchos más, si el usuario te otorga acceso.

Alcance y escala

Con un solo clic, cualquier persona del mundo puede hacer clic en un vínculo que le envíes, abrir la página web en su navegador y usar lo que creaste. No es necesario realizar una configuración compleja de Linux del servidor con controladores CUDA y mucho más solo para usar el sistema de aprendizaje automático.

Costo

Sin servidores, lo único que debes pagar es una CDN para alojar tus archivos HTML, CSS, JS y de modelo. El costo de una CDN es mucho menor que el de mantener un servidor (posiblemente con una tarjeta gráfica conectada) en funcionamiento las 24 horas, todos los días.

Funciones del servidor

Aprovechar la implementación de TensorFlow.js en Node.js permite las siguientes funciones.

Compatibilidad total con CUDA

En el servidor, para la aceleración de la tarjeta gráfica, debes instalar los controladores de NVIDIA CUDA para habilitar TensorFlow para que funcione con la tarjeta gráfica (a diferencia del navegador, que usa WebGL, no se necesita instalación). Sin embargo, con la compatibilidad total con CUDA, puedes aprovechar al máximo las capacidades de nivel inferior de la tarjeta gráfica, lo que genera tiempos de entrenamiento y de inferencia más rápidos. El rendimiento es similar al de la implementación de TensorFlow en Python, ya que ambos comparten el mismo backend de C++.

Tamaño del modelo

En el caso de los modelos de vanguardia de la investigación, es posible que trabajes con modelos muy grandes, tal vez de gigabytes de tamaño. Actualmente, estos modelos no se pueden ejecutar en el navegador web debido a las limitaciones de uso de memoria por pestaña del navegador. Para ejecutar estos modelos más grandes, puedes usar Node.js en tu propio servidor con las especificaciones de hardware que necesitas para ejecutar un modelo de este tipo de manera eficiente.

IOT

Node.js es compatible con computadoras de placa única populares, como la Raspberry Pi, lo que significa que también puedes ejecutar modelos de TensorFlow.js en esos dispositivos.

Velocidad

Node.js está escrito en JavaScript, lo que significa que se beneficia de la compilación Just-in-Time. Esto significa que, a menudo, puedes observar mejoras en el rendimiento cuando usas Node.js, ya que se optimizará en el tiempo de ejecución, en especial para cualquier preprocesamiento que realices. Un gran ejemplo de esto se puede ver en este caso de estudio, que muestra cómo Hugging Face usó Node.js para duplicar el rendimiento de su modelo de procesamiento de lenguaje natural.

Ahora que comprendes los conceptos básicos de TensorFlow.js, dónde se puede ejecutar y algunos de sus beneficios, comencemos a hacer cosas útiles con él.

3. Cómo configurar el sistema

En este instructivo, usaremos Ubuntu, una distribución popular de Linux que usan muchas personas y que está disponible en Compute Engine de Google Cloud como una imagen base si decides seguir los pasos en una máquina virtual basada en la nube.

En el momento de escribir este artículo, podemos seleccionar la imagen de Ubuntu 18.04.4 LTS cuando creamos una instancia nueva de Compute Engine, que es lo que usaremos. Por supuesto, puedes usar tu propia máquina o incluso un sistema operativo diferente si lo deseas, pero las instrucciones de instalación y las dependencias pueden variar entre los sistemas.

Instala TensorFlow (versión de Python)

Ahora bien, como probablemente estés intentando convertir algún modelo existente basado en Python que encontraste o que escribirás, antes de que podamos exportar un archivo "SavedModel" desde Python, deberás configurar la versión de Python de TensorFlow en tu instancia si el "SavedModel" aún no está disponible para su descarga.

Establece una conexión SSH a tu máquina en la nube que creaste anteriormente y, luego, escribe lo siguiente en la ventana de la terminal:

Ventana de la terminal:

sudo apt update
sudo apt-get install python3

Esto garantizará que tengamos Python 3 instalado en la máquina. Para usar TensorFlow, debes tener instalado Python 3.4 o una versión posterior.

Para verificar que se haya instalado la versión correcta, escribe lo siguiente:

Ventana de la terminal:

python3 --version

Deberías ver un resultado que indique el número de versión, como Python 3.6.9. Si ves que se imprimió correctamente y es superior a 3.4, puedes continuar.

A continuación, instalaremos PIP para Python 3, que es el administrador de paquetes de Python, y luego lo actualizaremos. Tipo:

Ventana de la terminal:

sudo apt install python3-pip
pip3 install --upgrade pip

Nuevamente, podemos verificar la instalación de pip3 con el siguiente comando:

Ventana de la terminal:

pip3 --version

En el momento de escribir este artículo, vemos que pip 20.2.3 se imprime en la terminal después de ejecutar este comando.

Antes de instalar TensorFlow, se requiere que el paquete de Python "setuptools" sea de la versión 41.0.0 o posterior. Ejecuta el siguiente comando para asegurarte de que se actualizó a la versión más reciente:

Ventana de la terminal:

pip3 install -U setuptools

Por último, ahora podemos instalar TensorFlow para Python:

Ventana de la terminal:

pip3 install tensorflow

Este proceso puede tardar un poco en completarse, así que espera hasta que termine de ejecutarse.

Comprobemos que TensorFlow se haya instalado correctamente. Crea un archivo de Python llamado test.py en tu directorio actual:

Ventana de la terminal:

nano test.py

Una vez que se abra nano, podemos escribir código en Python para imprimir la versión de TensorFlow instalada:

test.py:

import tensorflow as tf
print(tf.__version__)

Presiona CTRL + O para escribir los cambios en el disco y, luego, CTRL + X para salir del editor nano.

Ahora podemos ejecutar este archivo de Python para ver la versión de TensorFlow que se imprimió en la pantalla:

Ventana de la terminal:

python3 test.py

En el momento de escribir este artículo, vemos que se imprimió 2.3.1 en la consola para nuestra versión de TensorFlow Python instalada.

4. Cómo crear un modelo de Python

En el siguiente paso de este codelab, se explicará cómo crear un modelo simple de Python para mostrar cómo podemos guardar este modelo entrenado resultante en formato "SavedModel" y, luego, usarlo con nuestro convertidor de línea de comandos de TensorFlow.js. El principio sería similar para cualquier modelo de Python que intentes convertir, pero mantendremos este código simple para que todos puedan comprenderlo.

Editemos el archivo test.py que creamos en la primera sección y actualicemos el código de la siguiente manera:

test.py:

import tensorflow as tf
print(tf.__version__)

# Import NumPy - package for working with arrays in Python.
import numpy as np

# Import useful keras functions - this is similar to the
# TensorFlow.js Layers API functionality.
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense

# Create a new dense layer with 1 unit, and input shape of [1].
layer0 = Dense(units=1, input_shape=[1])
model = Sequential([layer0])

# Compile the model using stochastic gradient descent as optimiser
# and the mean squared error loss function.
model.compile(optimizer='sgd', loss='mean_absolute_error')

# Provide some training data! Here we are using some fictional data 
# for house square footage and house price (which is simply 1000x the 
# square footage) which our model must learn for itself.
xs = np.array([800.0, 850.0, 900.0, 950.0, 980.0, 1000.0, 1050.0, 1075.0, 1100.0, 1150.0, 1200.0, 1250.0, 1300.0, 1400.0, 1500.0, 1600.0, 1700.0, 1800.0, 1900.0, 2000.0], dtype=float)

ys = np.array([800000.0, 850000.0, 900000.0, 950000.0, 980000.0, 1000000.0, 1050000.0, 1075000.0, 1100000.0, 1150000.0, 1200000.0,  1250000.0, 1300000.0, 1400000.0, 1500000.0, 1600000.0, 1700000.0, 1800000.0, 1900000.0, 2000000.0], dtype=float)

# Train the model for 500 epochs.
model.fit(xs, ys, epochs=500, verbose=0)

# Test the trained model on a test input value
print(model.predict([1200.0]))

# Save the model we just trained to the "SavedModel" format to the
# same directory our test.py file is located.
tf.saved_model.save(model, './')

Este código entrenará una regresión lineal muy simple para aprender a estimar la relación entre las X (entradas) y las Y (salidas) proporcionadas. Luego, guardaremos el modelo entrenado resultante en el disco. Consulta los comentarios intercalados para obtener más detalles sobre lo que hace cada línea.

Si revisamos nuestro directorio después de ejecutar este programa (con python3 test.py), ahora deberíamos ver algunos archivos y carpetas nuevos creados en nuestro directorio actual:

  • test.py
  • saved_model.pb
  • recursos
  • variables

Ahora generamos los archivos que necesita el conversor de TensorFlow.js para convertir este modelo y ejecutarlo en el navegador.

5. Cómo convertir un modelo guardado al formato de TensorFlow.js

Instala el convertidor de TensorFlow.js

Para instalar el convertidor, ejecuta el siguiente comando:

Ventana de la terminal:

pip3 install tensorflowjs

Eso fue fácil.

Si suponemos que usamos el convertidor de línea de comandos (tensorflowjs_converter) y no la versión del asistente que se mostró anteriormente, podemos llamar al siguiente comando para convertir el modelo guardado que acabamos de crear y pasar explícitamente los parámetros al convertidor:

Ventana de la terminal:

tensorflowjs_converter \
    --input_format=keras_saved_model \
    ./ \
    ./predict_houses_tfjs

¿Qué sucede aquí? Primero, llamamos al archivo binario tensorflowjs_converter que acabamos de instalar y especificamos que intentamos convertir un modelo guardado de Keras.

En el código de ejemplo anterior, observarás que importamos Keras y usamos sus APIs de capas de nivel superior para crear nuestro modelo. Si no usaste Keras en tu código de Python, es posible que desees usar un formato de entrada diferente:

  • keras: Para cargar el formato de Keras (tipo de archivo HDF5)
  • tf_saved_model: Para cargar el modelo que usa las APIs principales de TensorFlow en lugar de Keras.
  • tf_frozen_model: Para cargar un modelo que contiene pesos inmovilizados.
  • tf_hub: Para cargar un modelo generado desde TensorFlow Hub.

Obtén más información sobre estos otros formatos aquí.

Los siguientes 2 parámetros especifican en qué carpeta se encuentra el modelo guardado. En nuestra demostración anterior, especificamos el directorio actual y, luego, especificamos el directorio en el que deseamos generar nuestra conversión, que especificamos anteriormente como una carpeta llamada "predict_houses_tfjs" en el directorio actual.

Si ejecutas el comando anterior, se creará una carpeta nueva en el directorio actual llamada predict_houses_tfjs que contiene:.

  • model.json
  • Group1-shard1of1.bin

Estos son los archivos que necesitamos para ejecutar el modelo en el navegador web. Guarda estos archivos, ya que los usaremos en la siguiente sección.

6. Cómo usar nuestro modelo convertido en el navegador

Aloja los archivos convertidos

Primero, debemos colocar los archivos model.json y *.bin que se generaron en un servidor web para poder acceder a ellos a través de nuestra página web. Para esta demostración, usaremos Glitch.com para que te resulte fácil seguir los pasos. Sin embargo, si tienes experiencia en ingeniería web, puedes iniciar un servidor HTTP simple en tu instancia actual de Ubuntu Server para hacerlo. La decisión es tuya.

Cómo subir archivos a Glitch

  1. Accede a Glitch.com.
  2. Usa este vínculo para clonar nuestro proyecto de plantilla de TensorFlow.js. Contiene archivos HTML, CSS y JS de esqueleto que importan la biblioteca de TensorFlow.js para que la usemos.
  3. Haz clic en la carpeta "recursos" en el panel de la izquierda.
  4. Haz clic en “Subir un activo” y selecciona group1-shard1of1.bin para subirlo a esta carpeta. Una vez que se suba, debería verse así: 25a2251c7f165184.png
  5. Si haces clic en el archivo group1-shard1of1.bin que acabas de subir, podrás copiar la URL a su ubicación. Copia esta ruta de acceso ahora como se muestra: 92ded8d46442c404.png
  6. Ahora edita model.json con tu editor de texto favorito en tu máquina local y busca (con CTRL+F) el archivo group1-shard1of1.bin, que se mencionará en algún lugar del archivo.

Reemplaza este nombre de archivo por la URL que copiaste en el paso 5, pero borra el https://cdn.glitch.com/ inicial que genera Glitch a partir de la ruta de acceso copiada.

Después de editarlo, debería verse de la siguiente manera (observa cómo se quitó la ruta del servidor inicial, por lo que solo se conserva el nombre de archivo subido resultante): d5a338f2dc1f31d4.png 7. Ahora, guarda y sube este archivo model.json editado a Glitch. Para ello, haz clic en Recursos y, luego, en el botón "Subir un recurso" (importante). Si no usas el botón físico y arrastras y sueltas, se subirá como un archivo editable en lugar de en la CDN, que no estará en la misma carpeta, y se supondrá la ruta relativa cuando TensorFlow.js intente descargar los archivos binarios para un modelo determinado. Si lo hiciste correctamente, deberías ver 2 archivos en la carpeta assets, como se muestra a continuación: 51a6dbd5d3097ffc.png

¡Genial! Ahora podemos usar los archivos guardados con código real en el navegador.

Carga el modelo

Ahora que alojamos nuestros archivos convertidos, podemos escribir una página web simple para cargar estos archivos y usarlos para hacer una predicción. Abre script.js en la carpeta del proyecto de Glitch y reemplaza el contenido de este archivo por lo siguiente después de cambiar const MODEL_URL para que apunte al vínculo generado de Glitch.com para tu archivo model.json que subiste a Glitch:

script.js:

// Grab a reference to our status text element on the web page.
// Initially we print out the loaded version of TFJS.
const status = document.getElementById('status');
status.innerText = 'Loaded TensorFlow.js - version: ' + tf.version.tfjs;

// Specify location of our Model.json file we uploaded to the Glitch.com CDN.
const MODEL_URL = YOUR MODEL.JSON URL HERE! CHANGE THIS!';
// Specify a test value we wish to use in our prediction.
// Here we use 950, so we expect the result to be close to 950,000.
const TEST_VALUE = 950.0

// Create an asynchronous function.
async function run() {
    // Load the model from the CDN.
    const model = await tf.loadLayersModel(MODEL_URL);

    // Print out the architecture of the loaded model.
    // This is useful to see that it matches what we built in Python.
    console.log(model.summary());

    // Create a 1 dimensional tensor with our test value.
    const input = tf.tensor1d([TEST_VALUE]);

    // Actually make the prediction.
    const result = model.predict(input);

    // Grab the result of prediction using dataSync method
    // which ensures we do this synchronously.
    status.innerText = 'Input of ' + TEST_VALUE + 
        'sqft predicted as $' + result.dataSync()[0];
}

// Call our function to start the prediction!
run();

Si ejecutas el código anterior después de cambiar la constante MODEL_URL para que apunte a la ruta de acceso de model.json, obtendrás el siguiente resultado.

c5e8457213058ec3.png

Si inspeccionamos la consola del navegador web (presiona F12 para abrir las herramientas para desarrolladores en el navegador), también podemos ver la descripción del modelo cargado, que imprime lo siguiente:

35e79d70dbd66f27.png

Si comparamos esto con nuestro código de Python al comienzo de este codelab, podemos confirmar que se trata de la misma red que creamos con 1 entrada densa y una capa densa con 1 nodo.

¡Felicitaciones! Acabas de ejecutar un modelo entrenado de Python convertido en el navegador web.

7. Modelos que no se convierten

Habrá ocasiones en las que no se admitirán para la conversión los modelos más complejos que se compilan para usar operaciones menos comunes. La versión de TensorFlow.js basada en el navegador es una reescritura completa de TensorFlow y, como tal, actualmente no admitimos todas las operaciones de bajo nivel que tiene la API de C++ de TensorFlow (hay miles), aunque, con el tiempo, se agregan más a medida que crecemos y las operaciones principales se vuelven más estables.

En el momento de escribir este documento, una de esas funciones en TensorFlow Python que genera una op no admitida cuando se exporta como un modelo guardado es linalg.diag. Si intentamos convertir un SavedModel que usa esto en Python (que admite las operaciones resultantes que produce), veremos un error similar al que se muestra a continuación:

5df94fc652393e00.png

Aquí podemos ver destacado en rojo que la llamada a linalg.diag se compiló para producir una operación llamada MatrixDiagV3, que no es compatible con TensorFlow.js en el navegador web en el momento de escribir este codelab.

¿Qué hacer?

Tienes dos opciones.

  1. Implementa esta operación faltante en TensorFlow.js. Somos un proyecto de código abierto y aceptamos contribuciones para elementos como operaciones nuevas. Consulta esta guía para escribir nuevas operaciones para TensorFlow.js. Si logras hacerlo, puedes usar la marca Skip_op_check en nuestro convertidor de línea de comandos para ignorar este error y continuar con la conversión de todos modos (se supondrá que esta operación está disponible en la nueva compilación de TensorFlow.js que creaste y que admite la operación faltante).
  2. Determina qué parte de tu código de Python produjo la operación no admitida en el archivo savedmodel que exportaste. En un pequeño conjunto de código, esto puede ser fácil de ubicar, pero en modelos más complejos, podría requerir una investigación considerable, ya que actualmente no hay ningún método para identificar la llamada a la función de Python de alto nivel que produjo una operación determinada una vez en el formato de archivo savedmodel. Sin embargo, una vez que lo encuentres, puedes cambiarlo para usar otro método compatible.

8. Felicitaciones

¡Felicitaciones! Diste tus primeros pasos para usar un modelo de Python a través de TensorFlow.js en el navegador web.

Resumen

En este codelab, aprendimos a hacer lo siguiente:

  1. Configura nuestro entorno de Linux para instalar TensorFlow basado en Python
  2. Exporta un "SavedModel" de Python
  3. Instala el convertidor de línea de comandos de TensorFlow.js
  4. Usa el convertidor de línea de comandos de TensorFlow.js para crear los archivos del cliente necesarios
  5. Cómo usar los archivos generados en una aplicación web real
  6. Identifica los modelos que no se convertirán y qué se debería implementar para permitir que se conviertan en el futuro.

¿Qué sigue?

Recuerda etiquetar cualquiera de tus creaciones con #MadeWithTFJS para tener la oportunidad de aparecer en las redes sociales o en los futuros eventos de TensorFlow. Nos encantaría ver qué conviertes y usas en el cliente en el navegador.

Más Codelabs de TensorFlow.js para aprender más

Sitios web que puedes revisar