Spark ML-Modelle mit Vertex AI bereitstellen

Last reviewed 2023-07-11 UTC

Data Scientists und ML-Entwickler benötigen oft eine Bereitstellungsarchitektur, die schnell genug ist, um den Anforderungen des Generierens von Onlinevorhersagen (oder Echtzeitvorhersagen) aus ihren Modellen zu genügen. Vertex AI kann diese Anforderung erfüllen.

Mit Vertex AI können Sie Modelle aus einer Vielzahl von ML-Frameworks bereitstellen. Für Frameworks wie TensorFlow, PyTorch, XGBoost und scikit-learn stellt Vertex AI vordefinierte Container bereit, in denen diese ML-Modelle ausgeführt werden können. Wenn Sie noch keines dieser ML-Frameworks verwenden, müssen Sie einen eigenen benutzerdefinierten Container erstellen, der von Vertex AI verwendet werden soll.

Dieses Dokument richtet sich an Nutzer, die einen benutzerdefinierten Container erstellen müssen, um ihre Spark ML-Modelle bereitzustellen. Das Dokument enthält sowohl eine Beschreibung der Bereitstellungsarchitektur, die für benutzerdefinierte Container benötigt wird, als auch eine Referenzimplementierung, die diese Architektur für ein Spark MLib-Modell veranschaulicht.

Damit Sie den Referenzimplementierungsteil dieses Dokuments optimal nutzen können, sollten Sie mit dem Export von Spark MLlib-Modellen in das MLeap-Format vertraut sein. Informieren Sie sich außerdem darüber, wie Vertex AI für das Bereitstellen von Vorhersagen verwendet wird und bringen Sie Erfahrung mit der Verwendung von Container-Images mit.

Architektur

Während für einige ML-Frameworks vordefinierte Container verfügbar sind, müssen Nutzer anderer ML-Frameworks wie Spark benutzerdefinierte Container erstellen, in denen Vertex AI Vorhersagen ausführen kann. Das folgende Diagramm zeigt die Bereitstellungsarchitektur, die Sie zum Bereitstellen von Spark MLib-Modellen und anderen Modellen benötigen, für die ein benutzerdefinierter Container erforderlich ist:

Grafik: Die Bereitstellungsarchitektur für das Modell, das in der Dokument verwendet wird.

Diese Architektur umfasst die folgenden Komponenten:

  • Cloud Storage: bietet Speicher für die Modellartefakte, die zum Ausführen des Modells erforderlich sind. Für das in der zugehörigen Referenzimplementierung verwendete Spark ML-Modell bestehen die Modellartefakte aus einem MLeap-Bundle und einem Modellschema.
  • Cloud Build: verwendet das Builder-Image, um ein benutzerdefiniertes Container-Image (Bereitstellungscontainer-Image) zu erstellen. Der Build-Prozess kompiliert und verpackt den Modellbereitstellungscode, erstellt das Bereitstellungscontainer-Image und überträgt das Bereitstellungscontainer-Image dann per Push an Artifact Registry.
  • Artifact Registry: enthält die folgenden Objekte:
    • Das Builder-Container-Image scala-sbt, mit dem Cloud Build das Bereitstellungscontainer-Image erstellt.
    • Das von Cloud Build erstellte Bereitstellungscontainer-Image.
  • Vertex AI: Enthält das ML-Modell, das aus Cloud Storage hochgeladen wurde. Das hochgeladene Modell wird mit dem Speicherort der Modellartefakte in Cloud Storage und dem Speicherort des Bereitstellungscontainer-Images in Artifact Registry konfiguriert. Vertex AI enthält auch einen Endpunkt, auf dem das Modell bereitgestellt wurde. Wenn das Modell auf dem Endpunkt bereitgestellt wurde, verknüpft Vertex AI mit dem Modell physische Ressourcen, damit das Modell Onlinevorhersagen bereitstellen kann.

Im Rahmen dieser Implementierung dieser Bereitstellungs-Architektur müssen Sie Ihr ML-Modell für die Verwendung durch andere Anwendungen exportieren und ein eigenes Bereitstellungscontainer-Image definieren. Die in diesem Dokument enthaltene Referenzimplementierung enthält den Code, mit dem das Bereitstellungscontainer-Image definiert und erstellt wird. Dieser Code enthält auch die Modellartefakte für ein zuvor exportiertes Spark ML-Modell. Mit einigen Konfigurationsänderungen können Sie diese Referenzimplementierung verwenden, um Ihre eigenen Spark ML-Modelle bereitzustellen.

Sie können diese Bereitstellungsarchitektur jedoch für sich genommen implementieren und nicht die Referenzimplementierung verwenden. Wenn Sie eine eigene Architektur implementieren möchten, müssen Sie Folgendes tun:

  • Exportieren Sie Ihr Modell, damit es von anderen Anwendungen verwendet werden kann. Dieser Prozess hängt von den verwendeten ML-Frameworks und -Tools ab. Sie können beispielsweise Spark MLlib-Modelle exportieren, indem Sie ein MLeap-Bundle erstellen, wie in der Referenzimplementierung beschrieben. Weitere Beispiele zum Exportieren von Modellen finden Sie unter Modellartefakte für Vorhersagen exportieren.
  • Entwerfen Sie Ihr Bereitstellungscontainer-Image so, dass es die benutzerdefinierten Containeranforderungen erfüllt, die dieses Image mit Vertex AI kompatibel machen. Der Code kann in der Programmiersprache Ihrer Wahl vorliegen.
  • Verpacken Sie den Code in einem Paketdateiformat, das mit der verwendeten Programmiersprache kompatibel ist. Sie können beispielsweise eine JAR-Datei für Java-Code oder ein Python-Rad für Python-Code verwenden.
  • Erstellen Sie ein benutzerdefiniertes Container-Image, das Ihren Code im benutzerdefinierten Modus bereitstellen kann.

Referenzimplementierung

Die folgende Referenzimplementierung stellt ein Spark-MLib-Modell bereit, das die Art der Schwertlilie anhand der Länge und Breite der Kelchblätter und der Blütenblätter der jeweiligen Pflanze vorhersagt.

Das in dieser Implementierung verwendete Modell finden Sie im Verzeichnis example_model des Repositorys vertex-ai-spark-ml-serving.git. Das Verzeichnis enthält die Modellartefakte, die vom Bereitstellungscontainer zum Ausführen von Vorhersagen verwendet werden. Außerdem enthält es die folgenden Dateien:

  • Die Datei example_model/model.zip ist ein logistisches Regressionsmodell, das mit Spark MLlib erstellt, mit dem Iris-Dataset trainiert und in ein MLeap-Bundle konvertiert wurde. Das Modell sagt die Art der Schwertlilie (Iris) anhand der Länge und Breite der Kelchblätter (Sepalen) und der Kronblätter (Petalen) vorher.
  • Die Datei example_model/schema.json ist eine JSON-Datei, die das Modellschema beschreibt. Das Modellschema beschreibt die erwarteten Eingabefelder für Vorhersageinstanzen und Ausgabefelder für Vorhersageergebnisse, die für das MLeap-Schema erforderlich sind.

Eigenes Mlib-Modell verwenden

Wenn Sie mit dieser Referenzimplementierung ein eigenes Modell verwenden möchten, muss Ihr Spark MLlib-Modell zuerst in ein MLeap-Bundle exportiert werden. Zum Bereitstellen des Spark MLib-Modells müssen Sie dann die entsprechenden Modellartefakte bereitstellen: das MLeap-Bundle und das Modellschema.

MLeap-Bundle

Der Bereitstellungscontainer ermittelt den Speicherort des MLeap-Bundles mithilfe der Umgebungsvariable AIP_STORAGE_URI, die beim Start von Vertex AI an den Container übergeben wird. Der Wert der Variable AIP_STORAGE_URI wird angegeben, wenn Sie das Modell in Vertex AI hochladen.

Modellschema

Das Modellschema beschreibt die Eingabefeatures und die Vorhersageausgabe eines Modells. Das Modellschema wird mithilfe von JSON-Daten dargestellt. Im Folgenden finden Sie das Schema das in dieser Referenzimplementierung verwendet wird, um die Art der Schwertlilie anhand der Länge und Breite der Kelchblätter und Blütenblätter der jeweiligen Blume vorherzusagen:

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

Im Beispielschema enthält das Array input die Eingabefelder (Spalten) für das Modell, während das Array output die Ausgabefelder (Spalten) enthält, die vom Modell zurückgegeben werden sollen. In beiden Arrays enthält jedes Objekt des Arrays die folgenden Attribute:

  • name: Der Name des Felds (Spalte).
  • type: Der Typ des Felds (Spalte). Gültige Typen sind BOOLEAN, BYTE, DOUBLE, FLOAT, INTEGER, LONG, SHORT und STRING.
  • (Optional) struct: Die Feldstruktur, z. B. ein Skalar oder ein Array. Gültige Strukturen sind BASIC (Skalartyp), ARRAY (Spark Array) und VECTOR (Spark DenseVector). BASIC wird verwendet, wenn das Feld struct nicht vorhanden ist.

Sie können eine der folgenden Methoden verwenden, um das Modellschema an den Bereitstellungscontainer zu übergeben:

  • Geben Sie die JSON-Daten an, die das Schema in der Umgebungsvariable MLEAP_SCHEMA definieren. Die Umgebungsvariable MLEAP_SCHEMA sollte die JSON-Daten selbst enthalten und keinen Pfad zu einer Datei, die das JSON-Schema enthält.
  • Speichern Sie die JSON-Daten in einer Datei mit dem Namen schema.json und stellen Sie diese Datei dem Container unter ${AIP_STORAGE_URI}/schema.json zur Verfügung. Dies ist die Methode, die für das in dieser Dokumentation bereitgestellte MLib-Beispielmodell verwendet wird.

Wenn Sie beide Methoden verwenden, um das Modellschema an den Bereitstellungscontainer zu übergeben, haben die in der Umgebungsvariable MLEAP_SCHEMA gespeicherten JSON-Daten Vorrang.

Kosten

In dieser Referenzimplementierung werden die folgenden kostenpflichtigen Komponenten von Google Cloud verwendet:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen.

Nach Abschluss dieser Implementierung können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweise

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. Enable the Vertex AI, Cloud Build, Cloud Storage, and Artifact Registry APIs.

    Enable the APIs

  4. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  5. Suchen Sie Ihre Projekt-ID und legen Sie sie in Cloud Shell fest.
    export PROJECT_ID=YOUR_PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    Ersetzen Sie YOUR_PROJECT_ID durch Ihre Projekt-ID.

Scala-SBT-Builder-Image erstellen

Sie verwenden Cloud Build mit dem scala-sbt-Community-Builder, um das Bereitstellungscontainer-Image zu erstellen. Dieser Build-Prozess hängt davon ab, ob sich das sbt-scala-Builder-Image in der Container Registry Ihres Projekts befindet.

  1. Klonen Sie in Cloud Shell das Repository cloud-builders-community:

    git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
    
  2. Wechseln Sie zum Projektverzeichnis:

    cd cloud-builders-community/scala-sbt
    
  3. Erstellen Sie das Builder-Image scala-sbt und übertragen Sie es per Push in Container Registry:

    gcloud builds submit .
    

Container-Image bereitstellen

Vertex AI verwendet den Bereitstellungscontainer, um Vorhersageanfragen für das Beispielmodell auszuführen. Ein erster Schritt zum Erstellen des Container-Images ist, ein Docker-Repository in Artifact Registry zu erstellen, in dem das Image gespeichert werden soll. Anschließend müssen Sie Vertex AI die Berechtigung erteilen, das Image des Bereitstellungscontainers aus dem Repository abzurufen. Nachdem Sie das Repository erstellt und Berechtigungen erteilt haben, können Sie das Bereitstellungscontainer-Image erstellen und es per Push in die Artifact Registry senden.

  1. In Cloud Shell erstellen Sie ein Docker-Repository in Artifact Registry:

    REPOSITORY="vertex-ai-prediction"
    LOCATION="us-central1"
    
    gcloud artifacts repositories create $REPOSITORY \
        --repository-format=docker \
        --location=$LOCATION
    
  2. Weisen Sie dem Vertex AI Dienst-Agent die Rolle Artifact Registry-Leser zu:

    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. Klonen Sie das Repository spark-ml-serving:

    git clone https://github.com/GoogleCloudPlatform/vertex-ai-spark-ml-serving.git
    
  4. Wechseln Sie zum Projektverzeichnis:

    cd vertex-ai-spark-ml-serving
    
  5. Erstellen Sie das Bereitstellungscontainer-Image in Ihrem Projekt:

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

    Die Datei cloudbuild.yaml gibt zwei Builder an: den scala-sbt-Builder und den docker-Image-Builder. Cloud Build verwendet den Builder scala-sbt, um den Code zur Modellbereitstellung aus Cloud Storage zu kompilieren, und verpackt dann den kompilierten Code in eine ausführbare JAR-Datei. Cloud Build verwendet den Builder docker, um das Bereitstellungscontainer-Image zu erstellen, das die JAR-Datei enthält. Nachdem das Bereitstellungscontainer-Image erstellt wurde, wird das Image per Push an Artifact Registry übertragen.

Modell in Vertex AI importieren

Der Bereitstellungscontainer liest Modellartefakte aus Cloud Storage. Sie müssen einen Speicherort für diese Artefakte erstellen, bevor Sie das Modell in Vertex AI importieren. Wenn Sie dann das Modell importieren, benötigen Sie sowohl den Speicherort des Modellartefakts als auch das Bereitstellungscontainer-Image in Artifact Registry.

  1. Erstellen Sie in Cloud Shell einen Bucket für die Modellartefakte:

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

    Ersetzen Sie YOUR_BUCKET_NAME durch den Namen Ihres Buckets:

  2. Kopieren Sie die Modellartefakte in den Bucket:

    gsutil cp example_model/* gs://$BUCKET/example_model/
    
  3. Importieren Sie das Modell in 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"
    

    Im Befehl gcloud ai models upload gibt der Wert des Parameters --artifact-uri den Wert der Variable AIP_STORAGE_URI an. Diese Variable gibt den Speicherort des MLeap-Bundles an, das in Vertex AI importiert wird.

Modell auf einem neuen Endpunkt bereitstellen

Damit Vertex AI Vorhersagen ausführen kann, muss das importierte Modell auf einem Endpunkt bereitgestellt werden. Sie benötigen sowohl die Endpunkt-ID als auch die Modell-ID, wenn Sie das Modell bereitstellen.

  1. Erstellen Sie in Cloud Shell den Modellendpunkt:

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

    Das Erstellen des Endpunkts mit dem gcloud-Befehlszeilentool kann einige Sekunden dauern.

  2. Rufen Sie die Endpunkt-ID des neu erstellten Endpunkts ab:

    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. Rufen Sie die Modell-ID des Modells ab, das Sie im Abschnitt Modell in Vertex AI importieren importiert haben:

    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. Stellen Sie das Modell für den Endpunkt bereit:

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

    Mit dem Befehl gcloud wird das Modell auf dem Endpunkt bereitgestellt. Standardwerte werden für den Ressourcentyp des Computers, die Mindest- und Höchstanzahl von Knoten und andere Konfigurationsoptionen verwendet. Weitere Informationen zu Bereitstellungsoptionen für Modelle finden Sie in der Dokumentation zu Vertex AI.

Endpunkt testen

Nachdem Sie das Modell auf dem Endpunkt bereitgestellt haben, können Sie Ihre Implementierung testen. Zum Testen des Endpunkts können Sie den Beispielclient verwenden, der im Referenzimplementierungscode enthalten ist. Der Beispielclient generiert Vorhersageinstanzen und sendet Vorhersageanfragen an den Endpunkt. Jede Vorhersageinstanz enthält zufällige Werte für sepal_length, sepal_width, petal_length und petal_width. Standardmäßig kombiniert der Beispielclient mehrere Vorhersageinstanzen zu einer einzigen Anfrage. Die Endpunktantwort enthält eine Vorhersage für jede Instanz, die in der Anfrage gesendet wird. Die Vorhersage enthält die Wahrscheinlichkeiten für jede Klasse im Iris-Dataset (setosa, versicolor und virginica).

  • Führen Sie in Cloud Shell den Beispielvorhersageclient aus:

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

    Wenn Sie das Script zum ersten Mal ausführen, erstellt das Script eine virtuelle Python-Umgebung und installiert Abhängigkeiten. Nach der Installation der Abhängigkeiten führt das Script den Beispielclient aus. Für jede Anfrage gibt der Client die Vorhersageinstanzen und die entsprechenden Klassenwahrscheinlichkeiten an das Terminal aus. Das folgende Beispiel zeigt einen Auszug:

    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
    

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Verfahren verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Projekt löschen

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Einzelne Ressourcen löschen

  1. Heben Sie die Bereitstellung des Modells in Cloud Shell auf dem Endpunkt auf:

    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. Löschen Sie den Endpunkt:

    gcloud ai endpoints delete $ENDPOINT_ID \
        --region=$REGION \
        --quiet
    
  3. Löschen Sie das Modell:

    gcloud ai models delete $MODEL_ID \
        --region=$REGION
    
  4. Löschen Sie das Bereitstellungscontainer-Image:

    gcloud artifacts docker images delete \
        $LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE \
        --delete-tags \
        --quiet
    
  5. Löschen Sie den Builder-Container scala-sbt:

    gcloud container images delete gcr.io/$PROJECT_ID/scala-sbt \
        --force-delete-tags \
        --quiet
    
  6. Löschen Sie alle Cloud Storage-Buckets, die nicht mehr benötigt werden:

    gsutil rm -r YOUR_BUCKET_NAME
    

    Beim Löschen eines Buckets werden auch alle in diesem Bucket gespeicherten Objekte gelöscht. Gelöschte Buckets und Objekte können nach dem Löschen nicht wiederhergestellt werden.

Nächste Schritte