Vertex AI:utiliser des routines de prédiction personnalisées avec Sklearn pour prétraiter et publier les données de prédiction

1. Introduction

Dans cet atelier, vous allez apprendre à utiliser des routines de prédiction personnalisées sur Vertex AI pour écrire une logique de prétraitement et de post-traitement personnalisée. Bien que cet exemple utilise scikit-learn, les routines de prédiction personnalisées peuvent fonctionner avec d'autres frameworks de ML Python tels que XGBoost, PyTorch et TensorFlow.

Points abordés

  • Écrire une logique de prédiction personnalisée avec des routines de prédiction personnalisées
  • Tester le modèle et le conteneur de diffusion personnalisé en local
  • Tester le conteneur de diffusion personnalisé sur Vertex AI Predictions

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.

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 Predictions et Workbench.

440e66b5fde4cee7.png

3. Présentation du cas d'utilisation

Dans cet atelier, vous allez créer un modèle de régression aléatoire des forêts pour prédire le prix d'un diamant en fonction d'attributs tels que la taille, la clarté et la taille.

Vous allez écrire une logique de prétraitement personnalisée pour vérifier que les données au moment de la diffusion sont au format attendu par le modèle. Vous allez également écrire une logique de post-traitement personnalisée pour arrondir les prédictions et les convertir en chaînes. Pour écrire cette logique, vous allez utiliser des routines de prédiction personnalisées.

Présentation des routines de prédiction personnalisées

Les conteneurs prédéfinis Vertex AI traitent les requêtes de prédiction en effectuant l'opération de prédiction du framework de machine learning. Avant les routines de prédiction personnalisées, si vous vouliez prétraiter l'entrée avant la prédiction ou post-traiter la prédiction du modèle avant de renvoyer le résultat, vous deviez créer un conteneur personnalisé.

La création d'un conteneur de diffusion personnalisé nécessite d'écrire un serveur HTTP qui encapsule le modèle entraîné, traduit les requêtes HTTP en entrées du modèle et traduit les sorties du modèle en réponses.

Avec les routines de prédiction personnalisées, Vertex AI vous fournit les composants liés à l'inférence pour que vous puissiez vous concentrer sur votre modèle et les transformations de données.

Objectifs de l'atelier

Vous allez configurer un réseau VPC nommé aiml-vpc, qui consiste en un sous-réseau Workbench utilisé pour déployer un notebook géré par l'utilisateur, et accéder à la prédiction en ligne et au point de terminaison du modèle déployés dans la région us-central1, comme illustré dans la figure 1 ci-dessous.

                                                                            Figure1

6ce21c7fdae12b4f.png

4. Activer les API du tutoriel

Étape 1: Activez l'API Compute Engine

Accédez à Compute Engine et sélectionnez "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 Artifact Registry

Accédez à Artifact Registry et cliquez sur "Activer" si ce n'est pas déjà fait. Vous l'utiliserez pour créer un conteneur de diffusion personnalisé.

Étape 3: Activez l'API Vertex AI

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

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

Si ce n'est pas déjà fait, activez l'API Notebooks AP.

5. Créer le VPC aiml-vpc

Ce tutoriel utilise $variables pour faciliter l'implémentation de la configuration gcloud dans Cloud Shell.

Dans Cloud Shell, effectuez les opérations suivantes:

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectid=YOUR-PROJECT-NAME
echo $projectid

Créer le VPC aiml-vpc

Dans Cloud Shell, effectuez les opérations suivantes:

gcloud compute networks create aiml-vpc --project=$projectid --subnet-mode=custom

Créer le sous-réseau de notebooks gérés par l'utilisateur

Dans Cloud Shell, créez le sous-réseau "workbench-subnet".

gcloud compute networks subnets create workbench-subnet --project=$projectid --range=172.16.10.0/28 --network=aiml-vpc --region=us-central1 --enable-private-ip-google-access

Configuration Cloud Router et NAT

Dans ce tutoriel, Cloud NAT est utilisé pour télécharger des packages logiciels, car le notebook géré par l'utilisateur ne possède pas d'adresse IP externe. Cloud NAT fournit des fonctionnalités NAT de sortie, ce qui signifie que les hôtes Internet ne sont pas autorisés à communiquer avec un notebook géré par l'utilisateur, ce qui le rend plus sûr.

Dans Cloud Shell, créez le routeur cloud régional us-central1.

gcloud compute routers create cloud-router-us-central1-aiml-nat --network aiml-vpc --region us-central1

Dans Cloud Shell, créez la passerelle Cloud NAT régionale, us-central1.

gcloud compute routers nats create cloud-nat-us-central1 --router=cloud-router-us-central1-aiml-nat --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --region us-central1

6. Créer le notebook géré par l'utilisateur

Créer un compte de service géré par l'utilisateur (notebook)

Dans la section suivante, vous allez créer un compte de service géré par l'utilisateur qui sera associé au Vertex Workbench (notebook) utilisé dans le tutoriel.

Dans le tutoriel, les règles suivantes seront appliquées au compte de service:

Dans Cloud Shell, créez le compte de service.

gcloud iam service-accounts create user-managed-notebook-sa \
    --display-name="user-managed-notebook-sa"

Dans Cloud Shell, mettez à jour le compte de service avec le rôle "Administrateur Storage".

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/storage.admin"

Dans Cloud Shell, mettez à jour le compte de service avec le rôle Utilisateur Vertex AI.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/aiplatform.user"

Dans Cloud Shell, attribuez le rôle "Administrateur Artifact Registry" au compte de service.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/artifactregistry.admin"

Dans Cloud Shell, listez le compte de service et notez l'adresse e-mail qui sera utilisée pour créer le notebook géré par l'utilisateur.

gcloud iam service-accounts list

Créer le notebook géré par l'utilisateur

Dans la section suivante, vous allez créer un notebook géré par l'utilisateur qui intègre le compte de service créé précédemment, user-managed-notebook-sa.

Dans Cloud Shell, créez l'instance du client privé.

gcloud notebooks instances create workbench-tutorial \
      --vm-image-project=deeplearning-platform-release \
      --vm-image-family=common-cpu-notebooks \
      --machine-type=n1-standard-4 \
      --location=us-central1-a \
      --shielded-secure-boot \
      --subnet-region=us-central1 \
      --subnet=workbench-subnet \
      --no-public-ip    --service-account=user-managed-notebook-sa@$projectid.iam.gserviceaccount.com

7. Rédiger le code d'entraînement

Étape 1: Créez un bucket Cloud Storage

Vous allez stocker le modèle et les artefacts de prétraitement dans un bucket Cloud Storage. Si votre projet contient déjà un bucket que vous souhaitez utiliser, vous pouvez ignorer cette étape.

Ouvrez une nouvelle session de terminal à partir du lanceur.

84a53a5b528f2507.png

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}-cpr-bucket"
gsutil mb -l us-central1 $BUCKET

Étape 2: Entraînez le modèle

Depuis le terminal, créez un répertoire nommé cpr-codelab et utilisez la commande cd pour y accéder.

mkdir cpr-codelab
cd cpr-codelab

Dans l'explorateur de fichiers, accédez au nouveau répertoire cpr-codelab, puis utilisez le lanceur pour créer un notebook Python 3 nommé task.ipynb.

f230930e0b79650c.png

Votre répertoire cpr-codelab devrait maintenant se présenter comme suit:

+ cpr-codelab/
    + task.ipynb

Dans le notebook, collez le code suivant.

Tout d'abord, écrivez un fichier requirements.txt.

%%writefile requirements.txt
fastapi
uvicorn==0.17.6
joblib~=1.1.1
numpy>=1.17.3, <1.24.0
scikit-learn~=1.0.0
pandas
google-cloud-storage>=2.2.1,<3.0.0dev
google-cloud-aiplatform[prediction]>=1.18.2

Un ensemble de dépendances différent de celui de votre environnement de notebook sera préinstallé sur le modèle que vous déployez. Pour cette raison, vous devez lister toutes les dépendances du modèle dans le fichier requirements.txt, puis utiliser pip pour installer exactement les mêmes dépendances dans le notebook. Plus tard, vous testerez le modèle localement avant de le déployer sur Vertex AI pour vérifier que les environnements correspondent.

Pip installe les dépendances dans le notebook.

!pip install -U --user -r requirements.txt

Notez que vous devrez redémarrer le noyau une fois l'installation de pip terminée.

Ensuite, créez les répertoires dans lesquels vous stockerez les artefacts de modèle et de prétraitement.

USER_SRC_DIR = "src_dir"
!mkdir $USER_SRC_DIR
!mkdir model_artifacts

# copy the requirements to the source dir
!cp requirements.txt $USER_SRC_DIR/requirements.txt

Votre répertoire cpr-codelab devrait maintenant se présenter comme suit:

+ cpr-codelab/
    + model_artifacts/
    + scr_dir/
        + requirements.txt
    + task.ipynb
    + requirements.txt

Maintenant que la structure de répertoire est configurée, il est temps d'entraîner un modèle.

Commencez par importer les bibliothèques.

import seaborn as sns
import numpy as np
import pandas as pd

from sklearn import preprocessing
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import make_pipeline
from sklearn.compose import make_column_transformer

import joblib
import logging

# set logging to see the docker container logs
logging.basicConfig(level=logging.INFO)

Définissez ensuite les variables suivantes. Veillez à remplacer PROJECT_ID par l'ID de votre projet et BUCKET_NAME par le bucket que vous avez créé à l'étape précédente.

REGION = "us-central1"
MODEL_ARTIFACT_DIR = "sklearn-model-artifacts"
REPOSITORY = "diamonds"
IMAGE = "sklearn-image"
MODEL_DISPLAY_NAME = "diamonds-cpr"

# Replace with your project
PROJECT_ID = "{PROJECT_ID}"

# Replace with your bucket
BUCKET_NAME = "gs://{BUCKET_NAME}"

Chargez les données de la bibliothèque Seaborn, puis créez deux trames de données, l'une avec les caractéristiques et l'autre avec l'étiquette.

data = sns.load_dataset('diamonds', cache=True, data_home=None)

label = 'price'

y_train = data['price']
x_train = data.drop(columns=['price'])

Examinons les données d'entraînement. Vous pouvez voir que chaque ligne représente un losange.

x_train.head()

Et les étiquettes, qui sont les prix correspondants.

y_train.head()

Définissez maintenant une transformation de colonne sklearn pour encoder à chaud les caractéristiques catégorielles et mettre à l'échelle les caractéristiques numériques.

column_transform = make_column_transformer(
    (preprocessing.OneHotEncoder(sparse=False), [1,2,3]),
    (preprocessing.StandardScaler(), [0,4,5,6,7,8]))

Définir le modèle de forêt aléatoire

regr = RandomForestRegressor(max_depth=10, random_state=0)

Créez ensuite un pipeline sklearn. Cela signifie que les données fournies à ce pipeline seront d'abord encodées/mises à l'échelle, puis transmises au modèle.

my_pipeline = make_pipeline(column_transform, regr)

Adapter le pipeline aux données d'entraînement

my_pipeline.fit(x_train, y_train)

Essayons le modèle pour vérifier qu'il fonctionne comme prévu. Appelez la méthode de prédiction sur le modèle en transmettant un échantillon de test.

my_pipeline.predict([[0.23, 'Ideal', 'E', 'SI2', 61.5, 55.0, 3.95, 3.98, 2.43]])

Nous pouvons maintenant enregistrer le pipeline dans le répertoire "model_artifacts" et le copier dans le bucket Cloud Storage

joblib.dump(my_pipeline, 'model_artifacts/model.joblib')

!gsutil cp model_artifacts/model.joblib {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/

Étape 3: Enregistrez un artefact de prétraitement

Vous allez maintenant créer un artefact de prétraitement. Cet artefact sera chargé dans le conteneur personnalisé au démarrage du serveur de modèles. Votre artefact de prétraitement peut prendre presque toutes les formes (un fichier pickle, par exemple), mais dans ce cas, vous allez écrire un dictionnaire dans un fichier JSON.

clarity_dict={"Flawless": "FL",
              "Internally Flawless": "IF",
              "Very Very Slightly Included": "VVS1",
              "Very Slightly Included": "VS2",
              "Slightly Included": "S12",
              "Included": "I3"}

La caractéristique de clarté de nos données d'entraînement a toujours été abrégée (par exemple, "FL" au lieu de "Flawless"). Lors de l'inférence, nous voulons vérifier que les données de cette caractéristique sont également abrégées. En effet, notre modèle sait comment encoder "FL" à chaud mais pas "Flawless". Vous écrirez cette logique de prétraitement personnalisée ultérieurement. Pour le moment, il vous suffit d'enregistrer cette table de recherche dans un fichier JSON et de l'écrire dans le bucket Cloud Storage.

import json
with open("model_artifacts/preprocessor.json", "w") as f:
    json.dump(clarity_dict, f)

!gsutil cp model_artifacts/preprocessor.json {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/

Votre répertoire local cpr-codelab doit maintenant se présenter comme suit:

+ cpr-codelab/
    + model_artifacts/
        + model.joblib
        + preprocessor.json
    + scr_dir/
        + requirements.txt
    + task.ipynb
    + requirements.txt

8. Créer un conteneur de diffusion personnalisé à l'aide du serveur de modèles CPR

Maintenant que le modèle a été entraîné et que l'artefact de prétraitement a été sauvegardé, il est temps de créer le conteneur de diffusion personnalisé. En règle générale, la création d'un conteneur de diffusion nécessite l'écriture du code du serveur de modèles. Toutefois, avec les routines de prédiction personnalisées, Vertex AI Predictions génère un serveur de modèles et crée une image de conteneur personnalisée pour vous.

Un conteneur de diffusion personnalisé contient les trois éléments de code suivants:

  1. Serveur de modèle (il sera généré automatiquement par le SDK et stocké dans scr_dir/)
  • Serveur HTTP qui héberge le modèle
  • Chargé de la configuration des routes, des ports, etc.
  1. Gestionnaire de requêtes
  • Chargé des aspects du serveur Web liés au traitement d'une requête, tels que la désérialisation du corps de la requête et la sérialisation de la réponse, la définition des en-têtes de réponse, etc.
  • Dans cet exemple, vous allez utiliser le gestionnaire par défaut google.cloud.aiplatform.prediction.handler.PredictionHandler fourni dans le SDK.
  1. Prédicteur
  • Chargé de la logique de ML pour le traitement d'une requête de prédiction.

Chacun de ces composants peut être personnalisé en fonction des exigences de votre cas d'utilisation. Dans cet exemple, vous n'implémenterez que le prédicteur.

Le prédicteur est responsable de la logique de ML pour le traitement d'une requête de prédiction, comme le prétraitement et le post-traitement personnalisés. Pour écrire une logique de prédiction personnalisée, vous devez sous-classer l'interface du prédicteur Vertex AI.

Cette version des routines de prédiction personnalisées est fournie avec des prédicteurs XGBoost et Sklearn réutilisables. Toutefois, si vous devez utiliser un framework différent, vous pouvez créer le vôtre en sous-classant le prédicteur de base.

Vous trouverez ci-dessous un exemple de prédicteur Sklearn. Voici tout le code qu'il vous faudrait écrire pour créer ce serveur de modèles personnalisés.

262df1246b28657e.png

Dans votre notebook, collez le code suivant ci-dessous pour sous-classer SklearnPredictor et écrivez-le dans un fichier Python situé dans le répertoire src_dir/. Notez que, dans cet exemple, nous ne personnalisons que les méthodes de chargement, de prétraitement et de post-traitement, et non la méthode de prédiction.

%%writefile $USER_SRC_DIR/predictor.py

import joblib
import numpy as np
import json

from google.cloud import storage
from google.cloud.aiplatform.prediction.sklearn.predictor import SklearnPredictor


class CprPredictor(SklearnPredictor):

    def __init__(self):
        return

    def load(self, artifacts_uri: str) -> None:
        """Loads the sklearn pipeline and preprocessing artifact."""

        super().load(artifacts_uri)

        # open preprocessing artifact
        with open("preprocessor.json", "rb") as f:
            self._preprocessor = json.load(f)


    def preprocess(self, prediction_input: np.ndarray) -> np.ndarray:
        """Performs preprocessing by checking if clarity feature is in abbreviated form."""

        inputs = super().preprocess(prediction_input)

        for sample in inputs:
            if sample[3] not in self._preprocessor.values():
                sample[3] = self._preprocessor[sample[3]]
        return inputs

    def postprocess(self, prediction_results: np.ndarray) -> dict:
        """Performs postprocessing by rounding predictions and converting to str."""

        return {"predictions": [f"${value}" for value in np.round(prediction_results)]}

Examinons plus en détail chacune de ces méthodes.

  • La méthode de chargement charge l'artefact de prétraitement, qui dans ce cas est un dictionnaire mappant les valeurs de pureté en losange à leurs abréviations.
  • La méthode de prétraitement utilise cet artefact pour s'assurer qu'au moment de la diffusion, la caractéristique de clarté est dans son format abrégé. Si ce n'est pas le cas, il convertit la chaîne complète en son abréviation.
  • La méthode de post-traitement renvoie la valeur prédite sous forme de chaîne avec un signe $ et arrondit la valeur.

Ensuite, utilisez le SDK Vertex AI pour Python pour créer l'image. À l'aide de routines de prédiction personnalisées, le Dockerfile est généré et une image est créée pour vous.

from google.cloud import aiplatform

aiplatform.init(project=PROJECT_ID, location=REGION)

import os

from google.cloud.aiplatform.prediction import LocalModel

from src_dir.predictor import CprPredictor  # Should be path of variable $USER_SRC_DIR

local_model = LocalModel.build_cpr_model(
    USER_SRC_DIR,
    f"{REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}",
    predictor=CprPredictor,
    requirements_path=os.path.join(USER_SRC_DIR, "requirements.txt"),
)

Écrivez un fichier de test avec deux exemples de prédiction. L'une des instances porte le nom de clarté abrégé, mais l'autre doit d'abord être convertie.

import json

sample = {"instances": [
  [0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43],
  [0.29, 'Premium', 'J', 'Internally Flawless', 52.5, 49.0, 4.00, 2.13, 3.11]]}

with open('instances.json', 'w') as fp:
    json.dump(sample, fp)

Testez le conteneur localement en déployant un modèle local.

with local_model.deploy_to_local_endpoint(
    artifact_uri = 'model_artifacts/', # local path to artifacts
) as local_endpoint:
    predict_response = local_endpoint.predict(
        request_file='instances.json',
        headers={"Content-Type": "application/json"},
    )

    health_check_response = local_endpoint.run_health_check()

Vous pouvez afficher les résultats de la prédiction avec :

predict_response.content

9. Déployer le modèle dans Vertex AI

Maintenant que vous avez testé le conteneur localement, vous pouvez transférer l'image vers Artifact Registry et importer le modèle dans Vertex AI Model Registry.

Commencez par configurer Docker pour accéder à Artifact Registry.

!gcloud artifacts repositories create {REPOSITORY} --repository-format=docker \
--location=us-central1 --description="Docker repository"

!gcloud auth configure-docker {REGION}-docker.pkg.dev --quiet

Transférez ensuite l'image.

local_model.push_image()

et importer le modèle.

model = aiplatform.Model.upload(local_model = local_model,
                                display_name=MODEL_DISPLAY_NAME,
                                artifact_uri=f"{BUCKET_NAME}/{MODEL_ARTIFACT_DIR}",)

Une fois le modèle importé, il doit apparaître dans la console:

Déployez ensuite le modèle afin de pouvoir l'utiliser pour les prédictions en ligne. Les routines de prédiction personnalisées fonctionnent également avec la prédiction par lot. Par conséquent, si votre cas d'utilisation ne nécessite pas de prédictions en ligne, vous n'avez pas besoin de déployer le modèle.

Transférez ensuite l'image.

endpoint = model.deploy(machine_type="n1-standard-2")

Enfin, testez le modèle déployé en obtenant une prédiction.

endpoint.predict(instances=[[0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43]])

🎉 Félicitations ! 🎉

Vous savez désormais utiliser Vertex AI pour :

  • Écrire une logique de prétraitement et de post-traitement personnalisée avec des routines de prédiction personnalisées

Cosmopup trouve les ateliers de programmation géniaux !

e6d3675ca7c6911f.jpeg

Et ensuite ?

Complément d'informations et Vidéos

Documents de référence