Vertex AI: co-hosting di modelli sulla stessa VM per le previsioni

1. Panoramica

In questo lab utilizzerai la funzionalità di co-hosting dei modelli in Vertex AI per ospitare più modelli sulla stessa VM per le previsioni online.

Cosa imparerai

Al termine del corso sarai in grado di:

  • Crea un DeploymentResourcePool
  • Esegui il deployment dei modelli entro DeploymentResourcePool

Il costo totale per eseguire questo lab su Google Cloud è di circa 2$.

2. Introduzione a Vertex AI

Questo lab utilizza la più recente offerta di prodotti AI disponibile su Google Cloud. Vertex AI integra le offerte ML di Google Cloud in un'esperienza di sviluppo fluida. In precedenza, i modelli addestrati con AutoML e i modelli personalizzati erano accessibili tramite servizi separati. La nuova offerta combina entrambi in un'unica API, insieme ad altri nuovi prodotti. Puoi anche migrare progetti esistenti su Vertex AI. In caso di feedback, consulta la pagina di supporto.

Vertex AI include molti prodotti diversi per supportare i flussi di lavoro ML end-to-end. Questo lab è incentrato sui prodotti evidenziati di seguito: Predictions e Workbench

Panoramica dei prodotti Vertex

3. Panoramica del caso d'uso

Quando esegui il deployment dei modelli nel servizio di previsione Vertex AI, per impostazione predefinita ogni modello viene eseguito nella propria VM. Per rendere l'hosting più conveniente, puoi ospitare più modelli sulla stessa VM, con un migliore utilizzo della memoria e delle risorse di calcolo. Il numero di modelli che scegli di eseguire nella stessa VM dipende dalle dimensioni dei modelli e dai pattern di traffico, ma questa funzionalità è particolarmente utile per gli scenari in cui sono presenti molti modelli di cui è stato eseguito il deployment con traffico scarso.

Il supporto del co-hosting dei modelli introduce il concetto di pool di risorse di deployment, che raggruppa i modelli per condividere le risorse all'interno di una VM. I modelli possono condividere una VM se condividono un endpoint e anche se vengono implementati in endpoint diversi. Attualmente, i modelli nello stesso pool di risorse devono avere la stessa immagine del contenitore, inclusa la versione del framework dei container predefiniti di Vertex Prediction. Inoltre, in questa release sono supportati solo i container predefiniti di Vertex Prediction con il framework di modelli TensorFlow. Altri framework di modelli e container personalizzati non sono ancora supportati.

deployment_pool

4. Configura l'ambiente

Per eseguire questo codelab, devi avere un progetto Google Cloud con la fatturazione abilitata. Per creare un progetto, segui le istruzioni riportate qui.

Passaggio 1: abilita l'API Compute Engine

Vai a Compute Engine e seleziona Attiva se non è già abilitato.

Passaggio 2: attiva l'API Vertex AI

Vai alla sezione Vertex AI della console Cloud e fai clic su Abilita API Vertex AI.

Dashboard di Vertex AI

Passaggio 3: crea un'istanza di Vertex AI Workbench

Nella sezione Vertex AI della console Cloud, fai clic su Workbench:

Menu Vertex AI

Abilita l'API Notebooks, se non lo è già.

Notebook_api

Una volta attivata, fai clic su NOTEBOOK GESTORI:

Notebooks_UI

Quindi seleziona NUOVO NOTEBOOK.

new_notebook

Assegna un nome al notebook e in Autorizzazione seleziona Account di servizio.

create_notebook

Seleziona Impostazioni avanzate.

In Sicurezza, seleziona "Attiva terminale" se non è già abilitato.

enable_terminal

Puoi lasciare invariate tutte le altre impostazioni avanzate.

Quindi, fai clic su Crea. Il provisioning dell'istanza richiederà un paio di minuti.

Una volta creata l'istanza, seleziona APRI JUPYTERLAB.

open_jupyterlab

5. Addestramento del modello

Prima di poter provare la funzionalità di co-hosting, dobbiamo prima addestrare un modello e archiviare gli artefatti del modello salvati in un bucket Cloud Storage. Utilizzeremo l'eseguitore di notebook Workbench per avviare il job di addestramento.

Passaggio 1: crea un bucket Cloud Storage

Se nel tuo progetto esiste già un bucket che vuoi utilizzare, puoi saltare questo passaggio. In caso contrario, apri una nuova sessione di terminale dal programma di avvio.

launcher_terminal

Dal terminale, esegui il comando riportato di seguito per definire una variabile env per il tuo progetto, assicurandoti di sostituire your-cloud-project con l'ID del tuo progetto:

PROJECT_ID='your-cloud-project'

Quindi, esegui il comando seguente per creare un nuovo bucket nel progetto.

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

Passaggio 2: avvia l'esecuzione del blocco note

Dall'avvio dell'istanza Workbench, apri un nuovo blocco note TensorFlow 2.

launcher_tf2

Il codice seguente addestra un classificatore del sentiment binario (positivo o negativo) sul set di dati delle recensioni dei film di IMDB. Incolla il codice nel tuo notebook.

Assicurati di sostituire {YOUR_BUCKET} con il bucket che hai creato nel passaggio precedente (o con un altro bucket del progetto). È qui che archivieremo gli artefatti del modello salvati, di cui avremo bisogno in seguito quando caricheremo il modello in Vertex AI Model Registry.

import numpy as np

import tensorflow_datasets as tfds
import tensorflow as tf

# REPLACE WITH YOUR BUCKET!
OUTPUT_PATH='gs://{YOUR_BUCKET}/model_output'

BUFFER_SIZE = 10000
BATCH_SIZE = 64
VOCAB_SIZE = 1000

# Load data
dataset, info = tfds.load('imdb_reviews', with_info=True,
                          as_supervised=True)
train_dataset, test_dataset = dataset['train'], dataset['test']

train_dataset = train_dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)
test_dataset = test_dataset.batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)

# Create text encoder
encoder = tf.keras.layers.TextVectorization(
    max_tokens=VOCAB_SIZE)
encoder.adapt(train_dataset.map(lambda text, label: text))

# Create model
model = tf.keras.Sequential([
    encoder,
    tf.keras.layers.Embedding(
        input_dim=len(encoder.get_vocabulary()),
        output_dim=64,
        # Use masking to handle the variable sequence lengths
        mask_zero=True),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(1)
])

# Compile model
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(1e-4),
              metrics=['accuracy'])

# Fit model
history = model.fit(train_dataset, epochs=10,
                    validation_data=test_dataset,
                    validation_steps=30)

# Save model
model.save(OUTPUT_PATH)

Quindi, seleziona il pulsante Esegui.

execute_nb

Poi configura l'esecuzione come segue e fai clic su INVIA.

execution_config

Nella scheda Esecuzioni della console, puoi monitorare lo stato del job di addestramento.

execution_status

6. Esegui il deployment del modello

Passaggio 1: carica il modello

Al termine dell'esecuzione, torna al notebook Workbench per caricare il modello. Crea un nuovo blocco note TensorFlow.

tf_nb

Per prima cosa, importa l'SDK Vertex AI Python

from google.cloud import aiplatform

Carica il modello sostituendo {YOUR_BUCKET} con il bucket specificato nel codice di addestramento.

# replace {YOUR_BUCKET}
model_1 = aiplatform.Model.upload(display_name='text-model-1',
                                  artifact_uri='gs://{YOUR_BUCKET}/model_output',
                                  serving_container_image_uri='us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-8:latest')

A scopo dimostrativo, caricheremo questo modello due volte, creando due risorse modello diverse in Vertex AI. In questo modo possiamo testare il deployment di più modelli in un singolo endpoint all'interno di un pool di risorse di deployment. In uno scenario reale, avresti due modelli diversi anziché creare modelli dagli stessi elementi salvati, ma questa è una scorciatoia per non dover lanciare un'altra esecuzione dell'addestramento. Inoltre, puoi scegliere di eseguire il deployment dei due modelli in endpoint diversi all'interno dello stesso pool di risorse di deployment.

# replace {YOUR_BUCKET}
model_2 = aiplatform.Model.upload(display_name='text-model-2',
                                  artifact_uri='gs://{YOUR_BUCKET}/model_output',
                                  serving_container_image_uri='us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-8:latest')

Ora dovresti vedere entrambi i modelli in Vertex AI Model Registry. Lo stato di deployment è vuoto perché non abbiamo ancora eseguito il deployment dei modelli.

model_registry

Passaggio 2: crea un endpoint

Crea un endpoint. Tieni presente che questo approccio è diverso dal deployment di un modello in un endpoint.

endpoint = aiplatform.Endpoint.create('cohost-endpoint')

Una volta creato, l'endpoint verrà visualizzato nella console.

console_endpoint

Passaggio 3: crea DeploymentResourcePool

Puoi creare il DeploymentResourcePool con il seguente comando. Assicurati di sostituire {YOUR_PROJECT} con il tuo ID progetto.

# replace {YOUR_PROJECT}
PROJECT_ID={YOUR_PROJECT}
REGION="us-central1"
VERTEX_API_URL=REGION + "-aiplatform.googleapis.com"
VERTEX_PREDICTION_API_URL=REGION + "-prediction-aiplatform.googleapis.com"
MULTI_MODEL_API_VERSION="v1beta1"

# Give the pool a name
DEPLOYMENT_RESOURCE_POOL_ID="my-resource-pool"

import json
import pprint
pp = pprint.PrettyPrinter(indent=4)

CREATE_RP_PAYLOAD = {
  "deployment_resource_pool":{
    "dedicated_resources":{
      "machine_spec":{
        "machine_type":"n1-standard-4"
      },
      "min_replica_count":1,
      "max_replica_count":2
    }
  },
  "deployment_resource_pool_id":DEPLOYMENT_RESOURCE_POOL_ID
}
CREATE_RP_REQUEST=json.dumps(CREATE_RP_PAYLOAD)
pp.pprint("CREATE_RP_REQUEST: " + CREATE_RP_REQUEST)

!curl \
-X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools \
-d '{CREATE_RP_REQUEST}'

Puoi vedere il pool eseguendo

!curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools/{DEPLOYMENT_RESOURCE_POOL_ID}

Passaggio 4: esegui il deployment dei modelli nell'endpoint

Ora che il pool di risorse è stato creato, possiamo eseguire il deployment dei modelli all'interno del pool di risorse.

Per prima cosa, eseguiremo il deployment di model_1. Assicurati di sostituire MODEL_1_ID e ENDPOINT_ID con i rispettivi ID.

MODEL_1_ID="{MODEL_1_ID}"
ENDPOINT_ID="{ENDPOINT_ID}"

Il seguente comando eseguirà il deployment di model_1 nell'endpoint all'interno del pool di risorse.

MODEL_NAME = "projects/{project_id}/locations/{region}/models/{model_id}".format(project_id=PROJECT_ID, region=REGION, model_id=MODEL_1_ID)
SHARED_RESOURCE = "projects/{project_id}/locations/{region}/deploymentResourcePools/{deployment_resource_pool_id}".format(project_id=PROJECT_ID, region=REGION, deployment_resource_pool_id=DEPLOYMENT_RESOURCE_POOL_ID)

DEPLOY_MODEL_PAYLOAD = {
  "deployedModel": {
    "model": MODEL_NAME,
    "shared_resources": SHARED_RESOURCE
  },
  "trafficSplit": {
    "0": 100
  }
}
DEPLOY_MODEL_REQUEST=json.dumps(DEPLOY_MODEL_PAYLOAD)
pp.pprint("DEPLOY_MODEL_REQUEST: " + DEPLOY_MODEL_REQUEST)

!curl -X POST \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:deployModel \
-d '{DEPLOY_MODEL_REQUEST}'

L'operazione richiederà alcuni minuti, ma al termine vedrai il modello di cui è stato eseguito il deployment nell'endpoint nella console.

model_1_endpoint

Successivamente, possiamo eseguire il deployment di model_2 nello stesso pool di deployment. Lo eseguiremo nello stesso endpoint di model_1. Tuttavia, puoi anche scegliere di eseguire il deployment di model_2 in un endpoint diverso all'interno dello stesso pool di risorse.

Aggiorna MODEL_ID con l'ID di model_2. Anche in questo caso, puoi ottenere questo ID eseguendo model_2.name

MODEL_2_ID="{MODEL_2_ID}"

Poi esegui il deployment di model_2. Poiché abbiamo già eseguito il deployment di model_1 nell'endpoint, dobbiamo aggiornare trafficSplit in modo che il traffico sia suddiviso tra i due modelli. Non dovremmo aggiornare trafficSplit se scegliamo di eseguire il deployment di model_2 in un endpoint diverso all'interno dello stesso pool di risorse.

Per aggiornare la suddivisione del traffico, devi definire l'ID modello di deployment per model_1. Tieni presente che si tratta di un valore diverso dall'ID modello.

DEPLOYED_MODEL_1_ID = {DEPLOYED_MODEL_1_ID}

Quindi esegui quanto segue per eseguire il deployment del secondo modello.

MODEL_NAME = "projects/{project_id}/locations/{region}/models/{model_id}".format(project_id=PROJECT_ID, region=REGION, model_id=MODEL_2_ID)
SHARED_RESOURCE = "projects/{project_id}/locations/{region}/deploymentResourcePools/{deployment_resource_pool_id}".format(project_id=PROJECT_ID, region=REGION, deployment_resource_pool_id=DEPLOYMENT_RESOURCE_POOL_ID)

#`trafficSplit` is a map from a DeployedModel's ID to the percentage of this Endpoint's traffic that should be forwarded to that DeployedModel.
# The traffic percentage values for an endpoint must add up to 100.
# The key for the model being deployed is "0".

DEPLOY_MODEL_PAYLOAD = {
  "deployedModel": {
    "model": MODEL_NAME,
    "shared_resources": SHARED_RESOURCE
  },
  "trafficSplit": {
    "0": 50,
    DEPLOYED_MODEL_1_ID: 50
  }
}
DEPLOY_MODEL_REQUEST=json.dumps(DEPLOY_MODEL_PAYLOAD)
pp.pprint("DEPLOY_MODEL_REQUEST: " + DEPLOY_MODEL_REQUEST)

!curl -X POST \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:deployModel \
-d '{DEPLOY_MODEL_REQUEST}'

Anche in questo esempio i due modelli sono stati di nuovo di cui è stato eseguito il deployment nello stesso endpoint, ma puoi anche ospitare in co-hosting modelli nello stesso pool di risorse di cui è stato eseguito il deployment in endpoint diversi. In questo caso, non dovrai preoccuparti della suddivisione del traffico.

Dopo aver eseguito il deployment del secondo modello, li vedrai entrambi nella console.

deployed_models

Passaggio 5: ottieni le previsioni

Il passaggio finale consiste nel testare l'endpoint e ottenere previsioni.

Innanzitutto, definiamo la frase di test.

x_test=['The movie was cool. The animation and the graphics were out of this world. I would recommend this movie.']

Quindi, chiama la funzione di previsione nell'endpoint, che restituirà una previsione di uno dei modelli di cui è stato eseguito il deployment nell'endpoint.

endpoint.predict(instances=x_test)

🎉 Complimenti! 🎉

Hai imparato come utilizzare Vertex AI per:

  • Ospita modelli sulla stessa VM per le previsioni online

Per saperne di più sulle diverse parti di Vertex, consulta la documentazione.

7. Esegui la pulizia

Se non prevedi di utilizzarli, devi annullare il deployment dei modelli dall'endpoint. Puoi anche eliminare completamente l'endpoint. Puoi sempre rieseguire il deployment di un modello in un endpoint, se necessario.

undeploy_model

I blocchi note gestiti da Workbench scadono automaticamente dopo 180 minuti di inattività, quindi non devi preoccuparti di arrestare l'istanza. Se vuoi arrestare manualmente l'istanza, fai clic sul pulsante Interrompi nella sezione Vertex AI Workbench della console. Per eliminare completamente il blocco note, fai clic sul pulsante Elimina.

Arresta istanza

Per eliminare il bucket di archiviazione, utilizza il menu di navigazione nella console Cloud, vai a Archiviazione, seleziona il bucket e fai clic su Elimina:

Eliminare lo spazio di archiviazione