Retour au blog

JavaScript et Machine Learning : Comment TensorFlow.js Democratise l'IA

Salut HaWkers, imaginez entrainer et executer des modeles de Machine Learning directement dans le navigateur, sans backend, sans Python, uniquement JavaScript. En 2025, ce n'est plus de la science-fiction — c'est la realite avec TensorFlow.js.

Avez-vous deja pense a ajouter la reconnaissance faciale a votre application web ? Ou creer un systeme de recommandation qui tourne a 100% sur le client ? TensorFlow.js rend l'IA accessible a des millions de developpeurs JavaScript.

Qu'est-ce que TensorFlow.js ?

TensorFlow.js est une bibliotheque JavaScript pour entrainer et executer des modeles de Machine Learning dans le navigateur et Node.js. Creee par Google, c'est la version JavaScript du celebre TensorFlow (Python).

Pourquoi TensorFlow.js est Revolutionnaire ?

Execution dans le Navigateur :

  • Zero latence serveur
  • Confidentialite totale (les donnees ne quittent pas l'appareil)
  • Fonctionne hors ligne
  • Acces au GPU via WebGL

Democratisation de l'IA :

  • JavaScript est le langage le plus populaire (utilise par 67% des devs)
  • Pas besoin d'apprendre Python
  • Integration facile avec les apps web existantes
  • Deploiement simple (juste du JavaScript)

Demarrer avec TensorFlow.js

Installation et Configuration

# Via npm
npm install @tensorflow/tfjs

# Via CDN (pour des prototypes rapides)
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>

Votre Premier Modele : Regression Lineaire

import * as tf from '@tensorflow/tfjs';

// Donnees d'entrainement : relation entre heures etudiees et note
const heuresEtudiees = [1, 2, 3, 4, 5, 6, 7, 8];
const notes = [2, 4, 6, 8, 10, 12, 14, 16];

// Convertit en tenseurs (structures de donnees TensorFlow)
const inputs = tf.tensor2d(heuresEtudiees, [8, 1]);
const outputs = tf.tensor2d(notes, [8, 1]);

// Cree un modele sequentiel (couche par couche)
const model = tf.sequential({
  layers: [
    tf.layers.dense({
      units: 1,        // 1 neurone de sortie
      inputShape: [1]  // 1 entree (heures)
    })
  ]
});

// Compile le modele
model.compile({
  optimizer: 'sgd',         // Stochastic Gradient Descent
  loss: 'meanSquaredError'  // Fonction de perte
});

// Entraine le modele
async function entrainerModele() {
  console.log('Demarrage de l\'entrainement...');

  await model.fit(inputs, outputs, {
    epochs: 100,  // 100 iterations
    callbacks: {
      onEpochEnd: (epoch, logs) => {
        console.log(`Epoque ${epoch}: loss = ${logs.loss.toFixed(4)}`);
      }
    }
  });

  console.log('Entrainement termine !');

  // Fait une prediction : combien d'heures pour une note de 18 ?
  const resultat = model.predict(tf.tensor2d([9], [1, 1]));
  resultat.print(); // ~18

  // Libere la memoire (important !)
  inputs.dispose();
  outputs.dispose();
  resultat.dispose();
}

entrainerModele();

machine learning training

Reconnaissance d'Image avec des Modeles Pre-Entraines

Un des cas d'usage les plus puissants : utiliser des modeles deja entraines par Google.

Classification d'Images avec MobileNet

import * as tf from '@tensorflow/tfjs';
import * as mobilenet from '@tensorflow-models/mobilenet';

// Charge le modele MobileNet (entraine sur ImageNet)
let model;

async function chargerModele() {
  console.log('Chargement de MobileNet...');
  model = await mobilenet.load({
    version: 2,
    alpha: 1.0  // Precision (0.25, 0.5, 0.75, 1.0)
  });
  console.log('Modele charge !');
}

// Classifie une image
async function classifierImage(elementImage) {
  if (!model) {
    await chargerModele();
  }

  // Prediction (retourne les 3 classes les plus probables)
  const predictions = await model.classify(elementImage, 3);

  console.log('Predictions:', predictions);

  // Format du resultat:
  // [
  //   { className: 'golden retriever', probability: 0.89 },
  //   { className: 'Labrador retriever', probability: 0.07 },
  //   { className: 'cocker spaniel', probability: 0.02 }
  // ]

  return predictions;
}

// Utilisation dans une application React
function ImageClassifier() {
  const [predictions, setPredictions] = useState([]);
  const [loading, setLoading] = useState(false);
  const imageRef = useRef(null);

  const handleImageUpload = async (event) => {
    const file = event.target.files[0];
    const imageUrl = URL.createObjectURL(file);

    // Affiche l'apercu
    imageRef.current.src = imageUrl;

    setLoading(true);

    // Attend le chargement de l'image
    imageRef.current.onload = async () => {
      const results = await classifierImage(imageRef.current);
      setPredictions(results);
      setLoading(false);
    };
  };

  return (
    <div className="classifier">
      <input
        type="file"
        accept="image/*"
        onChange={handleImageUpload}
      />

      <img ref={imageRef} alt="Apercu" />

      {loading && <p>Analyse de l'image...</p>}

      {predictions.length > 0 && (
        <div className="results">
          <h3>Resultats :</h3>
          {predictions.map((pred, idx) => (
            <div key={idx} className="prediction">
              <span>{pred.className}</span>
              <span>{(pred.probability * 100).toFixed(1)}%</span>
              <div
                className="confidence-bar"
                style={{ width: `${pred.probability * 100}%` }}
              />
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

Detection d'Objets en Temps Reel

Creons un detecteur d'objets utilisant la webcam :

import * as cocoSsd from '@tensorflow-models/coco-ssd';

// Modele COCO-SSD detecte 80 classes d'objets
let detectorModel;

async function initialiserDetecteur() {
  console.log('Chargement de COCO-SSD...');
  detectorModel = await cocoSsd.load({
    base: 'mobilenet_v2'  // ou 'lite_mobilenet_v2' pour plus de vitesse
  });
  console.log('Detecteur pret !');
}

// Detecte les objets dans une video
async function detecterObjets(videoElement, canvasElement) {
  if (!detectorModel) {
    await initialiserDetecteur();
  }

  const ctx = canvasElement.getContext('2d');

  // Boucle de detection
  async function detectFrame() {
    // Detecte les objets dans le frame actuel
    const predictions = await detectorModel.detect(videoElement);

    // Efface le canvas
    ctx.clearRect(0, 0, canvasElement.width, canvasElement.height);

    // Dessine les detections
    predictions.forEach(prediction => {
      const [x, y, width, height] = prediction.bbox;

      // Dessine la boite
      ctx.strokeStyle = '#00ff00';
      ctx.lineWidth = 2;
      ctx.strokeRect(x, y, width, height);

      // Dessine le label
      ctx.fillStyle = '#00ff00';
      ctx.font = '16px Arial';
      const label = `${prediction.class} (${(prediction.score * 100).toFixed(0)}%)`;
      ctx.fillText(label, x, y > 20 ? y - 5 : y + 15);
    });

    // Frame suivant
    requestAnimationFrame(detectFrame);
  }

  detectFrame();
}

// Composant React pour detection via webcam
function ObjectDetector() {
  const videoRef = useRef(null);
  const canvasRef = useRef(null);
  const [isDetecting, setIsDetecting] = useState(false);

  const startDetection = async () => {
    // Acces a la webcam
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { width: 640, height: 480 }
    });

    videoRef.current.srcObject = stream;
    await videoRef.current.play();

    // Ajuste le canvas a la taille de la video
    canvasRef.current.width = videoRef.current.videoWidth;
    canvasRef.current.height = videoRef.current.videoHeight;

    // Demarre la detection
    setIsDetecting(true);
    detecterObjets(videoRef.current, canvasRef.current);
  };

  const stopDetection = () => {
    const stream = videoRef.current.srcObject;
    stream.getTracks().forEach(track => track.stop());
    setIsDetecting(false);
  };

  return (
    <div className="detector">
      <div className="video-container">
        <video ref={videoRef} />
        <canvas ref={canvasRef} />
      </div>

      <button onClick={isDetecting ? stopDetection : startDetection}>
        {isDetecting ? 'Arreter' : 'Demarrer'} la Detection
      </button>
    </div>
  );
}

object detection

Classification de Texte et Analyse de Sentiment

TensorFlow.js ne se limite pas aux images. Creons un analyseur de sentiments :

import * as tf from '@tensorflow/tfjs';
import * as use from '@tensorflow-models/universal-sentence-encoder';

// Charge Universal Sentence Encoder
let encoder;

async function chargerEncoder() {
  encoder = await use.load();
  console.log('Encoder charge !');
}

// Cree et entraine un modele de sentiment
async function creerModeleSentiment() {
  // Dataset d'exemple (en production, utilisez un dataset plus grand)
  const textesEntrainement = [
    'Ce produit est incroyable ! J\'adore !',
    'Excellente qualite, je recommande',
    'Horrible, ne fonctionne pas',
    'Tres mauvais, n\'achetez pas',
    'Tres bien, je suis satisfait',
    'Decevant, j\'attendais mieux'
  ];

  const labels = [1, 1, 0, 0, 1, 0]; // 1 = positif, 0 = negatif

  // Convertit les textes en embeddings
  if (!encoder) await chargerEncoder();
  const embeddings = await encoder.embed(textesEntrainement);

  // Cree le modele de classification
  const model = tf.sequential({
    layers: [
      tf.layers.dense({
        inputShape: [512], // USE genere des vecteurs de 512 dimensions
        units: 128,
        activation: 'relu'
      }),
      tf.layers.dropout({ rate: 0.5 }), // Previent l'overfitting
      tf.layers.dense({
        units: 64,
        activation: 'relu'
      }),
      tf.layers.dense({
        units: 1,
        activation: 'sigmoid' // Output entre 0 et 1
      })
    ]
  });

  model.compile({
    optimizer: tf.train.adam(0.001),
    loss: 'binaryCrossentropy',
    metrics: ['accuracy']
  });

  // Entraine le modele
  const labelsTensor = tf.tensor2d(labels, [labels.length, 1]);

  await model.fit(embeddings, labelsTensor, {
    epochs: 50,
    batchSize: 2,
    validationSplit: 0.2,
    callbacks: {
      onEpochEnd: (epoch, logs) => {
        console.log(`Epoque ${epoch}: accuracy = ${(logs.acc * 100).toFixed(2)}%`);
      }
    }
  });

  return model;
}

// Analyse le sentiment d'un nouveau texte
async function analyserSentiment(texte, model) {
  if (!encoder) await chargerEncoder();

  // Convertit le texte en embedding
  const embedding = await encoder.embed([texte]);

  // Prediction
  const prediction = model.predict(embedding);
  const score = (await prediction.data())[0];

  // Libere la memoire
  embedding.dispose();
  prediction.dispose();

  return {
    sentiment: score > 0.5 ? 'Positif' : 'Negatif',
    confiance: score > 0.5 ? score : 1 - score,
    score: score
  };
}

Pose Detection : Detection du Corps Humain

Un des modeles les plus impressionnants — detecte 17 points du corps humain :

import * as poseDetection from '@tensorflow-models/pose-detection';

let detector;

async function creerDetecteurPose() {
  const model = poseDetection.SupportedModels.MoveNet;

  detector = await poseDetection.createDetector(model, {
    modelType: poseDetection.movenet.modelType.SINGLEPOSE_THUNDER
  });

  console.log('Detecteur de pose pret !');
}

// Detecte la pose dans une video
async function detecterPose(videoElement, canvasElement) {
  if (!detector) {
    await creerDetecteurPose();
  }

  const ctx = canvasElement.getContext('2d');

  async function detectFrame() {
    // Detecte la pose
    const poses = await detector.estimatePoses(videoElement);

    // Efface le canvas
    ctx.clearRect(0, 0, canvasElement.width, canvasElement.height);

    if (poses.length > 0) {
      const pose = poses[0];

      // Dessine les keypoints (points du corps)
      pose.keypoints.forEach(keypoint => {
        if (keypoint.score > 0.3) { // Confiance minimale
          ctx.beginPath();
          ctx.arc(keypoint.x, keypoint.y, 5, 0, 2 * Math.PI);
          ctx.fillStyle = '#00ff00';
          ctx.fill();

          // Affiche le nom du point
          ctx.fillStyle = '#ffffff';
          ctx.font = '12px Arial';
          ctx.fillText(keypoint.name, keypoint.x + 8, keypoint.y);
        }
      });

      // Connecte les points (squelette)
      dessinerSquelette(ctx, pose.keypoints);

      // Calcule les angles (utile pour les apps fitness)
      const angleGenou = calculerAngle(
        pose.keypoints[11], // hanche
        pose.keypoints[13], // genou
        pose.keypoints[15]  // cheville
      );

      ctx.fillStyle = '#ffffff';
      ctx.font = '16px Arial';
      ctx.fillText(`Angle genou: ${angleGenou.toFixed(0)}°`, 10, 30);
    }

    requestAnimationFrame(detectFrame);
  }

  detectFrame();
}

// Dessine les connexions entre keypoints
function dessinerSquelette(ctx, keypoints) {
  // Definition des connexions (os)
  const connections = [
    ['left_shoulder', 'right_shoulder'],
    ['left_shoulder', 'left_elbow'],
    ['left_elbow', 'left_wrist'],
    ['right_shoulder', 'right_elbow'],
    ['right_elbow', 'right_wrist'],
    ['left_shoulder', 'left_hip'],
    ['right_shoulder', 'right_hip'],
    ['left_hip', 'right_hip'],
    ['left_hip', 'left_knee'],
    ['left_knee', 'left_ankle'],
    ['right_hip', 'right_knee'],
    ['right_knee', 'right_ankle']
  ];

  connections.forEach(([start, end]) => {
    const startPoint = keypoints.find(kp => kp.name === start);
    const endPoint = keypoints.find(kp => kp.name === end);

    if (startPoint?.score > 0.3 && endPoint?.score > 0.3) {
      ctx.beginPath();
      ctx.moveTo(startPoint.x, startPoint.y);
      ctx.lineTo(endPoint.x, endPoint.y);
      ctx.strokeStyle = '#00ff00';
      ctx.lineWidth = 2;
      ctx.stroke();
    }
  });
}

// Calcule l'angle entre 3 points
function calculerAngle(p1, p2, p3) {
  const rad = Math.atan2(p3.y - p2.y, p3.x - p2.x) -
              Math.atan2(p1.y - p2.y, p1.x - p2.x);
  let angle = Math.abs(rad * 180 / Math.PI);

  if (angle > 180) {
    angle = 360 - angle;
  }

  return angle;
}

pose detection

TensorFlow.js vs Python : Quand Utiliser Chacun ?

Utilisez TensorFlow.js quand :

La confidentialite est critique - Les donnees ne quittent pas l'appareil
La latence compte - Zero aller-retour serveur
Deploiement simple - Juste des fichiers statiques
Fonctionnement offline - L'app fonctionne sans internet
Integration web - Vous avez deja un frontend JavaScript

Utilisez Python quand :

Entrainement intensif - Datasets gigantesques (GB/TB)
GPU dedie - Entrainement sur clusters
Recherche/experimentation - Jupyter notebooks
Modeles complexes - Architectures personnalisees
Ecosysteme riche - scikit-learn, pandas, etc

Hybride (Le Meilleur des Deux Mondes) :

  1. Entrainez en Python (puissance de calcul)
  2. Convertissez pour TensorFlow.js (deploiement web)
  3. Executez dans le navigateur (confidentialite + vitesse)
# Convertit le modele Python en JavaScript
pip install tensorflowjs

tensorflowjs_converter \
  --input_format=keras \
  ./model.h5 \
  ./tfjs_model/

Performance et Optimisation

1. Utilisez WebGL pour l'Acceleration GPU

import * as tf from '@tensorflow/tfjs';

// Force l'utilisation de WebGL (GPU)
await tf.setBackend('webgl');

// Verifie le backend actif
console.log('Backend:', tf.getBackend()); // 'webgl'

// WebGL vs CPU peut etre 10-100x plus rapide !

2. Quantification pour Reduire la Taille

// Lors de la conversion du modele Python, utilisez la quantification
// Reduit la taille de 4x avec une perte minimale de precision

tensorflowjs_converter \
  --input_format=keras \
  --quantize_uint8 \
  ./model.h5 \
  ./tfjs_model/

3. Gestion de la Memoire

// ❌ Fuite de memoire
async function mauvais() {
  for (let i = 0; i < 1000; i++) {
    const tensor = tf.tensor([1, 2, 3]);
    // Le tensor n'est pas libere - la memoire augmente !
  }
}

// ✅ Gestion correcte
async function bon() {
  for (let i = 0; i < 1000; i++) {
    const tensor = tf.tensor([1, 2, 3]);
    // ... utilise le tensor ...
    tensor.dispose(); // Libere la memoire
  }
}

// ✅ Encore mieux : tidy() libere automatiquement
async function meilleur() {
  for (let i = 0; i < 1000; i++) {
    tf.tidy(() => {
      const tensor = tf.tensor([1, 2, 3]);
      // Tout dans tidy() est libere automatiquement
      return tensor.sum();
    });
  }
}

// Surveille la memoire
console.log('Tensors en memoire:', tf.memory().numTensors);

Cas d'Usage Reels en Production

1. Google Photos - Recherche par Similarite

  • Utilise TensorFlow.js pour comparer les photos sur le client
  • Zero upload - confidentialite totale

2. Airbnb - Moderation de Contenu

  • Detecte les images inappropriees avant l'upload
  • Reduit la charge serveur de 80%

3. Uber - Detection de Fraude

  • Analyse les patterns de comportement dans l'app
  • Detection en temps reel sans latence

4. Duolingo - Reconnaissance Vocale

  • Evalue la prononciation avec TensorFlow.js
  • Fonctionne offline sur mobile

L'Avenir du ML dans le Navigateur

En 2025, la tendance est claire : le ML devient un outil essentiel pour les developpeurs web. Avec TensorFlow.js, vous n'avez pas besoin d'etre data scientist pour ajouter l'IA a vos applications.

La barriere entre frontend et IA disparait, et les developpeurs JavaScript ont maintenant le pouvoir de creer des experiences intelligentes, privees et instantanees.

Si vous voulez explorer plus sur le JavaScript moderne et ses capacites, je recommande de consulter un autre article : JavaScript Moderne : Features Essentielles ES2024 que Vous Devez Maitriser ou vous decouvrirez les dernieres nouveautes du langage.

C'est parti !

Commentaires (0)

Cet article n'a pas encore de commentaires. Soyez le premier!

Ajouter des commentaires