Ottieni previsioni da un modello di immagine TensorFlow preaddestrato su Vertex AI

1. Panoramica

In questo lab utilizzerai Vertex AI per ottenere previsioni da un modello di classificazione delle immagini preaddestrato.

Cosa imparerai

Al termine del corso sarai in grado di:

  • Importa un modello TensorFlow in Vertex AI Model Registry
  • Ricevi previsioni online
  • Aggiorna una funzione di pubblicazione di TensorFlow

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

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.

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

In questo lab imparerai a prendere un modello preaddestrato da TensorFlow Hub ed eseguirlo su Vertex AI. TensorFlow Hub è un repository di modelli addestrati per una serie di domini di problemi, come incorporamenti, generazione di testo, conversione della voce in testo, segmentazione delle immagini e altro ancora.

L'esempio utilizzato in questo lab è un modello di classificazione delle immagini MobileNet V1 preaddestrato sul set di dati ImageNet. Sfruttando i modelli di uso comune di TensorFlow Hub o altri repository di deep learning simili, puoi implementare modelli ML di alta qualità per una serie di attività di previsione senza doverti preoccupare dell'addestramento dei modelli.

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

Dalla 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 Blocco note.

new_notebook

Assegna un nome al tuo blocco note e seleziona Account di servizio in Autorizzazione

create_notebook

Seleziona Impostazioni avanzate.

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

enable_terminal

Puoi lasciare invariate tutte le altre impostazioni avanzate.

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

Dopo aver creato l'istanza, seleziona APRI JUPYTERLAB.

open_jupyterlab

5. Registra modello

Passaggio 1: carica il modello in Cloud Storage

Fai clic su questo link per andare alla pagina di TensorFlow Hub del modello MobileNet V1 addestrato sul set di dati ImagNet.

Seleziona Scarica per scaricare gli artefatti salvati del modello.

download_model

Nella sezione Cloud Storage della console Google Cloud, seleziona CREA.

create_bucket

Assegna un nome al bucket e seleziona us-central1 come regione. Quindi, fai clic su CREA.

specify_bucket

Carica il modello di TensorFlow Hub che hai scaricato nel bucket. Assicurati di estrarre prima il file.

gcs_model

Il bucket dovrebbe avere il seguente aspetto:

imagenet_mobilenet_v1_050_128_classification_5/
  saved_model.pb
  variables/
    variables.data-00000-of-00001
    variables.index

Passaggio 2: importa il modello nel registro

Vai alla sezione Registro dei modelli di Vertex AI della console Cloud.

model_registry

Seleziona IMPORTA.

Seleziona Importa come nuovo modello e poi fornisci un nome per il modello.

name_and_region

In Impostazioni modello, specifica il container TensorFlow predefinito più recente. Quindi, seleziona in Cloud Storage il percorso in cui hai archiviato gli artefatti del modello.

select_container

Puoi saltare la sezione Spiegabilità.

Quindi seleziona IMPORTA.

Una volta importato, il modello verrà visualizzato nel registry dei modelli

imported_model

6. Esegui il deployment del modello

Nel registry Model, seleziona i tre puntini sul lato destro del modello e fai clic su Esegui il deployment su endpoint.

deploy_model

In Definisci il tuo endpoint, seleziona Crea nuovo endpoint, quindi assegna un nome all'endpoint.

In Impostazioni modello, imposta il Numero massimo di nodi di calcolo su 1 e il tipo di macchina su n1-standard-2 e lascia invariate tutte le altre impostazioni. Poi fai clic su ESEGUI DEPLOY.

endpoint_settings

Una volta eseguito il deployment, lo stato del deployment diventerà Deployment eseguito su Vertex AI.

deploy_status

7. Ricevi previsioni

Apri il notebook Workbench che hai creato nei passaggi di configurazione. Dal programma di avvio, crea un nuovo notebook TensorFlow 2.

tf_nb

Esegui questa cella per importare le librerie necessarie

from google.cloud import aiplatform

import tensorflow as tf
import numpy as np
from PIL import Image

Il modello MobileNet scaricato da TensorFlow Hub è stato addestrato sul set di dati ImageNet. L'output del modello MobileNet è un numero che corrisponde a un'etichetta di classe nel set di dati ImageNet. Per tradurre il numero in un'etichetta di stringa, devi scaricare le etichette delle immagini.

# Download image labels

labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())

Per raggiungere l'endpoint, devi definire la risorsa endpoint. Assicurati di sostituire {PROJECT_NUMBER} e {ENDPOINT_ID}.

PROJECT_NUMBER = "{PROJECT_NUMBER}"
ENDPOINT_ID = "{ENDPOINT_ID}"

endpoint = aiplatform.Endpoint(
    endpoint_name=f"projects/{PROJECT_NUMBER}/locations/us-central1/endpoints/{ENDPOINT_ID}")

Puoi trovare il numero del tuo progetto nella home page della console.

project_number

E l'ID endpoint nella sezione Endpoint di Vertex AI.

endpoint_id

Ora dovrai testare l'endpoint.

Innanzitutto, scarica la seguente immagine e caricala nella tua istanza.

test_image

Apri l'immagine con PIL. Quindi ridimensiona e scala per 255. Tieni presente che le dimensioni delle immagini previste dal modello sono disponibili nella pagina di TensorFlow Hub del modello.

IMAGE_PATH = "test-image.jpg"
IMAGE_SIZE = (128, 128)

im = Image.open(IMAGE_PATH)
im = im.resize(IMAGE_SIZE
im = np.array(im)/255.0

Poi, converti i dati NumPy in un elenco in modo che possano essere inviati nel corpo della richiesta HTTP.

x_test = im.astype(np.float32).tolist()

Infine, effettua una chiamata di previsione all'endpoint e cerca l'etichetta della stringa corrispondente.

# make prediction request
result = endpoint.predict(instances=[x_test]).predictions

# post process result
predicted_class = tf.math.argmax(result[0], axis=-1)
string_label = imagenet_labels[predicted_class]

print(f"label ID: {predicted_class}")
print(f"string label: {string_label}")

8. [Facoltativo] Utilizzare TF Serving per ottimizzare le previsioni

Per esempi più realistici, ti consigliamo di inviare direttamente l'immagine all'endpoint, anziché caricarla prima in NumPy. Questa operazione è più efficiente, ma devi modificare la funzione di servizio del modello TensorFlow. Questa modifica è necessaria per convertire i dati di input nel formato previsto dal modello.

Passaggio 1: modifica la funzione di pubblicazione

Apri un nuovo blocco note TensorFlow e importa le librerie necessarie.

from google.cloud import aiplatform

import tensorflow as tf

Invece di scaricare gli elementi del modello salvati, questa volta caricherai il modello in TensorFlow utilizzando hub.KerasLayer, che avvolge un SavedModel di TensorFlow come livello Keras. Per creare il modello, puoi utilizzare l'API Keras Sequential con il modello TF Hub scaricato come livello e specificare la forma dell'input al modello.

tfhub_model = tf.keras.Sequential(
    [hub.KerasLayer("https://tfhub.dev/google/imagenet/mobilenet_v1_050_128/classification/5")]
)
tfhub_model.build([None, 128, 128, 3])

Definisci l'URI del bucket che hai creato in precedenza.

BUCKET_URI = "gs://{YOUR_BUCKET}"
MODEL_DIR = BUCKET_URI + "/bytes_model"

Quando invii una richiesta a un server di previsione online, la richiesta viene ricevuta da un server HTTP. Il server HTTP estrae la richiesta di previsione dal corpo dei contenuti della richiesta HTTP. La richiesta di previsione estratta viene inoltrata alla funzione di pubblicazione. Per i container di previsione predefiniti di Vertex AI, il contenuto della richiesta viene passato alla funzione di pubblicazione come tf.string.

Per passare immagini al servizio di previsione, devi codificare i byte dell'immagine compressi in base 64. In questo modo, i contenuti non possono essere modificati durante la trasmissione dei dati binari sulla rete.

Poiché il modello di cui è stato eseguito il deployment si aspetta dati di input sotto forma di byte non elaborati (non compressi), devi assicurarti che i dati con codifica base 64 vengano convertiti di nuovo in byte non elaborati (ad es. JPEG) e poi pre-elaborate per soddisfare i requisiti di input del modello, prima di essere passati come input al modello di cui è stato eseguito il deployment.

Per risolvere questo problema, definisci una funzione di pubblicazione (serving_fn) e la colleghi al modello come fase di pre-elaborazione. Aggiungi un decoratore @tf.function in modo che la funzione di pubblicazione venga unita al modello sottostante (anziché a monte su una CPU).

CONCRETE_INPUT = "numpy_inputs"


def _preprocess(bytes_input):
    decoded = tf.io.decode_jpeg(bytes_input, channels=3)
    decoded = tf.image.convert_image_dtype(decoded, tf.float32)
    resized = tf.image.resize(decoded, size=(128, 128))
    return resized


@tf.function(input_signature=[tf.TensorSpec([None], tf.string)])
def preprocess_fn(bytes_inputs):
    decoded_images = tf.map_fn(
        _preprocess, bytes_inputs, dtype=tf.float32, back_prop=False
    )
    return {
        CONCRETE_INPUT: decoded_images
    }  # User needs to make sure the key matches model's input


@tf.function(input_signature=[tf.TensorSpec([None], tf.string)])
def serving_fn(bytes_inputs):
    images = preprocess_fn(bytes_inputs)
    prob = m_call(**images)
    return prob


m_call = tf.function(tfhub_model.call).get_concrete_function(
    [tf.TensorSpec(shape=[None, 128, 128, 3], dtype=tf.float32, name=CONCRETE_INPUT)]
)

tf.saved_model.save(tfhub_model, MODEL_DIR, signatures={"serving_default": serving_fn})

Quando invii i dati per la previsione come pacchetto di richiesta HTTP, i dati dell'immagine sono codificati in base64, ma il modello TensorFlow accetta input numpy. La funzione di pubblicazione eseguirà la conversione da base64 a un array numpy.

Quando effettui una richiesta di previsione, devi indirizzarla alla funzione di pubblicazione anziché al modello, quindi devi conoscere il nome del livello di input della funzione di pubblicazione. Possiamo ottenere questo nome dalla firma della funzione di pubblicazione.

loaded = tf.saved_model.load(MODEL_DIR)

serving_input = list(
    loaded.signatures["serving_default"].structured_input_signature[1].keys()
)[0]
print("Serving function input name:", serving_input)

Passaggio 2: importa nel registry ed esegui il deployment

Nelle sezioni precedenti hai visto come importare un modello in Vertex AI Model Registry tramite la UI. In questa sezione viene mostrato un modo alternativo per utilizzare l'SDK. Tieni presente che, se preferisci, puoi comunque utilizzare l'interfaccia utente qui.

model = aiplatform.Model.upload(
    display_name="optimized-model",
    artifact_uri=MODEL_DIR,
    serving_container_image_uri="us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-8:latest",
)

print(model)

Puoi anche eseguire il deployment del modello utilizzando l'SDK anziché l'interfaccia utente.

endpoint = model.deploy(
     deployed_model_display_name='my-bytes-endpoint',
     traffic_split={"0": 100},
     machine_type="n1-standard-4",
     accelerator_count=0,
     min_replica_count=1,
     max_replica_count=1,
   )

Passaggio 3: testa il modello

Ora puoi testare l'endpoint. Poiché abbiamo modificato la funzione di pubblicazione, questa volta puoi inviare l'immagine direttamente (codificata in base64) nella richiesta anziché caricarla prima in NumPy. In questo modo potrai anche inviare immagini più grandi senza raggiungere il limite di dimensioni di Vertex AI Predictions.

Scarica di nuovo le etichette delle immagini

import numpy as np
labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())

Codifica l'immagine in base64.

import base64

with open("test-image.jpg", "rb") as f:
    data = f.read()
b64str = base64.b64encode(data).decode("utf-8")

Esegui una chiamata di previsione specificando il nome del livello di input della funzione di pubblicazione che abbiamo definito in precedenza nella variabile serving_input.

instances = [{serving_input: {"b64": b64str}}]

# Make request
result = endpoint.predict(instances=instances).predictions

# Convert image class to string label
predicted_class = tf.math.argmax(result[0], axis=-1)
string_label = imagenet_labels[predicted_class]

print(f"label ID: {predicted_class}")
print(f"string label: {string_label}")

🎉 Complimenti! 🎉

Hai imparato come utilizzare Vertex AI per:

  • Ospitazione ed esecuzione del deployment di un modello pre-addestrato

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

9. Esegui la pulizia

Poiché i notebook gestiti di Vertex AI Workbench dispongono di una funzionalità di arresto in caso di inattività, non dobbiamo preoccuparci 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