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:

  • Importare un modello TensorFlow in Vertex AI Model Registry
  • Generare previsioni online
  • Aggiornare 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 si concentrerà sui prodotti evidenziati di seguito: Predictions e Workbench.

Panoramica del prodotto Vertex

3. Panoramica del caso d'uso

In questo lab imparerai a prendere un modello preaddestrato da TensorFlow Hub ed eseguirne il deployment su Vertex AI. TensorFlow Hub è un repository di modelli addestrati per una varietà di domini problematici, come incorporamenti, generazione di testo, sintesi vocale, 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 standard di TensorFlow Hub o di altri repository di deep learning simili, puoi eseguire il deployment di modelli di machine learning 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 Platform 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 Abilita se non è già abilitato.

Passaggio 2: abilita l'API Vertex AI

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

Dashboard 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 l'hai già fatto.

Notebook_api

Una volta abilitata, fai clic su NOTEBOOK GESTITI:

Notebooks_UI

Quindi seleziona NUOVO NOTEBOOK.

new_notebook

Assegna un nome al notebook e, in Autorizzazione , seleziona Service account.

create_notebook

Seleziona Impostazioni avanzate.

In Sicurezza , seleziona "Abilita 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à alcuni minuti.

Una volta creata 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 per il modello MobileNet V1 addestrato sul set di dati ImageNet.

Seleziona Scarica per scaricare gli artefatti del modello salvato.

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 decomprimere prima il file.

gcs_model

Il bucket dovrebbe avere un aspetto simile al seguente:

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 Model Registry di Vertex AI della console Cloud.

model_registry

Seleziona IMPORT.

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 il percorso in Cloud Storage in cui hai archiviato gli artefatti del modello.

select_container

Puoi saltare la sezione Spiegabilità.

Quindi seleziona IMPORT.

Una volta importato, vedrai il modello nel registro dei modelli.

imported_model

6. Esegui il deployment del modello

In Model Registry, seleziona i tre puntini sul lato destro del modello e fai clic su Esegui il deployment nell'endpoint.

deploy_model

In Definisci l'endpoint , seleziona Crea nuovo endpoint e poi 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. Quindi, fai clic su ESEGUI IL DEPLOYMENT.

endpoint_settings

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

deploy_status

7. Ricevi previsioni

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

tf_nb

Esegui la seguente 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 che hai 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 questo numero in un'etichetta 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 di progetto nella home page della console.

project_number

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

endpoint_id

Ora testerai l'endpoint.

Innanzitutto, scarica l'immagine seguente e caricala nell'istanza.

test_image

Apri l'immagine con PIL. Quindi ridimensiona e scala di 255. Tieni presente che le dimensioni dell'immagine 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

Quindi, 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 poi cerca l'etichetta 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] Utilizza TF Serving per ottimizzare le previsioni

Per esempi più realistici, probabilmente ti consigliamo di inviare direttamente l'immagine all'endpoint, anziché caricarla prima in NumPy. Questo è più efficiente, ma dovrai modificare la funzione di pubblicazione 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 notebook TensorFlow e importa le librerie necessarie.

from google.cloud import aiplatform

import tensorflow as tf

Anziché scaricare gli artefatti del modello salvato, questa volta caricherai il modello in TensorFlow utilizzando hub.KerasLayer, che esegue il wrapping di un modello SavedModel di TensorFlow come strato Keras. Per creare il modello, puoi utilizzare l'API Keras Sequential con il modello TF Hub scaricato come strato e specificare la forma di input del 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 del contenuto 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 le immagini al servizio di previsione, dovrai codificare i byte dell'immagine compressa in base 64, in modo che il contenuto sia protetto dalle modifiche durante la trasmissione di dati binari sulla rete.

Poiché il modello di cui è stato eseguito il deployment prevede che i dati di input siano byte non elaborati (non compressi), devi assicurarti che i dati con codifica base 64 vengano riconvertiti in byte non elaborati (ad es. JPEG) e poi pre-elaborati in modo che corrispondano ai 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 passaggio di pre-elaborazione. Aggiungi un decoratore @tf.function in modo che la funzione di pubblicazione venga unita al modello sottostante (anziché upstream 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 richieste HTTP, i dati immagine vengono 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 indirizzare la richiesta alla funzione di pubblicazione anziché al modello, quindi devi conoscere il nome dello strato 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 registro ed esegui il deployment

Nelle sezioni precedenti hai visto come importare un modello in Vertex AI Model Registry tramite la UI. In questa sezione vedrai un modo alternativo utilizzando l'SDK. Tieni presente che puoi comunque utilizzare la UI se preferisci.

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é la UI.

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 (con codifica base64) nella richiesta anziché caricarla prima in NumPy. In questo modo potrai anche inviare immagini più grandi senza superare 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")

Effettua una chiamata di previsione, specificando il nome dello strato 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}")

🎉 Congratulazioni! 🎉

Hai imparato come utilizzare Vertex AI per:

  • Ospitare ed eseguire il deployment di un modello preaddestrato

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

9. Esegui la pulizia

Poiché i notebook gestiti di Vertex AI Workbench hanno una funzionalità di arresto inattivo, non dobbiamo preoccuparci di arrestare l'istanza. Se vuoi arrestare manualmente l'istanza, fai clic sul pulsante Arresta nella sezione Vertex AI Workbench della console. Se vuoi eliminare completamente il notebook, fai clic sul pulsante Elimina.

Arresta istanza

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

Elimina spazio di archiviazione