Diffuser des modèles Spark ML à l'aide de Vertex AI

Last reviewed 2022-02-22 UTC

Ce tutoriel explique comment diffuser (exécuter) des prédictions en ligne à partir de modèles de machine learning (ML) créés à l'aide de Spark MLlib et gérés à l'aide de Vertex AI. Les audiences principales de ce tutoriel sont les data scientists et les ingénieurs en ML qui utilisent Spark MLlib pour créer des modèles de ML et souhaitent diffuser ces modèles dans Vertex AI.

Pour suivre ce tutoriel, vous devez remplir les conditions ci-dessous :

Implémentation

Cette section présente la mise en œuvre que vous allez effectuer dans ce tutoriel. Cette mise en œuvre est la même, que vous utilisiez l'exemple de modèle de ce tutoriel ou votre propre modèle MLlib.

Le schéma suivant illustre l'architecture de diffusion du modèle que vous mettez en œuvre dans ce tutoriel :

Architecture de diffusion du modèle utilisé dans le tutoriel

Comme décrit dans le schéma, Cloud Build utilise le code stocké dans Cloud Storage pour préparer une image de conteneur personnalisé (appelée image de conteneur de diffusion) qui est utilisée par Vertex AI pour exécuter des prédictions. Le processus de compilation compile et empaquette le code de diffusion du modèle que vous utilisez dans ce tutoriel, crée l'image de conteneur et transfère l'image à Artifact Registry.

Une fois l'image de conteneur de diffusion transférée dans Artifact Registry, le modèle doit être importé depuis Cloud Storage dans Vertex AI. Le modèle importé est configuré avec l'emplacement des artefacts de modèle dans Cloud Storage et avec l'emplacement de l'image de conteneur de diffusion dans Artifact Registry.

Vous créez ensuite un point de terminaison dans Vertex AI et vous y déployez le modèle importé. Lorsque vous déployez le modèle, Vertex AI associe des ressources physiques au modèle afin qu'il puisse diffuser les prédictions en ligne.

Vous trouverez le modèle utilisé dans ce tutoriel dans le répertoire example_model du dépôt vertex-ai-spark-ml-serving.git. Le répertoire contient les artefacts de modèle utilisés par le conteneur de diffusion pour exécuter des prédictions, et inclut les fichiers suivants:

  • Le fichier example_model/model.zip est un modèle de régression logistique créé à l'aide de Spark MLlib, entraîné à l'aide de l'ensemble de données Iris et converti en bundle MLeap. Le modèle prédit la variété des iris en utilisant la longueur et la largeur des sépales et des pétales des fleurs.
  • Le fichier example_model/schema.json est un fichier JSON qui décrit le schéma du modèle. Le schéma de modèle décrit les champs de saisie attendus pour les instances de prédiction et les champs de sortie pour les résultats de prédiction requis pour le schéma MLeap.

Diffuser vos propres modèles

Vous pouvez également utiliser l'image de conteneur de diffusion de ce tutoriel comme mise en œuvre de référence pour diffuser vos propres modèles. Pour diffuser vos propres modèles, vous devez fournir vos propres artefacts de modèle, y compris le bundle MLeap et le schéma du modèle.

Fournir le bundle MLeap

Le conteneur de diffusion détermine l'emplacement du bundle MLeap à l'aide de la variable d'environnement AIP_STORAGE_URI transmise de Vertex AI au conteneur au démarrage. La valeur de la variable AIP_STORAGE_URI est spécifiée lorsque vous importez le modèle dans Vertex AI. Le conteneur de diffusion de ce tutoriel s'attend à ce que le bundle MLeap soit disponible à l'adresse ${AIP_STORAGE_URI}/model.zip.

Fournir le schéma de modèle

Le schéma de modèle décrit les caractéristiques d'entrée et le résultat de la prédiction d'un modèle. Le schéma de modèle est représenté à l'aide de données JSON. Pour transmettre le schéma de modèle au conteneur de diffusion, vous pouvez appliquer l'une des méthodes suivantes :

  • Spécifiez les données JSON qui définissent le schéma dans la variable d'environnement MLEAP_SCHEMA. La variable d'environnement MLEAP_SCHEMA doit contenir les données JSON, et non un chemin d'accès à un fichier contenant le schéma JSON.
  • Stockez les données JSON dans un fichier nommé schema.json et mettez ce fichier à la disposition du conteneur à l'adresse ${AIP_STORAGE_URI}/schema.json. Il s'agit de la méthode que vous utilisez dans ce tutoriel.

Si vous utilisez les deux méthodes pour transmettre le schéma de modèle au conteneur de diffusion, les données JSON stockées dans la variable d'environnement MLEAP_SCHEMA sont prioritaires.

Lorsque vous utilisez vos propres modèles, vous configurez votre propre schéma. L'exemple de modèle utilise le schéma suivant pour prédire les espèces d'iris en fonction de la longueur et de la largeur des sépales et des pétales de la fleur :

{
  "input": [
    {
      "name": "sepal_length",
      "type": "FLOAT"
    },
    {
      "name": "sepal_width",
      "type": "FLOAT"
    },
    {
      "name": "petal_length",
      "type": "FLOAT"
    },
    {
      "name": "petal_width",
      "type": "FLOAT"
    }
  ],
  "output": [
    {
      "name": "probability",
      "type": "DOUBLE",
      "struct": "VECTOR"
    }
  ]
}

Dans le schéma de modèle, le tableau input contient les champs d'entrée (colonnes) à destination du modèle, tandis que le tableau output contient les champs de sortie (colonnes) à renvoyer à partir du modèle. Dans les deux tableaux, chaque objet du tableau contient les propriétés suivantes :

  • name : nom du champ (colonne)
  • type: type de champ (colonne). Les types valides sont BOOLEAN, BYTE, DOUBLE, FLOAT, INTEGER, LONG, SHORT et STRING.
  • (Facultatif) struct: la structure du champ, telle qu'un scalaire ou un tableau. Les structures valides sont BASIC (type scalaire), ARRAY (Array Spark) et VECTOR (DenseVector Spark). BASIC est utilisé si le champ struct n'est pas présent.

Objectifs

  • Décrivez une approche de diffusion des prédictions en ligne à partir de modèles Spark MLlib à l'aide de Vertex AI.
  • Expliquez la fonction de l'image de conteneur de diffusion et savoir comment la configurer.
  • Utilisez Vertex AI pour diffuser des prédictions en ligne à partir d'un exemple de modèle inclus dans ce tutoriel.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  2. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  3. Activer les API Vertex AI, Cloud Build, Cloud Storage, and Artifact Registry.

    Activer les API

  4. Dans la console Google Cloud, activez Cloud Shell.

    Activer Cloud Shell

  5. Recherchez votre ID de projet et définissez-le dans Cloud Shell.
    export PROJECT_ID=YOUR_PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    en remplaçant YOUR_PROJECT_ID par l'ID de votre projet :

Créer l'image de compilateur scala-sbt

Vous utilisez Cloud Build avec le compilateur de la communauté scala-sbt pour créer l'image de conteneur de diffusion. Ce processus de compilation dépend de l'image de compilateur sbt-scala contenue dans le registre Container Registry de votre projet.

  1. Dans Cloud Shell, clonez le dépôt cloud-builders-community :

    git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
    
  2. Accédez au répertoire du projet :

    cd cloud-builders-community/scala-sbt
    
  3. Créez l'image à l'aide du compilateur scala-sbt et transférez-la vers Container Registry :

    gcloud builds submit .
    

Créer l'image de conteneur de diffusion

Vertex AI utilise le conteneur de diffusion pour exécuter des requêtes de prédiction pour l'exemple de modèle. La première étape de la création de l'image de conteneur de diffusion consiste à créer un dépôt Docker dans Artifact Registry dans lequel stocker l'image. Vous devez ensuite autoriser Vertex AI à extraire l'image de conteneur de diffusion du dépôt. Une fois le dépôt créé et les autorisations accordées, vous pouvez créer l'image de conteneur de diffusion et la transférer vers Artifact Registry.

  1. Dans Cloud Shell, créez un dépôt Docker dans Artifact Registry :

    REPOSITORY="vertex-ai-prediction"
    LOCATION="us-central1"
    
    gcloud artifacts repositories create $REPOSITORY \
        --repository-format=docker \
        --location=$LOCATION
    
  2. Attribuez le rôle de lecteur Artifact Registry à l'agent de service Vertex AI :

    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
        --format="value(projectNumber)")
    SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SERVICE_ACCOUNT" \
        --role="roles/artifactregistry.reader"
    
  3. Clonez le dépôt spark-ml-serving :

    git clone https://github.com/GoogleCloudPlatform/vertex-ai-spark-ml-serving.git
    
  4. Accédez au répertoire du projet :

    cd vertex-ai-spark-ml-serving
    
  5. Créez l'image de conteneur de diffusion dans votre projet :

    IMAGE=spark-ml-serving
    
    gcloud builds submit --config=cloudbuild.yaml \
        --substitutions="_LOCATION=$LOCATION,_REPOSITORY=$REPOSITORY,_IMAGE=$IMAGE" .
    

    Le fichier cloudbuild.yaml spécifie deux compilateurs : le compilateur scala-sbt et le compilateur d'images docker. Cloud Build utilise le compilateur scala-sbt pour compiler le code de diffusion du modèle à partir de Cloud Storage, puis empaqueter le code compilé dans un fichier JAR exécutable. Cloud Build utilise le compilateur docker pour créer l'image de conteneur de diffusion contenant le fichier JAR. Une fois l'image de conteneur de diffusion créée, elle est transférée vers Artifact Registry.

Importer le modèle dans Vertex AI

Le conteneur de diffusion lit les artefacts de modèle depuis Cloud Storage. Vous devez créer un emplacement de stockage pour ces artefacts avant d'importer le modèle dans Vertex AI. Lorsque vous importez ensuite le modèle, vous avez besoin à la fois de l'emplacement de stockage de l'artefact du modèle et de l'image du conteneur de diffusion dans Artifact Registry.

  1. Dans Cloud Shell, créez un bucket pour les artefacts du modèle :

    REGION="us-central1"
    BUCKET="YOUR_BUCKET_NAME"
    gsutil mb -l $REGION gs://$BUCKET
    

    Remplacez YOUR_BUCKET_NAME par le nom de votre bucket :

  2. Copiez les artefacts de modèle dans le bucket :

    gsutil cp example_model/* gs://$BUCKET/example_model/
    
  3. Importez le modèle dans Vertex AI :

    DISPLAY_NAME="iris-$(date +'%Y%m%d%H%M%S')"
    IMAGE_URI="${LOCATION}-docker.pkg.dev/$PROJECT_ID/${REPOSITORY}/${IMAGE}"
    ARTIFACT_URI="gs://$BUCKET/example_model/"
    
    gcloud ai models upload \
        --region=$REGION \
        --display-name=$DISPLAY_NAME \
        --container-image-uri=$IMAGE_URI \
        --artifact-uri=$ARTIFACT_URI \
        --container-health-route="/health" \
        --container-predict-route="/predict"
    

    Dans la commande gcloud ai models upload, la valeur du paramètre --artifact-uri spécifie la valeur de la variable AIP_STORAGE_URI. Cette variable fournit l'emplacement du bundle MLeap en cours d'importation vers Vertex AI.

Déployer le modèle sur un nouveau point de terminaison

Pour que Vertex AI puisse exécuter des prédictions, le modèle importé doit être déployé sur un point de terminaison. Vous avez besoin à la fois de l'ID du point de terminaison et de l'ID du modèle lorsque vous déployez le modèle.

  1. Dans Cloud Shell, créez le point de terminaison du modèle :

    gcloud ai endpoints create \
        --region=$REGION \
        --display-name=$DISPLAY_NAME
    

    La création du point de terminaison de l'outil de ligne de commande gcloud peut prendre quelques secondes.

  2. Obtenez l'ID du point de terminaison que vous venez de créer :

    ENDPOINT_ID=$(gcloud ai endpoints list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print ENDPOINT_ID to the console
    echo "Your endpoint ID is: $ENDPOINT_ID"
    
  3. Obtenez l'ID du modèle que vous avez importé dans la section Importer le modèle dans Vertex AI :

    MODEL_ID=$(gcloud ai models list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print MODEL_ID to the console
    echo "Your model ID is: $MODEL_ID"
    
  4. Déployez le modèle sur le point de terminaison :

    gcloud ai endpoints deploy-model $ENDPOINT_ID \
        --region=$REGION \
        --model=$MODEL_ID \
        --display-name=$DISPLAY_NAME \
        --traffic-split="0=100"
    

    La commande gcloud déploie le modèle sur le point de terminaison. Les valeurs par défaut sont utilisées pour le type de ressource de la machine, le nombre minimal et maximal de nœuds, ainsi que d'autres options de configuration. Pour en savoir plus sur les options de déploiement des modèles, consultez la documentation sur Vertex AI.

Tester le point de terminaison

Après avoir déployé le modèle sur le point de terminaison, vous pouvez tester votre mise en œuvre. Pour tester le point de terminaison, vous pouvez utiliser l'exemple de client inclus dans le code du tutoriel. L'exemple de client génère des instances de prédiction et envoie des requêtes de prédiction au point de terminaison. Chaque instance de prédiction contient des valeurs aléatoires pour sepal_length, sepal_width, petal_length et petal_width. Par défaut, l'exemple de client combine plusieurs instances de prédiction en une seule requête. La réponse de la réponse du point de terminaison inclut une prédiction pour chaque instance envoyée dans la requête. La prédiction contient les probabilités pour chaque classe de l'ensemble de données Iris (setosa, versicolor et virginica).

  • Dans Cloud Shell, exécutez l'exemple de client de prédiction :

    cd example_client
    ./run_client.sh --project $PROJECT_ID \
        --location $LOCATION \
        --endpoint $ENDPOINT_ID
    

    Lorsque vous exécutez le script pour la première fois, il crée un environnement virtuel Python et installe des dépendances. Après avoir installé les dépendances, le script exécute l'exemple de client. Pour chaque requête, le client imprime les instances de prédiction et les probabilités de classe correspondantes sur le terminal. Voici un extrait du résultat:

    Sending 10 asynchronous prediction requests with 3 instances per request ...
    
    ==> Response from request #10:
    
    Instance 1:     sepal_length:   5.925825137450266
                    sepal_width:    4.5047557888651
                    petal_length:   1.0432434310300223
                    petal_width:    0.5050397721287457
    
    Prediction 1:   setosa:         0.2036041134824573
                    versicolor:     0.6062980065549213
                    virginica:      0.1900978799626214
    
    Instance 2:     sepal_length:   6.121228622484405
                    sepal_width:    3.406317728235072
                    petal_length:   3.178583759980504
                    petal_width:    2.815141143581328
    
    Prediction 2:   setosa:         0.471811302254083
                    versicolor:     0.2063720436033448
                    virginica:      0.3218166541425723
    
    Instance 3:     sepal_length:   7.005781590327274
                    sepal_width:    2.532116893508745
                    petal_length:   2.6351337947193474
                    petal_width:    2.270855223519198
    
    Prediction 3:   setosa:         0.453579051699638
                    versicolor:     0.2132869980698818
                    virginica:      0.3331339502304803
    

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Supprimer le projet

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer des ressources individuelles

  1. Dans Cloud Shell, annulez le déploiement du modèle sur le point de terminaison :

    DEPLOYED_MODEL_ID=$(gcloud ai endpoints describe $ENDPOINT_ID \
        --region=$REGION \
        --format='value(deployedModels.id)')
    
    gcloud ai endpoints undeploy-model $ENDPOINT_ID \
        --region=$REGION \
        --deployed-model-id=$DEPLOYED_MODEL_ID
    
  2. Supprimez le point de terminaison :

    gcloud ai endpoints delete $ENDPOINT_ID \
        --region=$REGION \
        --quiet
    
  3. Supprimez le modèle :

    gcloud ai models delete $MODEL_ID \
        --region=$REGION
    
  4. Supprimez l'image de conteneur de diffusion :

    gcloud artifacts docker images delete \
        $LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE \
        --delete-tags \
        --quiet
    
  5. Supprimez le conteneur de compilateur scala-sbt :

    gcloud container images delete gcr.io/$PROJECT_ID/scala-sbt \
        --force-delete-tags \
        --quiet
    
  6. Supprimez tous les buckets Cloud Storage dont vous n'avez plus besoin :

    gsutil rm -r YOUR_BUCKET_NAME
    

    La suppression d'un bucket entraîne également la suppression de tous les objets qu'il contient. Les buckets et les objets supprimés ne peuvent pas être récupérés après leur suppression.

Étape suivante