Assistez au symposium Women in ML le 7 décembre Inscrivez-vous maintenant

Plateforme et environnement

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

TensorFlow.js fonctionne dans le navigateur et Node.js, et dans les deux plates-formes, il existe de nombreuses configurations différentes disponibles. Chaque plate-forme a un ensemble unique de considérations qui affecteront la façon dont les applications sont développées.

Dans le navigateur, TensorFlow.js prend en charge les appareils mobiles ainsi que les appareils de bureau. Chaque appareil a un ensemble spécifique de contraintes, comme les API WebGL disponibles, qui sont automatiquement déterminées et configurées pour vous.

Dans Node.js, TensorFlow.js prend en charge la liaison directe à l'API TensorFlow ou l'exécution avec les implémentations de CPU vanille plus lentes.

Environnements

Lorsqu'un programme TensorFlow.js est exécuté, la configuration spécifique est appelée l'environnement. L'environnement est composé d'un backend global unique ainsi que d'un ensemble d'indicateurs qui contrôlent les fonctionnalités précises de TensorFlow.js.

Backends

TensorFlow.js prend en charge plusieurs backends différents qui implémentent le stockage de tenseurs et les opérations mathématiques. À tout moment, un seul backend est actif. La plupart du temps, TensorFlow.js choisira automatiquement le meilleur backend pour vous compte tenu de l'environnement actuel. Cependant, il est parfois important de savoir quel backend est utilisé et comment le changer.

Pour trouver quel backend vous utilisez :

console.log(tf.getBackend());

Si vous souhaitez modifier manuellement le backend :

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

Back-end WebGL

Le backend WebGL, 'webgl', est actuellement le backend le plus puissant pour le navigateur. Ce backend est jusqu'à 100 fois plus rapide que le backend CPU vanille. Les tenseurs sont stockés sous forme de textures WebGL et les opérations mathématiques sont implémentées dans les shaders WebGL. Voici quelques éléments utiles à connaître lors de l'utilisation de ce backend : \

Évitez de bloquer le thread de l'interface utilisateur

Lorsqu'une opération est appelée, comme tf.matMul(a, b), le tf.Tensor résultant est renvoyé de manière synchrone, mais le calcul de la multiplication matricielle peut ne pas être encore prêt. Cela signifie que le tf.Tensor renvoyé n'est qu'une poignée pour le calcul. Lorsque vous appelez x.data() ou x.array() , les valeurs seront résolues lorsque le calcul sera réellement terminé. Il est donc important d'utiliser les méthodes asynchrones x.data() et x.array() plutôt que leurs homologues synchrones x.dataSync() et x.arraySync() pour éviter de bloquer le thread d'interface utilisateur pendant la fin du calcul.

Gestion de la mémoire

Une mise en garde lors de l'utilisation du backend WebGL est la nécessité d'une gestion explicite de la mémoire. WebGLTextures, où les données Tensor sont finalement stockées, ne sont pas automatiquement récupérées par le navigateur.

Pour détruire la mémoire d'un tf.Tensor , vous pouvez utiliser la méthode dispose() :

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

Il est très courant d'enchaîner plusieurs opérations dans une application. Conserver une référence à toutes les variables intermédiaires pour les disposer peut réduire la lisibilité du code. Pour résoudre ce problème, TensorFlow.js fournit une méthode tf.tidy() qui nettoie tous les tf.Tensor qui ne sont pas renvoyés par une fonction après son exécution, de la même manière que les variables locales sont nettoyées lorsqu'une fonction est exécutée :

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

Sur les appareils mobiles, WebGL peut ne prendre en charge que les textures à virgule flottante 16 bits. Cependant, la plupart des modèles d'apprentissage automatique sont entraînés avec des pondérations et des activations en virgule flottante de 32 bits. Cela peut entraîner des problèmes de précision lors du portage d'un modèle pour un appareil mobile, car les nombres flottants 16 bits ne peuvent représenter que des nombres dans la plage [0.000000059605, 65504] . Cela signifie que vous devez veiller à ce que les poids et les activations de votre modèle ne dépassent pas cette plage. Pour vérifier si l'appareil prend en charge les textures 32 bits, vérifiez la valeur de tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , si cela est faux, l'appareil ne prend en charge que les textures à virgule flottante 16 bits. Vous pouvez utiliser tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') pour vérifier si TensorFlow.js utilise actuellement des textures 32 bits.

Compilation de shaders et téléchargements de textures

TensorFlow.js exécute des opérations sur le GPU en exécutant des programmes de shader WebGL. Ces shaders sont assemblés et compilés paresseusement lorsque l'utilisateur demande d'exécuter une opération. La compilation d'un shader se produit sur le CPU sur le thread principal et peut être lente. TensorFlow.js mettra automatiquement en cache les shaders compilés, rendant le deuxième appel à la même opération avec des tenseurs d'entrée et de sortie de la même forme beaucoup plus rapidement. En règle générale, les applications TensorFlow.js utilisent les mêmes opérations plusieurs fois au cours de la durée de vie de l'application, de sorte que le deuxième passage dans un modèle d'apprentissage automatique est beaucoup plus rapide.

TensorFlow.js stocke également les données tf.Tensor en tant que WebGLTextures. Lorsqu'un tf.Tensor est créé, nous ne téléchargeons pas immédiatement les données sur le GPU, nous conservons plutôt les données sur le CPU jusqu'à ce que le tf.Tensor soit utilisé dans une opération. Si le tf.Tensor est utilisé une deuxième fois, les données sont déjà sur le GPU, il n'y a donc aucun coût de téléchargement. Dans un modèle d'apprentissage automatique typique, cela signifie que les pondérations sont téléchargées lors de la première prédiction dans le modèle et que le deuxième passage dans le modèle sera beaucoup plus rapide.

Si vous vous souciez des performances de la première prédiction via votre modèle ou le code TensorFlow.js, nous vous recommandons de préparer le modèle en transmettant un tenseur d'entrée de la même forme avant d'utiliser des données réelles.

Par exemple:

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 Node.js TensorFlow

Dans le backend TensorFlow Node.js, "node", l'API TensorFlow C est utilisée pour accélérer les opérations. Cela utilisera l'accélération matérielle disponible de la machine, comme CUDA, si disponible.

Dans ce backend, tout comme le backend WebGL, les opérations renvoient tf.Tensor s de manière synchrone. Cependant, contrairement au backend WebGL, l'opération est terminée avant que vous ne récupériez le tenseur. Cela signifie qu'un appel à tf.matMul(a, b) bloquera le thread d'interface utilisateur.

Pour cette raison, si vous avez l'intention de l'utiliser dans une application de production, vous devez exécuter TensorFlow.js dans les threads de travail pour ne pas bloquer le thread principal.

Pour plus d'informations sur Node.js, consultez ce guide.

Back-end WASM

TensorFlow.js fournit un backend WebAssembly ( wasm ), qui offre une accélération du processeur et peut être utilisé comme alternative aux backends vanilla JavaScript CPU ( cpu ) et WebGL accélérés ( webgl ). Pour l'utiliser:

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

Si votre serveur sert le fichier .wasm sur un autre chemin ou un autre nom, utilisez setWasmPath avant d'initialiser le backend. Voir la section "Using Bundlers" dans le README pour plus d'informations :

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

WASM a été introduit en 2015 en tant que nouveau format binaire basé sur le Web, fournissant aux programmes écrits en JavaScript, C, C++, etc. une cible de compilation pour s'exécuter sur le Web. WASM est pris en charge par Chrome, Safari, Firefox et Edge depuis 2017, et est pris en charge par 90 % des appareils dans le monde.

Performance

Le backend WASM exploite la bibliothèque XNNPACK pour une implémentation optimisée des opérateurs de réseaux de neurones.

Versus JavaScript : Les binaires WASM sont généralement beaucoup plus rapides que les bundles JavaScript pour les navigateurs à charger, analyser et exécuter. JavaScript est typé dynamiquement et récupéré, ce qui peut entraîner des ralentissements lors de l'exécution.

Versus WebGL : WebGL est plus rapide que WASM pour la plupart des modèles, mais pour les petits modèles, WASM peut surpasser WebGL en raison des frais généraux fixes liés à l'exécution des shaders WebGL. La section "Quand dois-je utiliser WASM" ci-dessous traite de l'heuristique pour prendre cette décision.

Portabilité et stabilité

WASM dispose d'une arithmétique flottante 32 bits portable, offrant une parité de précision sur tous les appareils. WebGL, d'autre part, est spécifique au matériel et différents appareils peuvent avoir une précision variable (par exemple, retour aux flottants 16 bits sur les appareils iOS).

Comme WebGL, WASM est officiellement pris en charge par tous les principaux navigateurs. Contrairement à WebGL, WASM peut s'exécuter dans Node.js et être utilisé côté serveur sans qu'il soit nécessaire de compiler des bibliothèques natives.

Quand dois-je utiliser WASM ?

Taille du modèle et demande de calcul

En général, WASM est un bon choix lorsque les modèles sont plus petits ou que vous vous souciez des appareils bas de gamme qui ne prennent pas en charge WebGL (extension OES_texture_float ) ou qui ont des GPU moins puissants. Le tableau ci-dessous montre les temps d'inférence (à partir de TensorFlow.js 1.5.2) dans Chrome sur un MacBook Pro 2018 pour 5 de nos modèles officiellement pris en charge sur les backends WebGL, WASM et CPU :

Modèles plus petits

Modèle WebGL ÉTAIT M CPU Mémoire
BlazeFace 22,5 millisecondes 15,6 millisecondes 315,2 millisecondes .4 Mo
FaceMesh 19,3 millisecondes 19,2 millisecondes 335 millisecondes 2,8 Mo

Modèles plus grands

Modèle WebGL ÉTAIT M CPU Mémoire
PoseNet 42,5 millisecondes 173,9 millisecondes 1514,7 millisecondes 4,5 Mo
BodyPix 77 ms 188,4 millisecondes 2683 ms 4,6 Mo
Mobile Net v2 37 millisecondes 94 millisecondes 923,6 millisecondes 13 Mo

Le tableau ci-dessus montre que WASM est 10 à 30 fois plus rapide que le backend CPU JS standard sur tous les modèles, et compétitif avec WebGL pour les modèles plus petits comme BlazeFace , qui est léger (400 Ko), mais a un nombre décent d'opérations (~ 140). Étant donné que les programmes WebGL ont un coût fixe par opération d'exécution, cela explique pourquoi des modèles comme BlazeFace sont plus rapides sur WASM.

Ces résultats varient en fonction de votre appareil. La meilleure façon de déterminer si WASM convient à votre application est de le tester sur nos différents backends.

Inférence vs Formation

Pour répondre au principal cas d'utilisation du déploiement de modèles pré-formés, le développement du backend WASM donnera la priorité à l' inférence par rapport au support de formation . Consultez une liste à jour des opérations prises en charge dans WASM et faites-nous savoir si votre modèle a une opération non prise en charge. Pour les modèles d'entraînement, nous vous recommandons d'utiliser le backend Node (TensorFlow C++) ou le backend WebGL.

Processeur principal

Le backend CPU, 'cpu', est le backend le moins performant, mais c'est le plus simple. Les opérations sont toutes implémentées en JavaScript vanille, ce qui les rend moins parallélisables. Ils bloquent également le fil d'interface utilisateur.

Ce backend peut être très utile pour les tests ou sur les appareils où WebGL n'est pas disponible.

Drapeaux

TensorFlow.js dispose d'un ensemble d'indicateurs d'environnement qui sont automatiquement évalués et déterminent la meilleure configuration sur la plate-forme actuelle. Ces drapeaux sont pour la plupart internes, mais quelques drapeaux globaux peuvent être contrôlés avec une API publique.

  • tf.enableProdMode(): active le mode de production, qui supprimera la validation du modèle, les vérifications NaN et d'autres vérifications d'exactitude en faveur des performances.
  • tf.enableDebugMode() : active le mode débogage, qui enregistrera dans la console chaque opération exécutée, ainsi que des informations sur les performances d'exécution telles que l'empreinte mémoire et le temps d'exécution total du noyau. Notez que cela ralentira considérablement votre application, ne l'utilisez pas en production.