Plataforma y medio ambiente

TensorFlow.js funciona en el navegador y 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 es compatible con dispositivos móviles y con dispositivos 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 la vinculación directa a la API de TensorFlow o la ejecución con implementaciones de CPU vanilla más lentas.

Ambientes

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

Backends

TensorFlow.js admite varios backends diferentes que implementan el almacenamiento de tensores y las 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á utilizando:

console.log(tf.getBackend());

Si desea cambiar manualmente el backend:

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

Backend de WebGL

El backend de 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 la 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 hilo 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 para el cálculo. Cuando se llama a x.data() o x.array() , los valores se resolverán cuando el cómputo de hecho ha completado. Esto hace que sea importante utilizar el asíncrona x.data() y x.array() métodos sobre sus contrapartes síncronas x.dataSync() y x.arraySync() para evitar el bloqueo el hilo de interfaz de usuario mientras se completa el cálculo.

Gestión de la memoria

Una advertencia al utilizar el backend de WebGL es la necesidad de una gestión de memoria explícita. WebGLTextures, que es donde los datos de Tensor finalmente se almacenan, no son basura recolectada automáticamente por el navegador.

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

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 una tf.tidy() Método que limpia toda tf.Tensor s que no están devuelto por una función después de ejecutar que, de forma similar a las variables locales se limpian 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 punto flotante de 16 bits. Sin embargo, la mayoría de los modelos de aprendizaje automático se entrenan con activaciones y ponderaciones de punto flotante de 32 bits. Esto puede causar problemas de precisión cuando al portar un modelo para un dispositivo móvil como números de coma flotante de 16 bits sólo puede representar números en el rango [0.000000059605, 65504] . Esto significa que debe tener cuidado de que los pesos y las activaciones en su modelo no excedan este rango. Para comprobar si las texturas bits soportes dispositivo 32, compruebe el valor de tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , si esto es falso, entonces el dispositivo sólo soporta 16 texturas de punto flotante bits. Puede utilizar tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') para comprobar si está utilizando actualmente TensorFlow.js 32 bits texturas.

Compilación de sombreadores y cargas 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 en el hilo 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 TensorFlow.js usarán las mismas operaciones varias veces durante la vida útil de la aplicación, por lo que la segunda pasada a través de un modelo de aprendizaje automático es mucho más rápida.

TensorFlow.js también almacena datos de tf.Tensor como WebGLTextures. Cuando un tf.Tensor se crea, no pongamos inmediatamente los datos a la GPU, en lugar guardamos los datos de la CPU hasta que el tf.Tensor se utiliza en una operación. Si el tf.Tensor se utiliza un segundo tiempo, los datos ya están en la GPU lo que no hay costos 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 a través del modelo será mucho más rápida.

Si le importa el rendimiento de la primera predicción a través de su modelo o código TensorFlow.js, recomendamos calentar el modelo pasando un tensor de entrada de la misma forma antes de que se usen 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);

Backend de Node.js TensorFlow

En el backend de TensorFlow Node.js, 'nodo', la API de TensorFlow C 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 componente de fondo, al igual que el backend WebGL, las operaciones regresen tf.Tensor es sincrónica. Sin embargo, a diferencia del backend de WebGL, la operación se completa antes de recuperar el tensor. Esto significa que una llamada a tf.matMul(a, b) bloqueará el hilo de 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.

Backend de WASM

TensorFlow.js proporciona un backend WebAssembly ( wasm ), que la aceleración ofertas CPU y se puede utilizar como una alternativa a la vainilla JavaScript CPU ( cpu ) y WebGL acelerado ( webgl ) backends. Para usarlo:

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

Si el servidor está sirviendo al .wasm archivo en un camino diferente o un nombre diferente, el uso setWasmPath antes de inicializar el backend. Consulte la "Uso Bundlers" sección en el archivo README 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. una compilación de destino para el funcionamiento de la web. WASM ha sido apoyado por Chrome, Safari, Firefox, y Edge desde 2017, y es apoyado por el 90% de los dispositivos en todo el mundo.

Rendimiento

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

Versus JavaScript: WASM binarios son generalmente mucho más rápido que agrupa JavaScript para navegadores para cargar, análisis sintáctico, y ejecutan. JavaScript se escribe dinámicamente y se recolecta basura, lo que puede causar ralentizaciones en tiempo de ejecución.

Versus WebGL: WebGL es más rápido que WASM para la mayoría de los modelos, pero para pequeños modelos WASM puede superar a WebGL debido a los gastos generales fijos de la ejecución de los sombreadores de WebGL. La sección "Cuándo debo usar WASM" a continuación trata sobre 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 diferentes dispositivos pueden tener una precisión variable (por ejemplo, retroceso a flotantes de 16 bits en dispositivos iOS).

Al igual que WebGL, WASM es compatible oficialmente con todos los navegadores principales. 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 debería usar WASM?

Tamaño del modelo y demanda computacional

En general, WASM es una opción buena cuando los modelos son más pequeños o que se preocupan por los dispositivos de gama baja que carecen de soporte WebGL ( OES_texture_float extensión) o que tienen las GPU menos potentes. El gráfico siguiente muestra la inferencia veces (a partir de TensorFlow.js 1.5.2) en Chrome en un MacBook Pro 2018 en 5 de nuestros apoyo oficial modelos en todo el WebGL, WASM, y backends CPU:

Modelos más pequeños

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

Modelos más grandes

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

La tabla anterior muestra que WASM es 10-30x más rápido que la llanura backend JS CPU a través de modelos y competitivo con WebGL para los modelos más pequeños como BlazeFace , que es ligero (400 KB), sin embargo, tiene un buen número de operaciones (~ 140). Dado que los programas WebGL tienen un costo general fijo por ejecución de operación, esto explica por qué modelos como BlazeFace son más rápidos en WASM.

Estos resultados variarán según 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 hacer frente al caso de uso principal para el despliegue de modelos pre-formados, el desarrollo backend WASM dará prioridad a la inferencia sobre la formación de apoyo. Ver una lista actualizada de las operaciones apoyadas en WASM y háganos saber si su modelo tiene un artículo sin apoyo. Para entrenar modelos, recomendamos usar el backend de Node (TensorFlow C ++) o el backend de WebGL.

Backend 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 vanilla, lo que las hace menos paralelizables. También bloquean el hilo 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. Estos indicadores son en su mayoría internos, pero algunos indicadores globales se pueden controlar con una API pública.

  • tf.enableProdMode(): habilita el modo de producción, lo que eliminará la validación del modelo, cheques Nan, y otras comprobaciones de exactitud en favor del rendimiento.
  • tf.enableDebugMode() : activa el modo de depuración, que se pueden registrar en la consola de cada operación que se ejecuta, así como información sobre el rendimiento en tiempo de ejecución como el consumo de memoria y tiempo de ejecución total del núcleo. Tenga en cuenta que esto ralentizará enormemente su aplicación, no lo utilice en producción.