Si TensorFlow suffit pour entraîner des réseaux neuronaux simples avec des quantités relativement faibles de données de formation, les réseaux neuronaux profonds basés sur de grands ensembles de données de formation ont vraiment besoin de GPU Nvidia compatibles CUDA, de TPU Google, ou de FPGA pour l'accélération. Jusqu'à il y a peu, l’entraînement pendant plusieurs semaines sur des clusters de CPU pouvait faire office d’alternative. Mais, contre toute attente, l’implémentation JavaScript TensorFlow.js introduite avec TensorFlow 2.0 améliore la vitesse d’entraînement ou d'inférence, grâce au support de tous les GPU (et pas seulement des GPU compatibles CUDA) via l'API WebGL.

Qu'est-ce que TensorFlow.js ?

TensorFlow.js est une bibliothèque qui permet de développer et d’entraîner des modèles d'apprentissage machine en JavaScript, et de les déployer dans un navigateur ou sur Node.js. On peut utiliser des modèles existants, convertir des modèles Python TensorFlow, utiliser l'apprentissage par transfert pour recycler des modèles existants avec ses propres données, et développer des modèles à partir de zéro.

Back-ends TensorFlow.js

TensorFlow.js prend en charge plusieurs back-ends pour l'exécution, même si un seul ne peut être actif à la fois. L'environnement TensorFlow.js Node.js permet d'utiliser une build installée de Python/C TensorFlow en tant que back-end, laquelle peut à son tour utiliser l'accélération matérielle disponible de la machine, comme CUDA. Il existe également un back-end basé sur JavaScript pour Node.js, mais ses capacités sont limitées. Dans le navigateur, TensorFlow.js dispose de plusieurs back-ends avec des caractéristiques différentes. Le back-end WebGL fournit un support GPU utilisant des textures WebGL pour le stockage et des shaders WebGL pour l'exécution. Celui-ci permet de rendre le back-end CPU ordinaire 100 fois plus rapide. WebGL n’a pas impérativement besoin de CUDA, si bien qu’il peut tirer parti de n'importe quel GPU disponible. Le back-end du navigateur WebAssembly (WASM) TensorFlow.js utilise la bibliothèque XNNPACK pour optimiser l'implémentation CPU des opérateurs de réseaux neuronaux. Le back-end WASM est généralement beaucoup plus rapide (de 10 à 30 fois) que le back-end du CPU JavaScript, mais il est généralement plus lent que le back-end WebGL, sauf pour les modèles de très petites tailles. Les configurations de chacun étant variables, le mieux est de tester les back-ends WASM et WebGL avec ses propres modèles sur son propre matériel pour évaluer ces performances.

Modèles et layers TensorFlow.js

TensorFlow.js prend en charge deux API pour la construction de modèles de réseaux neuronaux. L'une est l'API Layers. Elle est quasiment identique à l'API Keras de TensorFlow 2. L'autre est l'API Core, qui est essentiellement une manipulation directe des tenseurs. Comme Keras, l'API Layers de TensorFlow.js offre deux solutions pour créer un modèle : séquentielle (API Sequential) et fonctionnelle (API Functional). L'API Sequential est une pile linéaire de couches, implémentée avec une liste de couches (comme indiqué ci-dessous) ou avec la méthode model.add() :

const model = tf.sequential({

 layers : [

   tf.layers.dense({inputShape : [784], units : 32, activation : 'relu'),

   tf.layers.dense({unités : 10, activation : 'softmax'}),

 ]

}) ;

L'API Functional utilise l'API tf.model() et peut créer des réseaux DAG (directed acyclic graph) arbitraires :

// Create an arbitrary graph of layers, by connecting them (Créer un graphe arbitraire de couches, en les reliant)

// via the apply() method.

const input = tf.input({shape: [784]});

const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);

const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);

const model = tf.model({inputs: input, outputs: dense2});

L'API Core permet d’obtenir les mêmes résultats, avec un code différent, et un lien moins intuitif aux layers. Le modèle ci-dessous peut ressembler à des opérations de tenseur de base, mais il crée le même réseau que les deux formulations précédentes. Notez l’usage de relu() et softmax(), qui sont toutes deux des opérations de réseau neuronal, dans la fonction model() ci-dessous.

// The weights and biases for the two dense layers (Poids et biais des deux couches denses)

const w1 = tf.variable(tf.randomNormal([784, 32])) ;

const b1 = tf.variable(tf.randomNormal([32])) ;

const w2 = tf.variable(tf.randomNormal([32, 10])) ;

const b2 = tf.variable(tf.randomNormal([10])) ;

function model(x) {

  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();

}

Modèles TensorFlow.js pré-construits

Il existe plus d'une douzaine de modèles TensorFlow.js pré-construits, documentés, disponibles dans le référentiel et hébergés sur NPM (pour une utilisation dans Node.js) et unpkg (pour utilisation dans un navigateur). On peut utiliser ces modèles tels quels ou pour un apprentissage par transfert. Sans trop d’effort, on peut également les utiliser comme blocs de construction pour d'autres modèles.

Plusieurs de ces modèles utilisent la caméra d'un appareil en temps réel. C’est le cas par exemple de handpose :

Handpose peut détecter la paume de la main et suivre le mouvement des articulations. (Crédit : IDG)

La liste ci-dessous répertorie la plupart des modèles TensorFlow.js pré-construits

-Classification des images

-Détection d'objets

-Segmentation du corps

-Estimation de la position

-Détection de la toxicité des textes

-Encodeur universel de phrases

-Reconnaissance des commandes vocales

-Classificateur KNN

-Détection simple des visages

-Segmentation sémantique

-Détection de points de repère sur le visage

-Détection de la posture de la main

-Réponse aux questions en langage naturel

Qu'est-ce que ml5.js ?

ml5.js est une interface open source, conviviale et de haut niveau pour TensorFlow.js, développée en majeure partie à l'Université de New York. ml5.js fournit un accès immédiat à des modèles pré-entraînés dans le navigateur pour détecter des postures humaines, générer du texte, styliser une image avec une autre, composer de la musique, détecter la hauteur, les relations entre les mots de la langue anglaise courante, et bien plus encore. Contrairement à TensorFlow.js qui s'adresse principalement aux scientifiques et aux développeurs de données, ml5.js cherche à offrir une plus large compréhension de l'apprentissage machine au grand public et à favoriser un engagement plus affirmé en faveur de l'informatique éthique, de la collecte responsable de données, et de l'accessibilité et de la diversité des personnes et des perspectives dans le domaine de la technologie et des arts. La plupart des exemples présentés dans ml5.js sont basés sur des modèles TensorFlow.js. Ils ont été regroupés sous forme de pages web que l’on peut exécuter telles quelles ou modifier, pour utiliser différentes images par exemple.

PoseNet peut effectuer une estimation de la pose en temps réel dans le navigateur, à partir d'images ou d'un flux vidéo. (Crédit : IDG)

Démonstration : Classification des Iris avec TensorFlow.js

Le célèbre ensemble de données de discrimination de l‘Iris, créé par R.A. Fisher en 1936 pour illustrer l'analyse discriminante linéaire, est toujours utilisé comme cas test pour les méthodes de classification statistique et d'apprentissage machine. Il s’appuie sur quatre caractéristiques - la longueur et la largeur des sépales et des pétales de la fleur - pour classer trois espèces d'Iris, sue la base de 50 échantillons de chaque espèce. (L'article original de Fisher a été publié dans les Annals of Eugenics, qui en dit plus sur l’état de la science en 1936 que sur les données ou les statistiques). Si l’on effectue une analyse par cluster sur ces données, deux des espèces se partageront un cluster, et la troisième (I. Setosa) sera classée dans un cluster séparé. D'autre part, l'analyse en composantes principales permet de séparer assez bien les trois espèces. L'échantillon TensorFlow.js fait correspondre les données relatives aux Iris avec deux couches de réseau neuronal (dense) entièrement connectées, comme le montre l'extrait de code ci-dessous.

// Define the topology of the model: two dense layers (Définir la topologie du modèle : deux couches denses).

const model = tf.sequential();

model.add(tf.layers.dense(

     {units: 10, activation: 'sigmoid', inputShape: [xTrain.shape[1]]}

     ));

model.add(tf.layers.dense({units: 3, activation: 'softmax'}));

model.summary();

const optimizer = tf.train.adam(params.learningRate);

model.compile({

     optimizer: optimizer,

     loss: 'categoricalCrossentropy',

     metrics: ['accuracy'],

});

Comme on peut le voir dans la capture d'écran ci-dessous, ce modèle permet de classer les trois espèces de manière satisfaisante. Cependant, si l’on modifie les paramètres, on peut voir apparaître une certaine confusion entre deux des espèces (celles du même groupe) si l’on effectue l’itération sur plus de 40 époques.

Entraînement du modèle pour l'ensemble de données Iris en utilisant un modèle de réseau neuronal à deux couches denses. (Crédit : IDG)

Conversion des modèles Python TensorFlow en JavaScript

Une partie du référentiel TensorFlow.js contient un convertisseur pour les modèles TensorFlow et Keras sauvegardés. Il prend en charge trois formats : SavedModel (par défaut pour TensorFlow), HDF5 (par défaut pour Keras), et TensorFlow Hub. On peut utiliser le convertisseur pour les modèles sauvegardés dans les référentiels standards, les modèles que l’on a soi-même entraîné et les modèles que l’on a trouvés ailleurs. La conversion se fait en deux étapes : la première étape consiste à convertir le modèle existant en fichiers model.json et en fichiers de charges binaires ; la seconde étape consiste à utiliser une API pour charger le modèle dans TensorFlow.js, soit tf.loadGraphModel pour les modèles TensorFlow et TensorFlow Hub convertis, soit tf.loadLayersModel pour les modèles Keras convertis.

Utilisation de l'apprentissage par transfert

TensorFlow.js supporte l'apprentissage par transfert à la manière de TensorFlow. La documentation fournit des exemples pour personnaliser MobileNet pour ses propres images et personnaliser un modèle de reconnaissance de commandes vocales pour ses propres catégories de son. Globalement, il s’agit simplement d’ajouter un petit classificateur personnalisé dans chacun de ces codelabs, en plus du modèle entraîné, et de réentraîner le nouveau modèle. Dans l'ensemble, TensorFlow.js est capable de faire à peu près tout ce que fait TensorFlow. Cependant, étant donné que les environnements cibles de TensorFlow.js (GPU courantes pour les jeux) disposent de moins de mémoire GPU que les gros GPU de serveur Nvidia généralement utilisés pour l’entraînement deap learning de TensorFlow, il faudra peut-être réduire la taille de son modèle pour le faire fonctionner dans un navigateur. L'utilitaire de conversion effectue une partie de cette opération pour l’utilisateur, mais ce dernier devra peut-être enlever des couches manuellement et réduire la taille des lots pour mener à bien l’entraînement de son modèle.