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
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.
Passaggio 3: crea un'istanza di Vertex AI Workbench
Dalla sezione Vertex AI della console Cloud, fai clic su Workbench:
Abilita l'API Notebooks, se non lo è già.
Una volta attivata, fai clic su NOTEBOOK GESTORI:
Quindi seleziona NUOVO Blocco note.
Assegna un nome al tuo blocco note e seleziona Account di servizio in Autorizzazione
Seleziona Impostazioni avanzate.
In Sicurezza, seleziona "Attiva terminale" se non è già attivo.
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.
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.
Nella sezione Cloud Storage della console Google Cloud, seleziona CREA.
Assegna un nome al bucket e seleziona us-central1 come regione. Quindi, fai clic su CREA.
Carica il modello di TensorFlow Hub che hai scaricato nel bucket. Assicurati di estrarre prima il file.
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.
Seleziona IMPORTA.
Seleziona Importa come nuovo modello e poi fornisci un nome per il modello.
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.
Puoi saltare la sezione Spiegabilità.
Quindi seleziona IMPORTA.
Una volta importato, il modello verrà visualizzato nel registry dei modelli
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.
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.
Una volta eseguito il deployment, lo stato del deployment diventerà Deployment eseguito su Vertex AI.
7. Ricevi previsioni
Apri il notebook Workbench che hai creato nei passaggi di configurazione. Dal programma di avvio, crea un nuovo notebook TensorFlow 2.
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.
E l'ID endpoint nella sezione Endpoint di Vertex AI.
Ora dovrai testare l'endpoint.
Innanzitutto, scarica la seguente immagine e caricala nella tua istanza.
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.
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: