Prélecture prédictive avec TensorFlow.js

Dans ce didacticiel, vous exécuterez un exemple d'application Web qui utilise TensorFlow.js pour effectuer une prélecture prédictive des ressources. Construit avec Angular , l'exemple s'inspire du Google Merchandise Store mais ne partage aucune donnée ni aucun détail d'implémentation avec lui.

L'exemple utilise un modèle pré-entraîné pour effectuer des prédictions. Dans un scénario réel, vous devrez former un modèle à l'aide des analyses de votre site Web. Vous pouvez utiliser TFX pour effectuer une telle formation. Pour en savoir plus sur la formation d'un modèle personnalisé pour la prélecture prédictive, consultez cet article de blog .

L'exemple de code est disponible sur GitHub .

Conditions préalables

Pour terminer ce didacticiel, vous devez installer les éléments suivants dans votre environnement de développement :

Installer l'exemple

Récupérez le code source et installez les dépendances :

  1. Clonez ou téléchargez le référentiel tfjs-examples .
  2. Accédez au répertoire angular-predictive-prefetching/client et installez les dépendances :

    cd tfjs-examples/angular-predictive-prefetching/client && yarn
    
  3. Accédez au répertoire angular-predictive-prefetching/server et installez les dépendances :

    cd ../server && yarn
    

Exécutez l'exemple

Démarrez le serveur et le client :

  1. Démarrez le serveur : dans le répertoire server , exécutez yarn start .

  2. Démarrez le client :

    1. Ouvrez une autre fenêtre de terminal.
    2. Changez en tfjs-examples/angular-predictive-prefetching/client .
    3. Exécutez les commandes suivantes :

      yarn build
      cd dist/merch-store
      npx serve -s .
      

      Vous serez peut-être invité à installer le package de service . Si tel est le cas, entrez y pour installer le package.

  3. Accédez à http://localhost:3000 dans votre navigateur. Vous devriez voir une fausse boutique de produits Google.

Explorez avec DevTools

Utilisez Chrome DevTools pour voir la prélecture en action :

  1. Ouvrez DevTools et sélectionnez Console .
  2. Accédez à quelques pages différentes de l’application pour amorcer l’application. Sélectionnez ensuite Vente dans la navigation de gauche. Vous devriez voir une sortie de journal comme celle-ci :

    Navigating from: 'sale'
    'quickview' -> 0.381757915019989
    'apparel-unisex' -> 0.3150934875011444
    'store.html' -> 0.1957530975341797
    '' -> 0.052346792072057724
    'signin.html' -> 0.0007763378671370447
    

    Cette sortie affiche les prédictions pour la page que vous (l’utilisateur) visiterez ensuite. L'application récupère les ressources en fonction de ces prédictions.

  3. Pour voir les demandes de récupération, sélectionnez Réseau . La sortie est un peu bruyante, mais vous devriez pouvoir trouver des demandes de ressources pour les pages prédites. Par exemple, après avoir prédit quickview , l'application envoie une requête à http://localhost:8000/api/merch/quickview .

Comment fonctionne la prélecture prédictive

L'exemple d'application utilise un modèle pré-entraîné pour prédire la page qu'un utilisateur visitera ensuite. Lorsque l'utilisateur accède à une nouvelle page, l'application interroge le modèle, puis pré-extrait les images associées aux pages prédites.

L'application effectue la prélecture prédictive sur un service worker , afin qu'elle puisse interroger le modèle sans bloquer le thread principal. Sur la base de l'historique de navigation de l'utilisateur, le technicien de service fait des prédictions pour la navigation future et pré-extrait les images de produits pertinentes.

Le service worker est chargé dans le fichier principal de l'application Angular, main.ts :

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/prefetch.service-worker.js', { scope: '/' });
}

L'extrait ci-dessus télécharge le script prefetch.service-worker.js et l'exécute en arrière-plan.

Dans merch-display.component.ts , l'application transmet les événements de navigation au service worker :

this.route.params.subscribe((routeParams) => {
  this.getMerch(routeParams.category);
  if (this._serviceWorker) {
    this._serviceWorker.postMessage({ page: routeParams.category });
  }
});

Dans l'extrait ci-dessus, l'application surveille les modifications apportées aux paramètres de l'URL. En cas de changement, le script transmet la catégorie de la page au service worker.

Le script de service worker, prefetch.service-worker.js , gère les messages du thread principal, effectue des prédictions basées sur ceux-ci et pré-extrait les ressources pertinentes.

Le service worker utilise loadGraphModel pour charger le modèle pré-entraîné :

const MODEL_URL = "/assets/model.json";

let model = null;
tf.loadGraphModel(MODEL_URL).then((m) => (model = m));

La prédiction se produit dans l' expression de fonction suivante :

const predict = async (path, userId) => {
  if (!model) {
    return;
  }
  const page = pages.indexOf(path);
  const pageId = tf.tensor1d([parseInt(page)], "int32");

  const sessionIndex = tf.tensor1d([parseInt(userId)], "int32");

  const result = model.predict({
    cur_page: pageId,
    session_index: sessionIndex,
  });
  const values = result.dataSync();
  const orders = sortWithIndices(values).slice(0, 5);
  return orders;
};

La fonction predict est ensuite invoquée par la fonction prefetch :

const prefetch = async (path, sessionId) => {
  const predictions = await predict(path, sessionId);
  const formattedPredictions = predictions
    .map(([a, b]) => `'${b}' -> ${a}`)
    .join("\n");
  console.log(`Navigating from: '${path}'`);
  console.log(formattedPredictions);
  const connectionSpeed = navigator.connection.effectiveType;
  const threshold = connectionSpeeds[connectionSpeed];
  const cache = await caches.open(ImageCache);
  predictions.forEach(async ([probability, category]) => {
    if (probability >= threshold) {
      const merchs = (await getMerchList(category)).map(getUrl);
      [...new Set(merchs)].forEach((url) => {
        const request = new Request(url, {
          mode: "no-cors",
        });
        fetch(request).then((response) => cache.put(request, response));
      });
    }
  });
};

Tout d’abord, prefetch prédit les pages que l’utilisateur pourrait visiter ensuite. Ensuite, il parcourt les prédictions. Pour chaque prédiction, si la probabilité dépasse un certain seuil basé sur la vitesse de connexion, la fonction récupère les ressources pour la page prédite. En récupérant ces ressources avant la demande de page suivante, l'application peut potentiellement diffuser le contenu plus rapidement et offrir une meilleure expérience utilisateur.

Quelle est la prochaine étape

Dans ce didacticiel, l'exemple d'application utilise un modèle pré-entraîné pour effectuer des prédictions. Vous pouvez utiliser TFX pour entraîner un modèle à la prélecture prédictive. Pour en savoir plus, consultez Accélérez vos sites grâce à la prélecture de pages Web à l'aide du Machine Learning .