Vertex AI: Benutzerdefinierte Vorhersageroutinen mit Sklearn verwenden, um Daten für Vorhersagen vor- und nachzuverarbeiten

1. Übersicht

In diesem Lab erfahren Sie, wie Sie benutzerdefinierte Vorhersageroutinen in Vertex AI verwenden, um benutzerdefinierte Vor- und Nachverarbeitungslogik zu schreiben. In diesem Beispiel wird Scikit-learn verwendet. Benutzerdefinierte Vorhersageroutinen können jedoch auch mit anderen Python-ML-Frameworks wie XGBoost, PyTorch und TensorFlow verwendet werden.

Lerninhalte

Die folgenden Themen werden behandelt:

  • Benutzerdefinierte Vorhersagelogik mit benutzerdefinierten Vorhersageroutinen schreiben
  • Benutzerdefinierten Bereitstellungscontainer und das Modell lokal testen
  • Benutzerdefinierten Bereitstellungscontainer in Vertex AI Predictions testen

Die Gesamtkosten für die Ausführung dieses Labs in Google Cloud betragen etwa 1$.

2. Einführung in Vertex AI

In diesem Lab wird das neueste KI-Produkt von Google Cloud verwendet. Vertex AI vereint die ML-Angebote von Google Cloud in einer nahtlosen Entwicklungsumgebung. Bisher musste auf mit AutoML trainierte und benutzerdefinierte Modelle über verschiedene Dienste zugegriffen werden. Das neue Angebot kombiniert diese und weitere, neue Produkte zu einer einzigen API. Sie können auch vorhandene Projekte zu Vertex AI migrieren.

Vertex AI umfasst viele verschiedene Produkte zur Unterstützung von End-to-End-ML-Workflows. In diesem Lab geht es um Vorhersagen und Workbench.

Vertex-Produktübersicht

3. Übersicht über Anwendungsfälle

Anwendungsfall

In diesem Lab erstellen Sie ein Random Forest-Regressionsmodell, um den Preis eines Diamanten anhand von Attributen wie Schliff, Reinheit und Größe vorherzusagen.

Sie schreiben benutzerdefinierte Vorverarbeitungslogik, um zu prüfen, ob die Daten zur Bereitstellungszeit das vom Modell erwartete Format haben. Außerdem schreiben Sie eine benutzerdefinierte Nachbearbeitungslogik, um die Vorhersagen zu runden und in Strings zu konvertieren. Für diese Logik verwenden Sie benutzerdefinierte Vorhersageroutinen.

Einführung in benutzerdefinierte Vorhersageroutinen

Die vordefinierten Container von Vertex AI verarbeiten Vorhersageanfragen, indem sie den Vorhersagevorgang des Frameworks für maschinelles Lernen ausführen. Vor benutzerdefinierten Vorhersageroutinen mussten Sie einen benutzerdefinierten Container erstellen, wenn Sie die Eingabe vor der Vorhersage vorverarbeiten oder die Vorhersage des Modells vor der Rückgabe des Ergebnisses nachbearbeiten wollten.

Zum Erstellen eines benutzerdefinierten Bereitstellungscontainers müssen Sie einen HTTP-Server schreiben, der das trainierte Modell umschließt, HTTP-Anfragen in Modelleingaben und Modellausgaben in Antworten übersetzt.

Mit benutzerdefinierten Vorhersageroutinen stellt Vertex AI die Komponenten für die Bereitstellung für Sie bereit, sodass Sie sich auf Ihr Modell und Ihre Datentransformationen konzentrieren können.

4. Umgebung einrichten

Für dieses Codelab benötigen Sie ein Google Cloud Platform-Projekt mit aktivierter Abrechnung. Folgen Sie dieser Anleitung, um ein Projekt zu erstellen.

Schritt 1: Compute Engine API aktivieren

Rufen Sie Compute Engine auf und wählen Sie Aktivieren aus, falls die API noch nicht aktiviert ist. Sie benötigen diese, um Ihre Notebook-Instanz zu erstellen.

Schritt 2: Artifact Registry API aktivieren

Rufen Sie Artifact Registry auf und wählen Sie Aktivieren aus, falls die API noch nicht aktiviert ist. Damit erstellen Sie einen benutzerdefinierten Serving-Container.

Schritt 3: Vertex AI API aktivieren

Rufen Sie den Vertex AI-Bereich Ihrer Cloud Console auf und klicken Sie auf Vertex AI API aktivieren.

Vertex AI-Dashboard

Schritt 4: Vertex AI Workbench-Instanz erstellen

Klicken Sie in der Cloud Console im Bereich „Vertex AI“ auf „Workbench“:

Vertex AI-Menü

Aktivieren Sie die Notebooks API, falls sie noch nicht aktiviert ist.

Notebook_api

Klicken Sie nach der Aktivierung auf INSTANZEN und wählen Sie dann NEU ERSTELLEN aus.

Übernehmen Sie die Standardoptionen und klicken Sie auf Erstellen.

Wenn die Instanz bereit ist, klicken Sie auf JUPYTERLAB ÖFFNEN, um die Instanz zu öffnen.

5. Trainingscode schreiben

Schritt 1: Cloud Storage-Bucket erstellen

Sie speichern das Modell und die Vorverarbeitungsartefakte in einem Cloud Storage-Bucket. Wenn Sie bereits einen Bucket in Ihrem Projekt haben, den Sie verwenden möchten, können Sie diesen Schritt überspringen.

Öffnen Sie über den Launcher eine neue Terminalsitzung.

Open_terminal

Führen Sie im Terminal den folgenden Befehl aus, um eine Umgebungsvariable für Ihr Projekt zu definieren. Ersetzen Sie dabei your-cloud-project durch die ID Ihres Projekts:

PROJECT_ID='your-cloud-project'

Führen Sie als Nächstes den folgenden Befehl im Terminal aus, um einen neuen Bucket in Ihrem Projekt zu erstellen.

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

Schritt 2: Modell trainieren

Erstellen Sie im Terminal ein neues Verzeichnis mit dem Namen cpr-codelab und wechseln Sie in dieses Verzeichnis.

mkdir cpr-codelab
cd cpr-codelab

Rufen Sie im Dateibrowser das neue Verzeichnis cpr-codelab auf und erstellen Sie dann mit dem Launcher ein neues Python 3-Notebook namens task.ipynb.

file_browser

Ihr cpr-codelab-Verzeichnis sollte jetzt so aussehen:

+ cpr-codelab/
    + task.ipynb

Fügen Sie im Notebook den folgenden Code ein.

Schreiben Sie zuerst eine requirements.txt-Datei.

%%writefile requirements.txt
fastapi
uvicorn==0.17.6
joblib~=1.0
numpy~=1.20
scikit-learn>=1.2.2
pandas
google-cloud-storage>=1.26.0,<2.0.0dev
google-cloud-aiplatform[prediction]>=1.16.0

Für das bereitgestellte Modell ist eine andere Gruppe von Abhängigkeiten vorinstalliert als für Ihre Notebook-Umgebung. Daher sollten Sie alle Abhängigkeiten für das Modell in requirements.txt auflisten und dann pip verwenden, um genau dieselben Abhängigkeiten im Notebook zu installieren. Später testen Sie das Modell lokal, bevor Sie es in Vertex AI bereitstellen, um zu prüfen, ob die Umgebungen übereinstimmen.

Installieren Sie die Abhängigkeiten mit pip im Notebook.

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

Nachdem die Pip-Installation abgeschlossen ist, müssen Sie den Kernel neu starten.

restart_kernel

Erstellen Sie als Nächstes die Verzeichnisse, in denen Sie das Modell und die Preprocessing-Artefakte speichern.

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

Ihr cpr-codelab-Verzeichnis sollte jetzt so aussehen:

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

Nachdem die Verzeichnisstruktur eingerichtet ist, können Sie ein Modell trainieren.

Importieren Sie zuerst die Bibliotheken.

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)

Definieren Sie dann die folgenden Variablen. Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID und BUCKET_NAME durch den Bucket, den Sie im vorherigen Schritt erstellt haben.

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}"

Laden Sie die Daten aus der seaborn-Bibliothek und erstellen Sie dann zwei DataFrames, einen mit den Features und einen mit dem Label.

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

label = 'price'

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

Sehen wir uns die Trainingsdaten an. Jede Zeile stellt eine Raute dar.

x_train.head()

Und die Labels, also die entsprechenden Preise.

y_train.head()

Definieren Sie nun eine sklearn-Spaltentransformation, um die kategorialen Features als One-Hot-Codierung zu codieren und die numerischen Features zu skalieren.

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

Random Forest-Modell definieren

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

Erstellen Sie als Nächstes eine sklearn-Pipeline. Das bedeutet, dass Daten, die in diese Pipeline eingegeben werden, zuerst codiert/skaliert und dann an das Modell übergeben werden.

my_pipeline = make_pipeline(column_transform, regr)

Pipeline an die Trainingsdaten anpassen

my_pipeline.fit(x_train, y_train)

Lassen Sie uns das Modell testen, um sicherzugehen, dass es wie erwartet funktioniert. Rufen Sie die Methode predict für das Modell auf und übergeben Sie dabei ein Testbeispiel.

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

Jetzt können wir die Pipeline im Verzeichnis model_artifacts speichern und in den Cloud Storage-Bucket kopieren.

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

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

Schritt 3: Vorverarbeitungsartefakt speichern

Als Nächstes erstellen Sie ein Vorverarbeitungsartefakt. Dieses Artefakt wird beim Start des Modellservers in den benutzerdefinierten Container geladen. Ihr Vorverarbeitungsartefakt kann fast jedes Format haben (z. B. eine Pickle-Datei). In diesem Fall schreiben Sie jedoch ein Dictionary in eine JSON-Datei.

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

Das Feature clarity lag in unseren Trainingsdaten immer in der abgekürzten Form vor (d. h. „FL“ anstelle von „Flawless“). Beim Ausliefern möchten wir prüfen, ob die Daten für diese Funktion auch abgekürzt sind. Das liegt daran, dass unser Modell weiß, wie man einen „FL“, aber nicht „Flawless“ codieren muss. Diese benutzerdefinierte Vorverarbeitungslogik wird später geschrieben. Speichern Sie diese Suchtabelle vorerst in einer JSON-Datei und schreiben Sie sie dann in den Cloud Storage-Bucket.

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}/

Ihr lokales cpr-codelab-Verzeichnis sollte nun so aussehen:

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

6. Benutzerdefinierten Bereitstellungscontainer mit dem CPR-Modellserver erstellen

Nachdem das Modell trainiert und das Vorverarbeitungsartefakt gespeichert wurde, ist es an der Zeit, den benutzerdefinierten Bereitstellungscontainer zu erstellen. Normalerweise ist zum Erstellen eines Bereitstellungscontainers das Schreiben von Modellservercode erforderlich. Bei benutzerdefinierten Vorhersageroutinen generiert Vertex AI Predictions jedoch einen Modellserver und erstellt ein benutzerdefiniertes Container-Image für Sie.

Ein benutzerdefinierter Bereitstellungscontainer enthält die folgenden drei Codeabschnitte:

  1. Modellserver (wird automatisch vom SDK generiert und in scr_dir/ gespeichert)
    • HTTP-Server, auf dem das Modell gehostet wird
    • Verantwortlich für die Einrichtung von Routen/Ports usw.
  2. Request Handler
    • Verantwortlich für Webserveraspekte der Verarbeitung einer Anfrage, z. B. Deserialisieren des Anfragetexts, Serialisieren der Antwort und Festlegen von Antwortheadern.
    • In diesem Beispiel verwenden Sie den Standard-Handler google.cloud.aiplatform.prediction.handler.PredictionHandler, der im SDK enthalten ist.
  3. Vorhersagevariable
    • Verantwortlich für die ML-Logik zur Verarbeitung einer Vorhersageanfrage.

Jede dieser Komponenten kann an die Anforderungen Ihres Anwendungsfalls angepasst werden. In diesem Beispiel implementieren Sie nur den Vorhersagealgorithmus.

Der Predictor ist für die ML-Logik zur Verarbeitung einer Vorhersageanfrage verantwortlich, z. B. für die benutzerdefinierte Vor- und Nachbearbeitung. Zum Schreiben einer benutzerdefinierten Vorhersagelogik erstellen Sie eine Unterklasse der Vertex AI Predictor-Schnittstelle.

Diese Version von benutzerdefinierten Vorhersageroutinen enthält wiederverwendbare XGBoost- und Sklearn-Vorhersagemodelle. Wenn Sie jedoch ein anderes Framework verwenden müssen, können Sie Ihr eigenes erstellen, indem Sie das Basisvorhersagemodell unterklassen.

Unten sehen Sie ein Beispiel für den Sklearn-Vorhersagealgorithmus. Das ist der gesamte Code, den Sie zum Erstellen dieses benutzerdefinierten Modellservers schreiben müssen.

sklearn_predictor

Fügen Sie den folgenden Code in Ihr Notebook ein, um eine abgeleitete Klasse von SklearnPredictor zu erstellen und in eine Python-Datei in src_dir/ zu schreiben. Beachten Sie, dass wir in diesem Beispiel nur die Methoden load, preprocess und postprocess anpassen, nicht die Methode predict.

%%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)]}

Sehen wir uns die einzelnen Methoden genauer an.

  • Mit der Methode load wird das Vorverarbeitungsartefakt geladen, das in diesem Fall ein Dictionary ist, in dem die Werte für die Reinheit von Diamanten ihren Abkürzungen zugeordnet werden.
  • Bei der preprocess-Methode wird dieses Artefakt verwendet, um sicherzustellen, dass das Clarity-Feature bei der Bereitstellung im abgekürzten Format vorliegt. Andernfalls wird der gesamte String in die Abkürzung konvertiert.
  • Die Methode postprocess gibt den vorhergesagten Wert als String mit einem $-Zeichen zurück und rundet den Wert.

Verwenden Sie als Nächstes das Vertex AI Python SDK, um das Image zu erstellen. Wenn Sie benutzerdefinierte Vorhersageroutinen verwenden, wird das Dockerfile generiert und das Image für Sie erstellt.

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"),
)

Schreiben Sie eine Testdatei mit zwei Beispielen für die Vorhersage. Eine der Instanzen hat den abgekürzten Klarnamen, aber die andere muss zuerst konvertiert werden.

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)

Testen Sie den Container lokal, indem Sie ein lokales Modell bereitstellen.

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()

Sie können die Vorhersageergebnisse mit folgenden Tools aufrufen:

predict_response.content

7. Modell in Vertex AI bereitstellen

Nachdem Sie den Container lokal getestet haben, ist es an der Zeit, das Image in Artifact Registry zu pushen und das Modell in Vertex AI Model Registry hochzuladen.

Konfigurieren Sie zuerst Docker für den Zugriff auf 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

Übertragen Sie das Image per Push.

local_model.push_image()

Laden Sie das Modell hoch.

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

Nachdem das Modell hochgeladen wurde, sollte es in der Konsole angezeigt werden:

model_registry

Stellen Sie das Modell als Nächstes bereit, damit Sie es für Onlinevorhersagen verwenden können. Benutzerdefinierte Vorhersageroutinen funktionieren auch mit Batchvorhersagen. Wenn Ihr Anwendungsfall also keine Onlinevorhersagen erfordert, müssen Sie das Modell nicht bereitstellen.

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

Testen Sie das bereitgestellte Modell abschließend, indem Sie eine Vorhersage abrufen.

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

🎉 Das wars! 🎉

Sie haben gelernt, wie Sie Vertex AI für folgende Aufgaben verwenden:

  • Benutzerdefinierte Vorverarbeitungs- und Nachbearbeitungslogik mit benutzerdefinierten Vorhersageroutinen schreiben

Weitere Informationen zu den verschiedenen Bereichen von Vertex AI finden Sie in der Dokumentation.

8. Bereinigen

Wenn Sie das in diesem Lab erstellte Notebook weiterhin verwenden möchten, sollten Sie es deaktivieren, wenn Sie es nicht nutzen. Wählen Sie in der Workbench-Benutzeroberfläche in der Google Cloud Console das Notebook und dann Beenden aus.

Wenn Sie das Notebook vollständig löschen möchten, klicken Sie oben rechts auf die Schaltfläche Löschen.

Stop_nb

Wenn Sie den bereitgestellten Endpunkt löschen möchten, rufen Sie den Bereich „Endpunkte“ der Konsole auf, klicken Sie auf den erstellten Endpunkt und wählen Sie dann Bereitstellung des Modells am Endpunkt aufheben aus:

delete_endpoint

Wenn Sie das Container-Image löschen möchten, rufen Sie Artifact Registry auf, wählen Sie das von Ihnen erstellte Repository aus und klicken Sie auf Löschen.

delete_image

Wenn Sie den Storage-Bucket löschen möchten, rufen Sie in der Cloud Console über das Navigationsmenü „Storage“ auf, wählen Sie den Bucket aus und klicken Sie auf Löschen:

Speicher löschen