Vertex AI – réglages d'hyperparamètres

1. Présentation

Dans cet atelier, vous allez utiliser Vertex AI afin d'exécuter un job de réglage des hyperparamètres pour un modèle TensorFlow. Bien que cet atelier utilise TensorFlow pour le code du modèle, les concepts s'appliquent également à d'autres frameworks de ML.

Objectifs

Vous allez apprendre à effectuer les opérations suivantes :

  • Modifier le code de l'application d'entraînement pour le réglage automatique des hyperparamètres
  • Configurer et lancer un job de réglage des hyperparamètres à partir de l'interface utilisateur de Vertex AI
  • Configurer et lancer un job de réglage des hyperparamètres avec le SDK Vertex AI pour Python

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

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 depuis 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. Pour envoyer un commentaire, consultez la page d'assistance.

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. Vous en aurez besoin pour créer votre instance de notebook.

Étape 2 : Activez l'API Container Registry

Accédez à Container Registry et cliquez sur Activer si ce n'est pas déjà fait. Vous utiliserez ce service afin de créer un conteneur pour votre tâche 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 cliquez sur Paramètres avancés.

create_notebook

Sous "Paramètres avancés", activez l'arrêt en cas d'inactivité et définissez le nombre de minutes sur 60. Cela entraîne l'arrêt automatique du notebook lorsqu'il n'est pas utilisé. Vous ne payez donc pas de frais inutiles.

idle_timeout

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

La première fois que vous utilisez une nouvelle instance, vous êtes invité à vous authentifier. Pour ce faire, suivez les étapes indiquées dans l'interface utilisateur.

authenticate

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

Le modèle que vous allez entraîner et régler dans cet atelier est un modèle de classification d'images entraîné avec l'ensemble de données "horses_or_humans" de TensorFlow.

Vous allez envoyer ce job de réglage des hyperparamètres à Vertex AI en plaçant le code de votre application d'entraînement dans un conteneur Docker et en transférant ce conteneur vers Google Container Registry. Cette approche vous permet de régler les hyperparamètres d'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

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

mkdir horses_or_humans
cd horses_or_humans

Étape 1: Créez un Dockerfile

La première étape de la conteneurisation de votre code consiste à 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 requises, y compris la bibliothèque cloudml-hypertune, et configurera le point d'entrée du code d'entraînement.

Depuis votre terminal, créez un Dockerfile vide:

touch Dockerfile

Ouvrez le Dockerfile et copiez-y le code suivant :

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

WORKDIR /

# Installs hypertune library
RUN pip install cloudml-hypertune

# 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"]

Ce fichier Dockerfile utilise l'image Docker avec GPU de TensorFlow Enterprise 2.7 comme conteneur de deep learning. Les conteneurs de deep learning sur Google Cloud sont fournis avec de nombreux frameworks de ML et de data science courants préinstallés. Une fois cette image téléchargée, ce Dockerfile configure le point d'entrée du code d'entraînement. Vous n'avez pas encore créé ces fichiers. À la prochaine étape, vous allez ajouter le code d'entraînement et de réglage du modèle.

Étape 2: Ajoutez le code d'entraînement du modèle

Depuis votre terminal, exécutez le code suivant afin de créer un répertoire pour le code d'entraînement et un fichier Python dans lequel vous ajouterez le code :

mkdir trainer
touch trainer/task.py

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

+ Dockerfile
+ trainer/
    + task.py

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

import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune

NUM_EPOCHS = 10


def get_args():
  '''Parses args. Must include all hyperparameters you want to tune.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--learning_rate',
      required=True,
      type=float,
      help='learning rate')
  parser.add_argument(
      '--momentum',
      required=True,
      type=float,
      help='SGD momentum value')
  parser.add_argument(
      '--num_units',
      required=True,
      type=int,
      help='number of units in last hidden layer')
  args = parser.parse_args()
  return args


def preprocess_data(image, label):
  '''Resizes and scales images.'''

  image = tf.image.resize(image, (150,150))
  return tf.cast(image, tf.float32) / 255., label


def create_dataset():
  '''Loads Horses Or Humans dataset and preprocesses data.'''

  data, info = tfds.load(name='horses_or_humans', as_supervised=True, with_info=True)

  # Create train dataset
  train_data = data['train'].map(preprocess_data)
  train_data  = train_data.shuffle(1000)
  train_data  = train_data.batch(64)

  # Create validation dataset
  validation_data = data['test'].map(preprocess_data)
  validation_data  = validation_data.batch(64)

  return train_data, validation_data


def create_model(num_units, learning_rate, momentum):
  '''Defines and compiles model.'''

  inputs = tf.keras.Input(shape=(150, 150, 3))
  x = tf.keras.layers.Conv2D(16, (3, 3), activation='relu')(inputs)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(32, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(64, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(num_units, activation='relu')(x)
  outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)
  model = tf.keras.Model(inputs, outputs)
  model.compile(
      loss='binary_crossentropy',
      optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
      metrics=['accuracy'])
  return model


def main():
  args = get_args()
  train_data, validation_data = create_dataset()
  model = create_model(args.num_units, args.learning_rate, args.momentum)
  history = model.fit(train_data, epochs=NUM_EPOCHS, validation_data=validation_data)

  # DEFINE METRIC
  hp_metric = history.history['val_accuracy'][-1]

  hpt = hypertune.HyperTune()
  hpt.report_hyperparameter_tuning_metric(
      hyperparameter_metric_tag='accuracy',
      metric_value=hp_metric,
      global_step=NUM_EPOCHS)


if __name__ == "__main__":
    main()

Avant de créer le conteneur, examinons le code de plus près. Certains composants sont utilisés spécifiquement pour le service de réglage des hyperparamètres.

  1. Le script importe la bibliothèque hypertune. Notez que le Dockerfile de l'étape 1 contenait des instructions pour l'installation de cette bibliothèque avec pip.
  2. La fonction get_args() définit un argument de ligne de commande pour chaque hyperparamètre que vous souhaitez régler. Dans cet exemple, les hyperparamètres qui seront réglés sont le taux d'apprentissage, la valeur du momentum dans l'optimiseur et le nombre d'unités dans la dernière couche cachée du modèle, mais n'hésitez pas à effectuer des tests avec d'autres hyperparamètres. La valeur transmise dans ces arguments est ensuite utilisée pour définir l'hyperparamètre correspondant dans le code.
  3. À la fin de la fonction main(), la bibliothèque hypertune permet de définir la métrique que vous souhaitez optimiser. Dans TensorFlow, la méthode Keras model.fit renvoie un objet History. L'attribut History.history est un enregistrement des valeurs de perte d'entraînement et des métriques à des époques successives. Si vous transmettez des données de validation à model.fit, l'attribut History.history inclut également les valeurs de perte de validation et celles des métriques. Par exemple, si vous aviez entraîné un modèle pendant trois époques avec des données de validation et que vous aviez fourni accuracy comme métrique, l'attribut History.history ressemblerait au dictionnaire suivant.
{
 "accuracy": [
   0.7795261740684509,
   0.9471358060836792,
   0.9870933294296265
 ],
 "loss": [
   0.6340447664260864,
   0.16712145507335663,
   0.04546636343002319
 ],
 "val_accuracy": [
   0.3795261740684509,
   0.4471358060836792,
   0.4870933294296265
 ],
 "val_loss": [
   2.044623374938965,
   4.100203514099121,
   3.0728273391723633
 ]

Si vous souhaitez que le service de réglage des hyperparamètres découvre les valeurs qui maximisent la justesse de la validation du modèle, vous devez définir la métrique en tant que dernière entrée (ou NUM_EPOCS - 1) de la liste val_accuracy. Transmettez ensuite cette métrique à une instance de HyperTune. Vous pouvez choisir la chaîne que vous voulez pour hyperparameter_metric_tag, mais vous devrez la réutiliser ultérieurement lorsque vous lancerez le job de réglage des hyperparamètres.

Étape 3 : Créez le conteneur

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'

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

IMAGE_URI="gcr.io/$PROJECT_ID/horse-human:hypertune"

Configurez Docker.

gcloud auth configure-docker

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

docker build ./ -t $IMAGE_URI

Enfin, transférez-le vers Google Container Registry :

docker push $IMAGE_URI

Maintenant que le conteneur a été transféré vers Container Registry, vous êtes prêt à lancer un job de réglage des hyperparamètres d'un modèle personnalisé.

5. Exécuter une tâche de réglage des hyperparamètres sur Vertex AI

Cet atelier utilise un entraînement personnalisé via un conteneur personnalisé de Google Container Registry, mais vous pouvez également exécuter un job de réglage des hyperparamètres avec un conteneur Vertex AI prédéfini.

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

Menu uCAIP

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

Cliquez sur Créer pour saisir les paramètres de votre tâche de réglage des hyperparamètres.

  • 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.
  • Saisissez horses-humans-hyptertune (ou tout autre nom que vous souhaitez donner à votre modèle) dans 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 gcr.io/your-cloud-project/horse-human:hypertune, avec le nom de votre projet. Laissez les autres champs vides et cliquez sur Continuer.

Étape 2: Configurez le job de réglage des hyperparamètres

Sélectionnez Activer le réglage des hyperparamètres.

Hyperparamètres

Configurer les hyperparamètres

Vous devez ensuite ajouter les hyperparamètres que vous définissez comme arguments de ligne de commande dans le code de l'application d'entraînement. Lorsque vous ajoutez un hyperparamètre, vous devez d'abord en indiquer le nom. Il doit correspondre au nom d'argument que vous avez transmis à argparse.

learning_rate_name

Ensuite, vous sélectionnerez le Type ainsi que les limites pour les valeurs que le service de réglage essayera. Si vous sélectionnez le type "Double" ou "Entier", vous devez indiquer des valeurs minimale et maximale. Si vous sélectionnez un type "Catégoriel" ou "Discret", vous devez indiquer les valeurs.

learning_rate_typelearning_rate_name

Pour les types "Double" et "Entier", vous devez également fournir la valeur de scaling.

learning_rate_scale

Après avoir ajouté l'hyperparamètre learning_rate, ajoutez des paramètres pour momentum et num_units.

momentum_config

numneruons_config

Configurer la métrique

Une fois que vous avez ajouté les hyperparamètres, vous devez fournir la métrique que vous voulez optimiser ainsi que l'objectif. Il doit être identique au hyperparameter_metric_tag que vous avez défini dans votre application d'entraînement.

metric_config

Le service de réglage des hyperparamètres de Vertex AI effectue plusieurs essais avec votre application d'entraînement en utilisant les valeurs configurées au cours des étapes précédentes. Vous devez fixer une limite pour que le service ne dépasse pas un certain nombre d'essais. Un plus grand nombre d'essais permet généralement d'obtenir de meilleurs résultats, mais il existe un point de retours décroissants au-delà duquel les essais supplémentaires n'ont que peu ou pas d'effet sur la métrique que vous essayez d'optimiser. Il est recommandé de commencer avec un petit nombre d'essais et d'attendre d'avoir une idée du degré d'impact des hyperparamètres choisis pour passer à un grand nombre d'essais.

Vous devez également définir un nombre maximal d'essais parallèles. L'augmentation du nombre d'essais parallèles a pour effet de réduire le temps nécessaire à l'exécution du job de réglage des hyperparamètres. Toutefois, elle peut réduire l'efficacité globale du job. En effet, la stratégie de réglage par défaut utilise les résultats des essais précédents pour ajuster les valeurs affectées lors des essais suivants. Si vous exécutez un trop grand nombre d'essais en parallèle, certains essais démarreront sans bénéficier du résultat des essais qui sont toujours en cours d'exécution.

À titre de démonstration, vous pouvez définir le nombre d'essais sur 15 et le nombre maximal d'essais parallèles sur 3. Vous pouvez faire des tests avec des valeurs différentes, mais cela risque d'allonger le temps de réglage et d'augmenter les coûts.

trial_config

La dernière étape consiste à sélectionner l'algorithme de recherche par défaut. Google Vizier effectuera alors une optimisation bayésienne pour le réglage des hyperparamètres. En savoir plus sur cet algorithme

algorithm_config

Cliquez sur Continuer.

Étape 3: Configurez le calcul

Dans Options de calcul et tarifs, ne modifiez pas la région sélectionnée et configurez le Pool de nœuds de calcul 0 comme suit.

Type de machine

Cliquez sur Démarrer l'entraînement pour lancer le job de réglage des hyperparamètres. Dans l'onglet TÂCHES DE RÉGLAGE D'HYPERPARAMÈTRES de la section "Entraînement" de votre console, vous devriez voir ceci:

Jobs d'hyperparamètres

Quand il sera terminé, vous pourrez cliquer sur le nom du job et voir les résultats des essais de réglage.

Sortie des hyperparamètres

🎉 Félicitations ! 🎉

Vous savez désormais utiliser Vertex AI pour :

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

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

6. [Facultatif] Utiliser Vertex SDK

La section précédente vous a indiqué comment lancer la tâche de réglage des hyperparamètres via l'interface utilisateur. Dans cette section, vous allez voir une autre façon de soumettre le job de réglage des hyperparamètres à l'aide de l'API Vertex pour Python.

Créez un notebook TensorFlow 2 via le lanceur.

new_notebook

Importez le SDK Vertex AI.

from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt

Pour lancer le job de réglage des hyperparamètres, vous devez d'abord définir les spécifications suivantes. Vous devrez remplacer {PROJECT_ID} par l'ID de votre projet dans image_uri.

# The spec of the worker pools including machine type and Docker image
# Be sure to replace PROJECT_ID in the `image_uri` with your project.

worker_pool_specs = [{
    "machine_spec": {
        "machine_type": "n1-standard-4",
        "accelerator_type": "NVIDIA_TESLA_V100",
        "accelerator_count": 1
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human:hypertune"
    }
}]


# Dictionary representing metrics to optimize.
# The dictionary key is the metric_id, which is reported by your training job,
# And the dictionary value is the optimization goal of the metric.
metric_spec={'accuracy':'maximize'}

# Dictionary representing parameters to optimize.
# The dictionary key is the parameter_id, which is passed into your training
# job as a command line argument,
# And the dictionary value is the parameter specification of the metric.
parameter_spec = {
    "learning_rate": hpt.DoubleParameterSpec(min=0.001, max=1, scale="log"),
    "momentum": hpt.DoubleParameterSpec(min=0, max=1, scale="linear"),
    "num_units": hpt.DiscreteParameterSpec(values=[64, 128, 512], scale=None)
}

Ensuite, créez un CustomJob. Vous devez remplacer {YOUR_BUCKET} par un bucket de votre projet pour la préproduction.

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans-sdk-job',
                              worker_pool_specs=worker_pool_specs,
                              staging_bucket='gs://{YOUR_BUCKET}')

Ensuite, créez et exécutez HyperparameterTuningJob.

hp_job = aiplatform.HyperparameterTuningJob(
    display_name='horses-humans-sdk-job',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=15,
    parallel_trial_count=3)

hp_job.run()

7. Nettoyage

Comme le notebook est configuré pour expirer au bout de 60 minutes d'inactivité, il n'est pas nécessaire d'arrêter 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