Passer du prototype à la mise en production : entraîner des modèles personnalisés avec Vertex AI

1. Présentation

Dans cet atelier, vous allez utiliser Vertex AI pour exécuter un job d'entraînement personnalisé.

Cet atelier fait partie d'une série de vidéos appelée Passer du prototype à la mise en production. Vous y créerez un modèle de classification d'images à l'aide de l'ensemble de données Flowers. Vous pouvez consulter la vidéo associée pour approfondir vos connaissances :

.

Objectifs de l'atelier

Vous allez apprendre à effectuer les opérations suivantes :

  • Créer un notebook géré par Vertex AI Workbench
  • Configurer et lancer un job d'entraînement personnalisé à partir de l'interface utilisateur de Vertex AI
  • Configurer et lancer un job d'entraînement personnalisé avec le SDK Vertex AI pour Python

Le coût total d'exécution de cet atelier sur Google Cloud est d'environ 1 $.

2. Présentation de Vertex AI

Cet atelier utilise la toute dernière offre de produits d'IA de Google Cloud. Vertex AI simplifie l'expérience de développement en intégrant toutes les offres de ML de Google Cloud. Auparavant, les modèles entraînés avec AutoML et les modèles personnalisés étaient accessibles via des services distincts. La nouvelle offre regroupe ces deux types de modèles mais aussi d'autres nouveaux produits en une seule API. Vous pouvez également migrer des projets existants vers Vertex AI.

Vertex AI comprend de nombreux produits différents qui permettent de gérer les workflows de ML de bout en bout. Cet atelier se concentre sur les produits mis en évidence ci-dessous : Training et Workbench.

Présentation des produits Vertex

3. Configurer votre environnement

Pour suivre cet atelier de programmation, vous aurez besoin d'un projet Google Cloud Platform dans lequel la facturation est activée. Pour créer un projet, suivez ces instructions.

Étape 1 : Activez l'API Compute Engine

Accédez à Compute Engine et cliquez sur Activer si ce n'est pas déjà fait.

Étape 2 : Activez l'API Artifact Registry

Accédez à Artifact Registry et cliquez sur Activer si ce n'est pas déjà fait. Vous l'utiliserez afin de créer un conteneur pour votre job d'entraînement personnalisé.

Étape 3 : Activez l'API Vertex AI

Accédez à la section Vertex AI de Cloud Console, puis cliquez sur Activer l'API Vertex AI.

Tableau de bord Vertex AI

Étape 4 : Créez une instance Vertex AI Workbench

Dans la section Vertex AI de Cloud Console, cliquez sur Workbench :

Menu Vertex AI

Activez l'API Notebooks si ce n'est pas déjà fait.

Notebook_api

Une fois l'API activée, cliquez sur NOTEBOOKS GÉRÉS :

Notebooks_UI

Sélectionnez ensuite NOUVEAU NOTEBOOK.

new_notebook

Attribuez un nom à votre notebook, puis sous Autorisation, sélectionnez Compte de service.

create_notebook

Sélectionnez Paramètres avancés.

Dans la section Sécurité, sélectionnez "Activer le terminal" si ce n'est pas déjà fait.

enable_terminal

Vous pouvez conserver tous les autres paramètres avancés tels quels.

Cliquez ensuite sur Créer. Le provisionnement de l'instance prend quelques minutes.

Une fois l'instance créée, sélectionnez OUVRIR JUPYTERLAB :

open_jupyterlab

4. Conteneuriser le code de l'application d'entraînement

Vous allez soumettre ce job d'entraînement à Vertex AI en plaçant votre code d'application d'entraînement dans un conteneur Docker et en déployant ce conteneur dans Google Artifact Registry. Cette approche vous permet d'entraîner un modèle créé avec n'importe quel framework.

Pour commencer, à partir du menu de lancement, ouvrez une fenêtre de terminal dans votre instance de notebook :

Ouvrir le terminal dans le notebook

Étape 1 : Créez un bucket Cloud Storage

Dans ce job d'entraînement, vous allez exporter le modèle TensorFlow entraîné vers un bucket Cloud Storage. Vous stockerez également les données d'entraînement dans un bucket Cloud Storage.

Depuis votre terminal, exécutez la commande suivante afin de définir une variable d'environnement pour votre projet, en veillant à remplacer your-cloud-project par l'ID de votre projet :

PROJECT_ID='your-cloud-project'

Ensuite, exécutez la commande suivante dans votre terminal pour créer un bucket dans votre projet.

BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET

Étape 2 : Copiez les données dans le bucket Cloud Storage

Vous devez transférer votre ensemble de données "Flowers" dans Cloud Storage. À titre de démonstration, vous allez d'abord télécharger l'ensemble de données sur cette instance Workbench, puis le copier dans un bucket.

Téléchargez et décompressez les données.

wget https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
tar xvzf flower_photos.tgz

Ensuite, copiez-les dans le bucket que vous venez de créer. Vous devez ajouter l'option -r afin de copier l'ensemble du répertoire et l'option -m pour effectuer une copie multitraitement, ce qui accélère les choses.

gsutil -m cp -r flower_photos $BUCKET

Étape 3 : Rédigez le code d'entraînement

Créez un répertoire appelé flowers et utilisez la commande cd pour y accéder :

mkdir flowers
cd flowers

Exécutez la commande suivante afin de créer un répertoire pour le code d'entraînement et un fichier Python dans lequel vous pourrez ajouter le code.

mkdir trainer
touch trainer/task.py

Votre répertoire flowers/ doit maintenant contenir les éléments suivants :

+ trainer/
    + task.py

Pour plus de détails concernant la méthode de structuration de votre code d'application d'entraînement, consultez la documentation

Ouvrez ensuite le fichier task.py que vous venez de créer et copiez-y le code ci-dessous.

Vous devez remplacer {your-gcs-bucket} par le nom du bucket Cloud Storage que vous venez de créer.

Grâce à l'outil FUSE de Cloud Storage, les jobs d'entraînement créés sur Vertex AI Training peuvent accéder aux données sur Cloud Storage sous forme de fichiers disponibles dans le système de fichiers local. Lorsque vous démarrez un job d'entraînement personnalisé, celui-ci peut lire un répertoire /gcs qui contient tous vos buckets Cloud Storage en tant que sous-répertoires. Pour cette raison, les chemins de données dans le code d'entraînement commencent par /gcs.

import tensorflow as tf
import numpy as np
import os

## Replace {your-gcs-bucket} !!
BUCKET_ROOT='/gcs/{your-gcs-bucket}'

# Define variables
NUM_CLASSES = 5
EPOCHS=10
BATCH_SIZE = 32

IMG_HEIGHT = 180
IMG_WIDTH = 180

DATA_DIR = f'{BUCKET_ROOT}/flower_photos'

def create_datasets(data_dir, batch_size):
  '''Creates train and validation datasets.'''

  train_dataset = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(IMG_HEIGHT, IMG_WIDTH),
    batch_size=batch_size)

  validation_dataset = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(IMG_HEIGHT, IMG_WIDTH),
    batch_size=batch_size)

  train_dataset = train_dataset.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
  validation_dataset = validation_dataset.cache().prefetch(buffer_size=tf.data.AUTOTUNE)

  return train_dataset, validation_dataset

def create_model():
  '''Creates model.'''

  model = tf.keras.Sequential([
    tf.keras.layers.Resizing(IMG_HEIGHT, IMG_WIDTH),
    tf.keras.layers.Rescaling(1./255, input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
    tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(NUM_CLASSES, activation='softmax')
  ])
  return model

# CREATE DATASETS
train_dataset, validation_dataset = create_datasets(DATA_DIR, BATCH_SIZE)

# CREATE/COMPILE MODEL
model = create_model()
model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.SparseCategoricalCrossentropy(),
              metrics=['accuracy'])

# TRAIN MODEL
history = model.fit(
  train_dataset,
  validation_data=validation_dataset,
  epochs=EPOCHS
)

# SAVE MODEL
model.save(f'{BUCKET_ROOT}/model_output')

Étape 4 : Créez un Dockerfile

Pour conteneuriser votre code, vous devrez créer un Dockerfile. Vous allez placer dans ce Dockerfile toutes les commandes nécessaires à l'exécution de l'image. Il installera toutes les bibliothèques nécessaires et configurera le point d'entrée du code d'entraînement.

Depuis votre terminal, créez un Dockerfile vide à la racine de votre répertoire "flowers" :

touch Dockerfile

Votre répertoire flowers/ doit maintenant contenir les éléments suivants :

+ Dockerfile
+ trainer/
    + task.py

Ouvrez le Dockerfile et copiez-y le code suivant :

FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-8

WORKDIR /

# Copies the trainer code to the docker image.
COPY trainer /trainer

# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]

Passons en revue les commandes de ce fichier.

La commande FROM permet de spécifier l'image de base, qui correspond à l'image parente sur laquelle l'image que vous créez reposera. Comme image de base, vous utiliserez l'image Docker de la version 2.8 du GPU TensorFlow Enterprise des conteneurs de deep learning. Les conteneurs de deep learning de Google Cloud sont fournis avec de nombreux frameworks de ML et de science des données courants préinstallés.

La commande WORKDIR spécifie le répertoire sur l'image où les instructions suivantes sont exécutées.

La commande COPY copie le code d'entraînement dans l'image Docker. Notez que dans cet exemple, le répertoire d'entraînement ne contient qu'un seul fichier Python. Cependant, en réalité, il contiendrait probablement des fichiers supplémentaires (par exemple, un fichier appelé data.py qui assurerait le prétraitement des données et un autre appelé model.py qui contiendrait uniquement le code du modèle, etc.). Pour voir un exemple de code d'entraînement plus complexe, consultez la documentation Python sur le packaging des projets Python.

Si vous souhaitez ajouter des bibliothèques supplémentaires, vous pouvez utiliser la commande RUN pour installer pip (ex. : RUN pip install -r requirements.txt). Cela n'est toutefois pas nécessaire dans l'exemple de cet atelier.

Enfin, la commande ENTRYPOINT configure le point d'entrée pour appeler l'application d'entraînement qui sera exécutée au démarrage du job d'entraînement. En ce qui nous concerne, cela correspond à l'exécution du fichier task.py.

Pour en savoir plus sur l'écriture de fichiers Dockerfile pour Vertex AI Training, consultez cette page.

Étape 4 : Créez le conteneur

Dans le terminal de votre notebook Workbench, exécutez le code suivant afin de définir une variable d'environnement pour votre projet (veillez à remplacer your-cloud-project par l'ID de votre projet) :

PROJECT_ID='your-cloud-project'

Créer un dépôt dans Artifact Registry

REPO_NAME='flower-app'

gcloud artifacts repositories create $REPO_NAME --repository-format=docker \
--location=us-central1 --description="Docker repository"

Définissez une variable avec l'URI de votre image de conteneur dans Google Artifact Registry :

IMAGE_URI=us-central1-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/flower_image:latest

Configurer Docker

gcloud auth configure-docker \
    us-central1-docker.pkg.dev

Ensuite, créez le conteneur en exécutant la commande suivante à partir de la racine de votre répertoire flower :

docker build ./ -t $IMAGE_URI

Enfin, déployez-le dans Artifact Registry :

docker push $IMAGE_URI

Maintenant que le conteneur a été transféré vers Artifact Registry, vous êtes prêt à lancer un job d'entraînement.

5. Exécuter un job d'entraînement personnalisé sur Vertex AI

Cet atelier utilise un entraînement personnalisé via un conteneur personnalisé de Google Artifact Registry, mais vous pouvez également exécuter un job d'entraînement avec les conteneurs prédéfinis.

Pour commencer, accédez à l'onglet Entraînement de la section Vertex de votre console Cloud :

menu entraînement

Étape 1 : Configurez le job d'entraînement

Cliquez sur Créer pour saisir les paramètres de votre job d'entraînement.

create_training

  • Sous Ensemble de données, sélectionnez Aucun ensemble de données géré.
  • Sélectionnez ensuite Entraînement personnalisé (avancé) comme méthode d'entraînement, puis cliquez sur Continuer.
  • Sélectionnez Entraîner un nouveau modèle, puis saisissez flowers-model (ou un autre nom de votre choix) Nom du modèle.
  • Cliquez sur Continuer.

À l'étape des paramètres du conteneur, sélectionnez Conteneur personnalisé :

Option de conteneur personnalisé

Dans le premier champ (Image du conteneur), saisissez la valeur de votre variable IMAGE_URI de la section précédente. Il doit s'agir de us-central1-docker.pkg.dev/{PROJECT_ID}/flower-app/flower_image:latest, avec l'ID de votre propre projet. Laissez les autres champs vides et cliquez sur Continuer.

Ignorez l'étape "Hyperparamètres" en cliquant à nouveau sur Continuer.

Étape 2 : Configurez le cluster de calcul

Configurez le pool de nœuds de calcul 0 comme suit :

worker_pool_0

Vous allez ignorer l'étape 6 pour le moment et configurer le conteneur de prédiction dans le prochain atelier de cette série.

Cliquez sur DÉMARRER L'ENTRAÎNEMENT pour lancer le job d'entraînement. Votre nouveau job s'affiche dans l'onglet PIPELINES D'ENTRAÎNEMENT de la section "Entraînement" de votre console :

Jobs d'entraînement

🎉 Félicitations ! 🎉

Vous savez désormais utiliser Vertex AI pour :

  • lancer un job d'entraînement personnalisé pour un code d'entraînement fourni dans un conteneur personnalisé. Vous avez utilisé un modèle TensorFlow dans cet exemple, mais vous pouvez entraîner un modèle créé avec n'importe quel framework à l'aide de conteneurs personnalisés ou prédéfinis.

Pour en savoir plus sur les différents composants de Vertex, consultez la documentation.

6. [Facultatif] Utiliser le SDK Vertex AI pour Python

Dans la section précédente, vous avez découvert comment lancer le job d'entraînement via l'interface utilisateur. Dans cette section, vous allez voir une autre façon de soumettre le job d'entraînement à l'aide du SDK Vertex AI pour Python.

Revenez à votre instance de notebook et créez un notebook TensorFlow 2 via le lanceur :

new_notebook

Importez le SDK Vertex AI.

from google.cloud import aiplatform

Ensuite, créez un CustomContainerTrainingJob. Vous devez remplacer la valeur de {PROJECT_ID} dans container_uri par le nom de votre projet, et {BUCKET} dans staging_bucket par le bucket que vous avez créé précédemment.

my_job = aiplatform.CustomContainerTrainingJob(display_name='flower-sdk-job',
                                               container_uri='us-central1-docker.pkg.dev/{PROJECT_ID}/flower-app/flower_image:latest',
                                               staging_bucket='gs://{BUCKET}')

Ensuite, exécutez le job.

my_job.run(replica_count=1,
           machine_type='n1-standard-8',
           accelerator_type='NVIDIA_TESLA_V100',
           accelerator_count=1)

À titre de démonstration, ce job a été configuré pour s'exécuter sur une machine de capacité supérieure à celle de la section précédente. En outre, l'exécution repose sur un GPU. Si vous ne spécifiez pas machine-type, accelerator_type, or accelerator_count, le job s'exécutera par défaut sur n1-standard-4.

Votre job d'entraînement s'affiche dans l'onglet JOBS PERSONNALISÉS de la section "Entraînement" de votre console.

7. Nettoyage

Étant donné que les notebooks gérés par Vertex AI Workbench disposent d'une fonctionnalité d'arrêt en cas d'inactivité, vous n'avez pas à vous soucier de l'arrêt de l'instance. Si vous souhaitez arrêter l'instance manuellement, cliquez sur le bouton "Arrêter" dans la section "Vertex AI Workbench" de la console. Si vous souhaitez supprimer le notebook définitivement, cliquez sur le bouton "Supprimer".

Arrêter l'instance

Pour supprimer le bucket de stockage, utilisez le menu de navigation de la console Cloud pour accéder à Stockage, sélectionnez votre bucket puis cliquez sur "Supprimer" :

Supprimer l'espace de stockage