Plataforma y entorno

TensorFlow.js funciona en el navegador y en Node.js, y en ambas plataformas hay muchas configuraciones diferentes disponibles. Cada plataforma tiene un conjunto único de consideraciones que afectarán la forma en que se desarrollan las aplicaciones.

En el navegador, TensorFlow.js admite dispositivos móviles y de escritorio. Cada dispositivo tiene un conjunto específico de restricciones, como las API de WebGL disponibles, que se determinan y configuran automáticamente para usted.

En Node.js, TensorFlow.js admite el enlace directo a la API de TensorFlow o la ejecución con las implementaciones de CPU estándar más lentas.

Entornos

Cuando se ejecuta un programa TensorFlow.js, la configuración específica se denomina entorno. El entorno se compone de un único backend global, así como de un conjunto de indicadores que controlan las características detalladas de TensorFlow.js.

backends

TensorFlow.js admite múltiples backends diferentes que implementan almacenamiento de tensor y operaciones matemáticas. En un momento dado, solo un backend está activo. La mayoría de las veces, TensorFlow.js elegirá automáticamente el mejor backend para ti dado el entorno actual. Sin embargo, a veces es importante saber qué backend se está utilizando y cómo cambiarlo.

Para encontrar qué backend estás usando:

console.log(tf.getBackend());

Si desea cambiar manualmente el backend:

tf.setBackend('cpu');
console.log(tf.getBackend());

back-end de WebGL

El backend WebGL, 'webgl', es actualmente el backend más poderoso para el navegador. Este backend es hasta 100 veces más rápido que el backend de CPU estándar. Los tensores se almacenan como texturas WebGL y las operaciones matemáticas se implementan en sombreadores WebGL. Aquí hay algunas cosas útiles que debe saber al usar este backend: \

Evite bloquear el subproceso de la interfaz de usuario

Cuando se llama a una operación, como tf.matMul(a, b), el tf.Tensor resultante se devuelve sincrónicamente, sin embargo, es posible que el cálculo de la multiplicación de matrices aún no esté listo. Esto significa que el tf.Tensor devuelto es solo un identificador del cálculo. Cuando llama a x.data() o x.array() , los valores se resolverán cuando el cálculo realmente se haya completado. Esto hace que sea importante usar los métodos asincrónicos x.data() y x.array() sobre sus homólogos sincrónicos x.dataSync() y x.arraySync() para evitar bloquear el subproceso de la interfaz de usuario mientras se completa el cálculo.

Gestión de la memoria

Una advertencia al usar el backend de WebGL es la necesidad de una administración de memoria explícita. WebGLTextures, que es donde los datos de Tensor se almacenan en última instancia, no son automáticamente recolectados por el navegador.

Para destruir la memoria de un tf.Tensor , puede usar el método dispose() :

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();

Es muy común encadenar varias operaciones juntas en una aplicación. Mantener una referencia a todas las variables intermedias para eliminarlas puede reducir la legibilidad del código. Para resolver este problema, TensorFlow.js proporciona un método tf.tidy() que limpia todos los tf.Tensor que no devuelve una función después de ejecutarla, de forma similar a como se limpian las variables locales cuando se ejecuta una función:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
Precisión

En dispositivos móviles, es posible que WebGL solo admita texturas de coma flotante de 16 bits. Sin embargo, la mayoría de los modelos de aprendizaje automático se entrenan con pesos y activaciones de coma flotante de 32 bits. Esto puede causar problemas de precisión al migrar un modelo para un dispositivo móvil, ya que los números flotantes de 16 bits solo pueden representar números en el rango [0.000000059605, 65504] . Esto significa que debe tener cuidado de que los pesos y activaciones en su modelo no excedan este rango. Para verificar si el dispositivo admite texturas de 32 bits, verifique el valor de tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , si es falso, el dispositivo solo admite texturas de punto flotante de 16 bits. Puede usar tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') para verificar si TensorFlow.js está usando actualmente texturas de 32 bits.

Compilación de sombreadores y carga de texturas

TensorFlow.js ejecuta operaciones en la GPU mediante la ejecución de programas de sombreado WebGL. Estos sombreadores se ensamblan y compilan de forma perezosa cuando el usuario solicita ejecutar una operación. La compilación de un sombreador ocurre en la CPU del subproceso principal y puede ser lenta. TensorFlow.js almacenará en caché los sombreadores compilados automáticamente, haciendo que la segunda llamada a la misma operación con tensores de entrada y salida de la misma forma sea mucho más rápida. Por lo general, las aplicaciones de TensorFlow.js usarán las mismas operaciones varias veces durante la vida útil de la aplicación, por lo que el segundo paso a través de un modelo de aprendizaje automático es mucho más rápido.

TensorFlow.js también almacena datos de tf.Tensor como WebGLTextures. Cuando se crea un tf.Tensor , no subimos datos inmediatamente a la GPU, sino que mantenemos los datos en la CPU hasta que se usa el tf.Tensor en una operación. Si tf.Tensor se usa por segunda vez, los datos ya están en la GPU, por lo que no hay costo de carga. En un modelo típico de aprendizaje automático, esto significa que los pesos se cargan durante la primera predicción a través del modelo y la segunda pasada por el modelo será mucho más rápida.

Si te preocupa el rendimiento de la primera predicción a través de tu modelo o código TensorFlow.js, te recomendamos calentar el modelo pasando un tensor de entrada de la misma forma antes de usar los datos reales.

Por ejemplo:

const model = await tf.loadLayersModel(modelUrl);

// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();

// The second predict() will be much faster
const result = model.predict(userData);

Back-end de Node.js TensorFlow

En el backend de TensorFlow Node.js, 'node', la API C de TensorFlow se usa para acelerar las operaciones. Esto utilizará la aceleración de hardware disponible de la máquina, como CUDA, si está disponible.

En este backend, al igual que el backend de WebGL, las operaciones devuelven tf.Tensor s sincrónicamente. Sin embargo, a diferencia del backend de WebGL, la operación se completa antes de que recupere el tensor. Esto significa que una llamada a tf.matMul(a, b) bloqueará el subproceso de la interfaz de usuario.

Por esta razón, si tiene la intención de usar esto en una aplicación de producción, debe ejecutar TensorFlow.js en subprocesos de trabajo para no bloquear el subproceso principal.

Para obtener más información sobre Node.js, consulte esta guía.

back-end WASM

TensorFlow.js proporciona un backend de WebAssembly ( wasm ), que ofrece aceleración de CPU y se puede usar como una alternativa a los backends de CPU de JavaScript estándar ( cpu ) y WebGL acelerado ( webgl ). Para usarlo:

// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});

Si su servidor sirve el archivo .wasm en una ruta diferente o con un nombre diferente, use setWasmPath antes de inicializar el backend. Consulte la sección "Uso de paquetes" en el LÉAME para obtener más información:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
¿Por qué WASM?

WASM se introdujo en 2015 como un nuevo formato binario basado en la web, proporcionando programas escritos en JavaScript, C, C++, etc. un objetivo de compilación para ejecutar en la web. WASM ha sido compatible con Chrome, Safari, Firefox y Edge desde 2017, y es compatible con el 90 % de los dispositivos en todo el mundo.

Actuación

El backend de WASM aprovecha la biblioteca XNNPACK para una implementación optimizada de operadores de redes neuronales.

En comparación con JavaScript : los archivos binarios de WASM son generalmente mucho más rápidos que los paquetes de JavaScript para que los navegadores carguen, analicen y ejecuten. JavaScript se escribe dinámicamente y se recolecta basura, lo que puede causar ralentizaciones en el tiempo de ejecución.

Versus WebGL : WebGL es más rápido que WASM para la mayoría de los modelos, pero para modelos pequeños, WASM puede superar a WebGL debido a los costos generales fijos de ejecutar sombreadores de WebGL. La sección "Cuándo debo usar WASM" a continuación analiza la heurística para tomar esta decisión.

Portabilidad y Estabilidad

WASM tiene aritmética flotante portátil de 32 bits, que ofrece paridad de precisión en todos los dispositivos. WebGL, por otro lado, es específico del hardware y los diferentes dispositivos pueden tener una precisión variable (p. ej., respaldo a flotadores de 16 bits en dispositivos iOS).

Al igual que WebGL, WASM es oficialmente compatible con todos los principales navegadores. A diferencia de WebGL, WASM puede ejecutarse en Node.js y usarse en el lado del servidor sin necesidad de compilar bibliotecas nativas.

¿Cuándo debo usar WASM?

Tamaño del modelo y demanda computacional

En general, WASM es una buena opción cuando los modelos son más pequeños o le interesan los dispositivos de gama baja que carecen de compatibilidad con WebGL (extensión OES_texture_float ) o tienen GPU menos potentes. El siguiente gráfico muestra los tiempos de inferencia (a partir de TensorFlow.js 1.5.2) en Chrome en una MacBook Pro 2018 para 5 de nuestros modelos admitidos oficialmente en los backends WebGL, WASM y CPU:

Modelos más pequeños

Modelo WebGL ERA M UPC Memoria
BlazeCara 22,5 ms 15,6 ms 315,2 ms .4 MB
Malla facial 19,3 ms 19,2 ms 335ms 2,8 MB

Modelos más grandes

Modelo WebGL ERA M UPC Memoria
PoseNet 42,5 ms 173,9 ms 1514,7ms 4,5 MB
cuerpopix 77 ms 188,4ms 2683ms 4,6 MB
MobileNet v2 37 ms 94 ms 923,6 ms 13 MB

La tabla anterior muestra que WASM es entre 10 y 30 veces más rápido que el backend de CPU JS simple en todos los modelos, y compite con WebGL para modelos más pequeños como BlazeFace , que es liviano (400 KB), pero tiene una cantidad decente de operaciones (~140). Dado que los programas WebGL tienen un costo general fijo por ejecución de operación, esto explica por qué los modelos como BlazeFace son más rápidos en WASM.

Estos resultados variarán dependiendo de su dispositivo. La mejor manera de determinar si WASM es adecuado para su aplicación es probarlo en nuestros diferentes backends.

Inferencia vs Entrenamiento

Para abordar el caso de uso principal para la implementación de modelos preentrenados, el desarrollo de back-end de WASM priorizará la inferencia sobre el soporte de entrenamiento . Consulte una lista actualizada de operaciones admitidas en WASM e infórmenos si su modelo tiene una operación no admitida. Para los modelos de entrenamiento, recomendamos usar el backend Node (TensorFlow C++) o el backend WebGL.

back-end de la CPU

El backend de la CPU, 'cpu', es el backend de menor rendimiento, sin embargo, es el más simple. Todas las operaciones se implementan en JavaScript estándar, lo que las hace menos paralelizables. También bloquean el subproceso de la interfaz de usuario.

Este backend puede ser muy útil para realizar pruebas o en dispositivos donde WebGL no está disponible.

banderas

TensorFlow.js tiene un conjunto de indicadores de entorno que se evalúan automáticamente y determinan la mejor configuración en la plataforma actual. Estas banderas son en su mayoría internas, pero algunas banderas globales se pueden controlar con API pública.

  • tf.enableProdMode(): habilita el modo de producción, que eliminará la validación del modelo, las comprobaciones de NaN y otras comprobaciones de corrección a favor del rendimiento.
  • tf.enableDebugMode() : habilita el modo de depuración, que registrará en la consola cada operación que se ejecute, así como información sobre el rendimiento del tiempo de ejecución, como la huella de memoria y el tiempo total de ejecución del kernel. Tenga en cuenta que esto ralentizará en gran medida su aplicación, no lo use en producción.