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 conteneur et le modèle d'inférence personnalisés 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.
3. Présentation du cas d'utilisation
Dans cet atelier, vous allez créer un modèle de régression de forêt aléatoire pour prédire le prix d'un diamant en fonction d'attributs tels que la taille, la pureté 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 écrirez également une logique de post-traitement personnalisée pour arrondir les prédictions et les convertir en chaînes. Pour écrire cette logique, vous utiliserez des routines de prédiction personnalisées.
Présentation des routines de prédiction personnalisées
Les conteneurs prédéfinis Vertex AI gèrent 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 souhaitiez prétraiter l'entrée avant d'effectuer 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é.
Pour créer un conteneur de diffusion personnalisé, vous devez écrire un serveur HTTP qui encapsule le modèle entraîné, traduit les requêtes HTTP en entrées de modèle et traduit les sorties de modèle en réponses.
Avec les routines de prédiction personnalisées, Vertex AI vous fournit les composants liés au service, ce qui vous permet de vous concentrer sur votre modèle et vos transformations de données.
Objectifs de l'atelier
Vous allez configurer un réseau VPC appelé "aiml-vpc", qui se compose d'un sous-réseau Workbench utilisé pour déployer un notebook géré par l'utilisateur et accéder au point de terminaison de prédiction et de modèle en ligne déployé dans us-central1, comme illustré dans la figure 1 ci-dessous.
Figure1

4. Activer les API du tutoriel
É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 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 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
Activez l'API Notebooks si ce n'est pas déjà fait.
5. Créer aiml-vpc
Ce tutoriel utilise des $variables pour faciliter l'implémentation de la configuration gcloud dans Cloud Shell.
Dans Cloud Shell, procédez comme suit :
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, procédez comme suit :
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 de Cloud Router et de NAT
Cloud NAT est utilisé dans le tutoriel 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 à initier une communication avec un notebook géré par l'utilisateur, ce qui le rend plus sécurisé.
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é à 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, mettez à jour le compte de service avec le rôle Administrateur Artifact Registry.
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 lors de la création du notebook géré par l'utilisateur.
gcloud iam service-accounts list
Créer le notebook géré par l'utilisateur
Dans la section suivante, créez un notebook géré par l'utilisateur qui intègre le compte de service user-managed-notebook-sa créé précédemment.
Dans Cloud Shell, créez l'instance de 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 stockerez le modèle et les artefacts de prétraitement dans un bucket Cloud Storage. Si vous disposez déjà d'un bucket dans votre projet que vous souhaitez utiliser, vous pouvez ignorer cette étape.
Depuis le lanceur, ouvrez une nouvelle session de terminal.

Depuis votre terminal, exécutez la commande suivante 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'
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îner le modèle
Dans 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.

Votre répertoire cpr-codelab devrait maintenant se présenter comme suit :
+ cpr-codelab/
+ task.ipynb
Dans le notebook, collez le code suivant.
Commencez par écrire 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
L'ensemble des dépendances préinstallées du modèle que vous déployez sera différent de celui de votre environnement de notebook. Pour cette raison, vous devez lister toutes les dépendances du modèle dans requirements.txt, puis utiliser pip pour installer exactement les mêmes dépendances dans le notebook. Vous testerez ensuite le modèle en local 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 pip terminée.
Ensuite, créez les répertoires dans lesquels vous stockerez le modèle et les artefacts 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épertoires 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 depuis la bibliothèque Seaborn, puis créez deux cadres de données, l'un avec les caractéristiques et l'autre avec le libellé.
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 effectuer un encodage one-hot des caractéristiques catégorielles et ajuster 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 d'arbres décisionnels
regr = RandomForestRegressor(max_depth=10, random_state=0)
Ensuite, créez 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)
Ajuster le pipeline aux données d'entraînement
my_pipeline.fit(x_train, y_train)
Testons le modèle pour nous assurer 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 se présenter sous n'importe quel format, par exemple un fichier pickle, 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 pureté de nos données d'entraînement était toujours au format abrégé (par exemple, "FL" au lieu de "Flawless"). Au moment de la diffusion, nous voulons vérifier que les données de cette caractéristique sont également abrégées. En effet, notre modèle sait comment effectuer un encodage one-hot de "FL", mais pas de "Flawless". Vous écrirez cette logique de prétraitement personnalisée plus tard. Pour le moment, il vous suffit d'enregistrer cette table de conversion dans un fichier JSON, puis 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 devrait 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é enregistré, il est temps de créer le conteneur de diffusion personnalisé. En général, la création d'un conteneur de diffusion nécessite d'écrire du code de serveur de modèle. Toutefois, avec les routines de prédiction personnalisées, Vertex AI Predictions génère un serveur de modèle et crée une image de conteneur personnalisée pour vous.
Un conteneur de diffusion personnalisé contient les trois éléments de code suivants :
- Serveur de modèle (généré automatiquement par le SDK et stocké dans scr_dir/)
- Serveur HTTP qui héberge le modèle
- Responsable de la configuration des routes/ports/etc.
- Responsable 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, 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.
- Responsable 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 demande de prédiction, comme le prétraitement et le post-traitement personnalisés. Pour écrire une logique de prédiction personnalisée, vous devez créer une sous-classe de l'interface Vertex AI Predictor.
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 autre framework, 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. Il s'agit de tout le code que vous devez écrire pour créer ce serveur de modèle personnalisé.

Dans votre notebook, collez le code suivant pour sous-classer le SklearnPredictor et écrivez-le dans un fichier Python dans 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 "load" charge l'artefact de prétraitement, qui dans ce cas est un dictionnaire mappant les valeurs de pureté des diamants à leurs abréviations.
- La méthode de prétraitement utilise cet artefact pour s'assurer que la fonctionnalité de clarté est au format abrégé au moment de la diffusion. Sinon, il convertit la chaîne complète en son abréviation.
- La méthode postprocess renvoie la valeur prédite sous forme de chaîne avec un signe dollar et arrondit la valeur.
Ensuite, utilisez le SDK Vertex AI pour Python pour créer l'image. Si vous utilisez des routines de prédiction personnalisées, le fichier Dockerfile sera généré et une image sera créée automatiquement.
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 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, il est temps de transférer l'image vers Artifact Registry et d'importer le modèle dans Vertex AI Model Registry.
Configurez d'abord 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()
Importez 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 :
Ensuite, déployez le modèle pour 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 pense que les ateliers de programmation sont géniaux !

Et ensuite ?
Lectures et vidéos complémentaires
- Qu'est-ce que Vertex AI ?
- Premiers pas avec Vertex AI
- Quelle solution d'IA/ML sur Vertex AI me convient le mieux ?
- Créer un système de questions-réponses avec Vertex AI
