Aprendizaje automático con Node.js utilizando la biblioteca Tensorflow.js

Hola a todos, colegas!

Quizás los fanáticos de la biblioteca Tensorflow, que ya notaron este libro en nuestro pedido anticipado, también observaron de cerca las posibilidades de aprendizaje automático y profundo en el navegador, especialmente porque el propio Francois Schollet no ignoró el tema. Invitamos a los interesados ​​en el gato, que explica cómo se reconocen las imágenes utilizando la biblioteca Tensorflow.js.

TensorFlow.js es una nueva versión de la popular biblioteca de código abierto que enriquece JavaScript con capacidades de aprendizaje profundo. Los desarrolladores ahora pueden definir, entrenar y ejecutar modelos utilizando la API de biblioteca de alto nivel .

Gracias a los modelos previamente entrenados, los desarrolladores ahora pueden resolver fácilmente tareas complejas como el reconocimiento de patrones , la generación de música o la determinación de posiciones humanas en solo unas pocas líneas de JavaScript.

Tensorflow.js comenzó como una biblioteca front-end para trabajar en un navegador, pero este año se agregó soporte experimental para Node.js. Por lo tanto, TensorFlow.js también se puede utilizar en aplicaciones de back-end de JavaScript, lo que nos evita por completo tener que recurrir a Python.

Al leer sobre esta biblioteca, decidí probarla en una tarea simple ...
Use TensorFlow.js para el reconocimiento visual de imágenes en imágenes cuando use JavaScript de Node.js
Desafortunadamente, la documentación y los ejemplos de código describen principalmente el uso de esta biblioteca en el navegador. Tuve que pasar mucho tiempo para leer bien las fuentes de Script para esta biblioteca.

Sin embargo, después de unos días de swotting, ¡todavía lo hice! ¡Hurra!

Antes de pasar a un análisis detallado del código, hablemos de otras implementaciones de la biblioteca TensorFlow.

Tensorflow

TensorFlow es una biblioteca de software gratuita para aplicaciones de aprendizaje automático. TensorFlow se puede usar para crear redes neuronales e implementar otros algoritmos de aprendizaje profundo.

Esta es una biblioteca lanzada por Google en noviembre de 2015, originalmente escrita en Python . Para la capacitación y evaluación de modelos creados, utiliza cálculos en una CPU o GPU. Inicialmente, esta biblioteca fue creada para trabajar en servidores de alto rendimiento utilizando GPU de uso intensivo de recursos.

Las actualizaciones recientes han permitido optimizar esta biblioteca y usarla en entornos con recursos más limitados, por ejemplo, en dispositivos móviles y navegadores web.

TensorFlow Lite

Tensorflow Lite , la versión lite de esta biblioteca para dispositivos móviles y sistemas integrados, se lanzó en mayo de 2017. Junto con él, se proporciona un nuevo conjunto de modelos profundos previamente entrenados para tareas relacionadas con el reconocimiento de patrones; Esta colección se llama MobileNet . Los modelos MobileNet se han diseñado específicamente para un funcionamiento eficiente en entornos con una cantidad limitada de recursos, como dispositivos móviles.

TensorFlow.js

Después de Tensorflow Lite, TensorFlow.js se anunció en marzo de 2018. Esta versión de la biblioteca está diseñada para funcionar en un navegador y se basa en un proyecto anterior llamado deeplearn.js . WebGL proporciona acceso de GPU a la biblioteca. Los desarrolladores usan la API de JavaScript para entrenar, cargar y ejecutar modelos.

Más tarde, TensorFlow.js se expandió para trabajar con Node.js, para esto se utiliza el complemento de biblioteca tfjs-node .

Importe modelos existentes en TensorFlow.js

Los modelos de TensorFlow y Keras listos para usar se pueden ejecutar utilizando la biblioteca TensorFlow.js. Antes de ejecutar el modelo, debe convertir a un nuevo formato con esta herramienta . Los modelos preformados y transformados para clasificar imágenes, definir poses y detectar vecinos más cercanos están disponibles en Github .

Usando TensorFlow.js con Node.js

Instalar bibliotecas TensorFlow

TensorFlow.js se puede instalar desde el registro NPM .


 npm install @tensorflow/tfjs @tensorflow/tfjs-node // ... npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu 

Ambas extensiones para Node.js usan dependencias nativas, que se compilarán a pedido.

Descargar TensorFlow Libraries

La API de JavaScript para Tensorflow se proporciona desde la biblioteca principal. No se proporcionan API de extensión en los módulos de extensión que admiten Node.js.

  const tf = require('@tensorflow/tfjs') //   ( CPU) require('@tensorflow/tfjs-node') //    ( GPU) require('@tensorflow/tfjs-node-gpu') 

Descargar modelos TensorFlow

TensorFlow.js proporciona una biblioteca NPM ( tfjs-models ) que simplifica la carga de tfjs-models pre-entrenados y transformados para clasificar imágenes , definir poses y detectar vecinos k-más cercanos .

El modelo de clasificación de imágenes de MobileNet es una red neuronal profunda entrenada para distinguir entre 1000 clases diferentes de imágenes .

En el archivo README para el proyecto como ejemplo , el siguiente código se usa para cargar el modelo.

 import * as mobilenet from '@tensorflow-models/mobilenet'; //   const model = await mobilenet.load(); 

Uno de los primeros problemas que encontré es que este código no funciona con Node.js.

 Error: browserHTTPRequest is not supported outside the web browser. 

Después de examinar el código fuente , vemos que la biblioteca mobilenet es un contenedor para la clase tf.Model . Cuando se lo llama, el método load() descarga automáticamente los archivos de modelo necesarios ubicados en una dirección HTTP externa y crea una instancia del modelo TensorFlow.

La extensión Node.js en el momento de la escritura aún no admitía solicitudes HTTP para la recuperación de modelos dinámicos. Todo lo que quedaba era cargar manualmente los modelos en el sistema de archivos.

Sin embargo, después de leer el código fuente de la biblioteca, encontré una solución ...

Descargar modelos del sistema de archivos

Si la clase MobileNet se crea manualmente, no puede llamar al método de load del módulo, sino reescribir la path variable generada automáticamente path contiene la dirección HTTP del modelo, reemplazando esta dirección con la ruta local en el sistema de archivos. Después de eso, cuando se llama al método de load en la instancia de clase, se disparará la clase del cargador del sistema de archivos ; en este caso, nos negamos a usar un descargador HTTP basado en navegador.

 const path = "mobilenet/model.json" const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load() 

¡Genial, todo funciona!

Pero, ¿de dónde vienen los archivos del modelo?

Modelos MobileNet

Los modelos para TensorFlow.js consisten en dos tipos de archivos: un archivo de configuración de modelo almacenado en formato JSON y pesos de modelo almacenados en formato binario. Los pesos del modelo a menudo se fragmentan en muchas partes para optimizar el almacenamiento en caché del navegador.

Después de considerar el código de descarga automática para los modelos MobileNet, vemos que los modelos, sus configuraciones y fragmentos de peso se extraen del contenedor público en la siguiente dirección.

 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v${version}_${alpha}_${size}/ 

Los parámetros de la plantilla en la URL describen las versiones del modelo enumeradas aquí . La precisión de clasificación resultante también se muestra en la misma página.

El código fuente indica que solo los modelos de MobileNet v1 pueden descargarse usando la tensorflow-models/mobilenet .

El código de extracción HTTP descarga el archivo model.json desde la ubicación de almacenamiento y luego selecciona recursivamente todos los fragmentos de los modelos con pesos referenciados. Estos son archivos en el formato groupX-shard1of1 .

Descarga manual de modelos

Si desea guardar todos los archivos de modelo en el sistema de archivos, puede hacer esto: extraer el archivo de configuración del modelo, analizar la sintaxis de todos los archivos ponderados a los que se hace referencia en el archivo de configuración y luego descargar cada archivo ponderado manualmente.
Iba a usar el módulo MobileNet V1 con un valor alfa de 1.0 y una imagen de 224 píxeles . Entonces obtengo la siguiente URL para el archivo de configuración del modelo.

 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/model.json 

Una vez que este archivo se descarga localmente, puede usar la herramienta jq para analizar los nombres de todos los archivos ponderados.

 $ cat model.json | jq -r ".weightsManifest[].paths[0]" group1-shard1of1 group2-shard1of1 group3-shard1of1 ... 

Con la herramienta sed , puede prefijar el nombre de cada elemento HTTP con una URL para generar una URL para cada archivo de peso.

 $ cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group1-shard1of1 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group2-shard1of1 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group3-shard1of1 ... 

Los comandos parallel y curl le permiten descargar todos estos archivos a mi directorio local.

 cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' | parallel curl -O 

Clasificación de la imagen

Este código de muestra proporcionado con TensorFlow.js muestra cómo devolver el resultado de la clasificación de imágenes.

 const img = document.getElementById('img'); //   const predictions = await model.classify(img); 

Esto no funciona en Node.js debido a la falta de soporte DOM.

El método de classify acepta varios elementos DOM ( canvas , video , image ) y extrae y convierte automáticamente los bytes de "imagen" de estos elementos a la clase tf.Tensor3D , utilizada como entrada de modelo. Alternativamente, la tf.Tensor3D se puede transmitir directamente.

Decidí no intentar usar un paquete externo para simular un elemento DOM manualmente, pero descubrí que tf.Tensor3D más fácil de ensamblar manualmente .

Generamos Tensor3D a partir de la imagen.

Al leer el código fuente del método utilizado para convertir elementos DOM a clases Tensor3D, encontramos que los siguientes parámetros de entrada se utilizan para generar la clase Tensor3D.

 const values = new Int32Array(image.height * image.width * numChannels); //     ,    const outShape = [image.height, image.width, numChannels]; const input = tf.tensor3d(values, outShape, 'int32'); 

pixels es una matriz de tipo (Int32Array) contiene una lista secuencial de valores de canal para cada píxel. numChannels es el número de valores de canal por píxel.

Crear valores de entrada para JPEG

La biblioteca jpeg-js es un codificador / decodificador JPEG para Node.js escrito en JavaScript puro. Con esta biblioteca, puede extraer valores RGB para cada píxel.

 const pixels = jpeg.decode(buffer, true); 

Como resultado, obtenemos un Uint8Array con cuatro valores de canal ( RGBA ) para cada píxel ( width * height ). El modelo MobileNet usa solo tres canales de color ( RGB ) para la clasificación, el canal alfa se ignora. Este código convierte una matriz de cuatro canales en una verdadera versión de tres canales.

  const numChannels = 3; const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } } 

Requisitos de entrada para modelos MobileNet

El modelo de MobileNet utilizado aquí clasifica las imágenes de 224 píxeles de alto y ancho. Los tensores de entrada deben contener valores de coma flotante en el rango de -1 a 1 para cada uno de los tres valores de canal de cada píxel.

Los valores de entrada para imágenes con una dimensión diferente deben convertirse al tamaño correcto antes de la clasificación. Además, los valores de píxeles obtenidos del decodificador JPEG están en el rango de 0 a 255, no de -1 a 1. Estos valores también deben convertirse antes de la clasificación.

TensorFlow.js tiene métodos de biblioteca para simplificar este proceso, pero, aún mejor, ¡hay una tfjs-models/mobilenet especial tfjs-models/mobilenet que resuelve automáticamente este problema !

El desarrollador puede pasar los Tensor3D de entrada de tipo int32 , así como varias dimensiones al método de classify , que traduce los valores de entrada al formato correcto antes de la clasificación. Es decir, no tenemos nada que hacer aquí. Genial

Obteniendo predicciones

Los modelos MobileNet de Tensorflow aprenden a reconocer objetos de las 1000 clases más importantes del conjunto de datos de ImageNet . En la salida del modelo, proporcione valores probabilísticos que caractericen cuáles son las posibilidades de encontrar estos objetos en la imagen clasificada.

En este archivo se encuentra una lista completa de clases capacitadas para el modelo utilizado .

La tfjs-models/mobilenet ofrece el método de classify en la clase MobileNet , que devuelve la X superior de las clases más probables, según lo que se muestra en la imagen.

 const predictions = await mn_model.classify(input, 10); 

predictions es una matriz de clases X y probabilidades en el siguiente formato.

  { className: 'panda', probability: 0.9993536472320557 } 

Ejemplo

Entonces, hemos descubierto cómo usar la biblioteca TensorFlow.js y los modelos MobileNet en Node.js, y ahora veamos cómo este script clasifica la imagen especificada como un argumento de línea de comandos.

Código fuente

Guarde este archivo de script y el descriptor del paquete en archivos locales.

 { "name": "tf-js", "version": "1.0.0", "main": "script.js", "license": "MIT", "dependencies": { "@tensorflow-models/mobilenet": "^0.2.2", "@tensorflow/tfjs": "^0.12.3", "@tensorflow/tfjs-node": "^0.1.9", "jpeg-js": "^0.3.4" } } 

 const tf = require('@tensorflow/tfjs') const mobilenet = require('@tensorflow-models/mobilenet'); require('@tensorflow/tfjs-node') const fs = require('fs'); const jpeg = require('jpeg-js'); const NUMBER_OF_CHANNELS = 3 const readImage = path => { const buf = fs.readFileSync(path) const pixels = jpeg.decode(buf, true) return pixels } const imageByteArray = (image, numChannels) => { const pixels = image.data const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } } return values } const imageToInput = (image, numChannels) => { const values = imageByteArray(image, numChannels) const outShape = [image.height, image.width, numChannels]; const input = tf.tensor3d(values, outShape, 'int32'); return input } const loadModel = async path => { const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load() return mn } const classify = async (model, path) => { const image = readImage(path) const input = imageToInput(image, NUMBER_OF_CHANNELS) const mn_model = await loadModel(model) const predictions = await mn_model.classify(input) console.log('classification results:', predictions) } if (process.argv.length !== 4) throw new Error('incorrect arguments: node script.js <MODEL> <IMAGE_FILE>') classify(process.argv[2], process.argv[3]) 

Prueba

Descargue los archivos del modelo en el directorio de mobilenet siguiendo las instrucciones anteriores.
Establecer dependencias del proyecto usando NPM

npm install

Descargue un archivo JPEG de muestra para clasificarlo

wget http://bit.ly/2JYSal9 -O panda.jpg



Ejecute el script, cuyos argumentos serán el archivo del modelo y la imagen de entrada.

node script.js mobilenet/model.json panda.jpg

Si todo funcionó correctamente, la siguiente salida debería aparecer en la consola.

  classification results: [ { className: 'giant panda, panda, panda bear, coon bear', probability: 0.9993536472320557 } ] 

¡La imagen está clasificada correctamente como que contiene un panda con una probabilidad del 99,93%!

Conclusión

La biblioteca TensorFlow.js abre oportunidades de aprendizaje profundo para los desarrolladores de JavaScript. El uso de modelos previamente entrenados con la biblioteca TensorFlow.js le permite construir fácilmente en aplicaciones JavaScript nuevas funciones para resolver problemas complejos de aprendizaje automático, con un esfuerzo mínimo y un código conciso.

La biblioteca TensorFlow.js se creó exclusivamente para trabajar en un navegador, pero ahora interactúa con Node.js, aunque no todas las herramientas y utilidades admiten este nuevo tiempo de ejecución. Después de jugar con la biblioteca durante varios días, aprendí a usarla con los modelos MobileNet para el reconocimiento visual de imágenes de un archivo local.

Source: https://habr.com/ru/post/es432984/


All Articles