Vertex AI: usa la pacchettizzazione automatica per ottimizzare BERT con Hugging Face su Vertex AI Training

1. Panoramica

In questo lab imparerai a eseguire un job di addestramento personalizzato su Vertex AI Training con la funzionalità di pacchettizzazione automatica. I job di addestramento personalizzati su Vertex AI utilizzano i container. Se non vuoi creare un'immagine personalizzata, puoi utilizzare auotpackaging, che crea un'immagine Docker personalizzata in base al codice, esegue il push dell'immagine su Container Registry e avvia un CustomJob in base all'immagine.

Cosa imparerai

Imparerai a:

Il costo totale per l'esecuzione di questo lab su Google Cloud è di circa 2$.

2. Panoramica del caso d'uso

Utilizzando le librerie di Hugging Face, potrai ottimizzare un modello BERT sul set di dati IMDB. Il modello prevede se la recensione di un film è positiva o negativa. Il set di dati verrà scaricato dalla libreria di set di dati di Hugging Face e il modello BERT dalla libreria dei trasformatori di Hugging Face.

3. 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 su addestramento e Workbench.

Panoramica del prodotto Vertex

4. Configura l'ambiente

Per eseguire questo codelab, è necessario un progetto Google Cloud con fatturazione abilitata. Per creare un progetto, segui le istruzioni riportate qui.

Passaggio 1: abilita l'API Compute Engine

Passa a Compute Engine e seleziona Abilita se non è già abilitato.

Passaggio 2: abilita l'API Vertex AI

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

Dashboard di Vertex AI

Passaggio 3: abilita l'API Container Registry

Vai a Container Registry e seleziona Abilita, se non è già selezionato. Lo utilizzerai per creare un container per il tuo job di addestramento personalizzato.

Passaggio 4: crea un'istanza di Vertex AI Workbench

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

Menu Vertex AI

Quindi, fai clic su QUADRI GESTITI:

Notebooks_UI

Quindi seleziona NUOVO Blocco note.

new_notebook

Assegna un nome al blocco note, quindi fai clic su Impostazioni avanzate.

create_notebook

In Impostazioni avanzate, abilita l'arresto per inattività e imposta il numero di minuti su 60. Ciò significa che il blocco note si arresterà automaticamente quando non è in uso, per evitare costi inutili.

idle_timeout

Puoi lasciare invariate tutte le altre impostazioni avanzate.

Quindi, fai clic su Crea.

Una volta creata l'istanza, seleziona Apri JupyterLab.

open_jupyterlab

La prima volta che utilizzi una nuova istanza, ti verrà chiesto di autenticarti.

autenticare

5. Scrivi il codice di addestramento

Per iniziare, dal menu Avvio app, apri una finestra Terminale nell'istanza del blocco note:

launcher_terminal

Crea una nuova directory chiamata autopkg-codelab e accedi con cd.

mkdir autopkg-codelab
cd autopkg-codelab

Dal tuo terminale, esegui quanto segue per creare una directory per il codice di addestramento e un file Python in cui aggiungerai il codice:

mkdir trainer
touch trainer/task.py

Ora dovresti avere quanto segue nella directory autopkg-codelab/:

+ trainer/
    + task.py

Successivamente, apri il file task.py che hai appena creato e copia il codice seguente.

import argparse

import tensorflow as tf
from datasets import load_dataset
from transformers import AutoTokenizer
from transformers import TFAutoModelForSequenceClassification

CHECKPOINT = "bert-base-cased"

def get_args():
  '''Parses args.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--epochs',
      required=False,
      default=3,
      type=int,
      help='number of epochs')
  parser.add_argument(
      '--job_dir',
      required=True,
      type=str,
      help='bucket to store saved model, include gs://')
  args = parser.parse_args()
  return args


def create_datasets():
    '''Creates a tf.data.Dataset for train and evaluation.'''

    raw_datasets = load_dataset('imdb')
    tokenizer = AutoTokenizer.from_pretrained(CHECKPOINT)
    tokenized_datasets = raw_datasets.map((lambda examples: tokenize_function(examples, tokenizer)), batched=True)

    # To speed up training, we use only a portion of the data.
    # Use full_train_dataset and full_eval_dataset if you want to train on all the data.
    small_train_dataset = tokenized_datasets['train'].shuffle(seed=42).select(range(1000))
    small_eval_dataset = tokenized_datasets['test'].shuffle(seed=42).select(range(1000))
    full_train_dataset = tokenized_datasets['train']
    full_eval_dataset = tokenized_datasets['test']

    tf_train_dataset = small_train_dataset.remove_columns(['text']).with_format("tensorflow")
    tf_eval_dataset = small_eval_dataset.remove_columns(['text']).with_format("tensorflow")

    train_features = {x: tf_train_dataset[x] for x in tokenizer.model_input_names}
    train_tf_dataset = tf.data.Dataset.from_tensor_slices((train_features, tf_train_dataset["label"]))
    train_tf_dataset = train_tf_dataset.shuffle(len(tf_train_dataset)).batch(8)

    eval_features = {x: tf_eval_dataset[x] for x in tokenizer.model_input_names}
    eval_tf_dataset = tf.data.Dataset.from_tensor_slices((eval_features, tf_eval_dataset["label"]))
    eval_tf_dataset = eval_tf_dataset.batch(8)

    return train_tf_dataset, eval_tf_dataset


def tokenize_function(examples, tokenizer):
    '''Tokenizes text examples.'''

    return tokenizer(examples['text'], padding='max_length', truncation=True)


def main():
    args = get_args()
    train_tf_dataset, eval_tf_dataset = create_datasets()
    model = TFAutoModelForSequenceClassification.from_pretrained(CHECKPOINT, num_labels=2)

    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=tf.metrics.SparseCategoricalAccuracy(),
    )

    model.fit(train_tf_dataset, validation_data=eval_tf_dataset, epochs=args.epochs)
    model.save(f'{args.job_dir}/model_output')


if __name__ == "__main__":
    main()

Ecco alcuni aspetti da considerare sul codice:

  • CHECKPOINT è il modello che vogliamo ottimizzare. In questo caso utilizziamo BERT.
  • Il metodo TFAutoModelForSequenceClassification caricherà l'architettura del modello linguistico e i pesi specificati in TensorFlow e aggiungerà un'intestazione di classificazione in alto con ponderazioni inizializzate in modo casuale. In questo caso, abbiamo un problema di classificazione binaria (positiva o negativa), quindi specifichiamo num_labels=2 per questo classificatore.

6. Containerizzazione ed esecuzione del codice di addestramento a livello locale

Puoi utilizzare il comando gcloud ai custom-jobs local-run per creare un'immagine container Docker basata sul codice di addestramento ed eseguirla come container sulla macchina locale. L'esecuzione in locale di un container permette di eseguire il codice di addestramento in modo simile all'esecuzione su Vertex AI Training e può essere utile per eseguire il debug dei problemi del codice prima di eseguire l'addestramento personalizzato su Vertex AI.

Nel job di addestramento, esporteremo il modello addestrato in un bucket Cloud Storage. Dal tuo terminale, esegui quanto segue 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, crea un bucket. Se hai già un bucket, puoi utilizzarlo.

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

Quando eseguiamo il job di addestramento personalizzato su Vertex AI Training, utilizziamo una GPU. Ma poiché non abbiamo specificato la nostra istanza Workbench con GPU, utilizzeremo un'immagine basata su CPU per i test locali. In questo esempio viene utilizzato un container predefinito Vertex AI Training.

Esegui questo comando per impostare l'URI di un'immagine Docker da utilizzare come base del container.

BASE_CPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-7:latest

Quindi imposta un nome per l'immagine Docker creata dal comando locale run.

OUTPUT_IMAGE=$PROJECT_ID-local-package-cpu:latest

Il nostro codice di addestramento utilizza i set di dati e le librerie dei trasformatori di Hugging Face. Queste librerie non sono incluse nell'immagine che abbiamo selezionato come immagine di base, pertanto dovremo fornirle come requisiti. Per farlo, creeremo un file requirements.txt nella directory autopkg-codelab.

Assicurati di essere nella directory autopkg-codelab e digita quanto segue nel terminale.

touch requirements.txt

Ora dovresti avere quanto segue nella directory autopkg-codelab:

+ requirements.txt
+ trainer/
    + task.py

Apri il file dei requisiti e incolla il seguente

datasets==1.18.2
transformers==4.16.2

Infine, esegui il comando gcloud ai custom-jobs local-run per avviare l'addestramento sulla nostra istanza gestita di Workbench.

gcloud ai custom-jobs local-run \
--executor-image-uri=$BASE_CPU_IMAGE \
--python-module=trainer.task \
--output-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME

Dovresti vedere l'immagine Docker in creazione. Le dipendenze che abbiamo aggiunto al file requirements.txt verranno installate tramite pip. Il completamento dell'operazione potrebbe richiedere alcuni minuti la prima volta che esegui questo comando. Una volta creata l'immagine, inizierà l'esecuzione del file task.py e vedrai l'addestramento del modello. Il risultato dovrebbe essere simile a questo:

local_training

Poiché non stiamo utilizzando una GPU in locale, l'addestramento del modello richiederà molto tempo. Puoi premere Ctrl+C e annullare l'addestramento locale invece di attendere il completamento del job.

Tieni presente che se vuoi fare ulteriori test, puoi anche eseguire direttamente l'immagine creata in precedenza, senza ripacchettirla.

gcloud beta ai custom-jobs local-run \
--executor-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME \
--epochs=1

7. Creazione di un job personalizzato

Ora che abbiamo testato la modalità locale, utilizzeremo la funzionalità di pacchettizzazione automatica per avviare il nostro job di addestramento personalizzato su Vertex AI Training. Con un solo comando, questa funzionalità:

  • Crea un'immagine Docker personalizzata basata sul tuo codice.
  • Esegui il push dell'immagine in Container Registry.
  • Avvia un CustomJob basato sull'immagine.

Torna al terminale e vai al livello superiore della directory autopkg-codelab.

+ autopkg-codelab
  + requirements.txt
  + trainer/
      + task.py

Specifica l'immagine GPU TensorFlow predefinita di Vertex AI Training come immagine di base per il job di addestramento personalizzato.

BASE_GPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-gpu.2-7:latest

A questo punto, esegui il comando gcloud ai custom-jobs create. Innanzitutto, questo comando creerà un'immagine Docker personalizzata basata sul codice di addestramento. L'immagine di base è il container predefinito Vertex AI Training che abbiamo impostato come BASE_GPU_IMAGE. La funzionalità di autopackaging eseguirà poi il pip di installare i set di dati e le librerie dei trasformatori come specificato nel nostro file requirements.txt.

gcloud ai custom-jobs create \
--region=us-central1 \
--display-name=fine_tune_bert \
--args=--job_dir=$BUCKET_NAME \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,accelerator-type=NVIDIA_TESLA_V100,executor-image-uri=$BASE_GPU_IMAGE,local-package-path=autopkg-codelab,python-module=trainer.task

Diamo un'occhiata all'argomento worker-pool-spec. Definisce la configurazione del pool di worker utilizzata dal job personalizzato. Puoi specificare più specifiche di un pool di worker per creare un job personalizzato con più pool di worker per l'addestramento distribuito. In questo esempio specifichiamo un solo pool di worker, dato che il nostro codice di addestramento non è configurato per l'addestramento distribuito.

Ecco alcuni dei campi principali di questa specifica:

  • (Obbligatorio) machine-type: il tipo di macchina. Fai clic qui per conoscere i tipi supportati.
  • replica-count: il numero di repliche dei worker da utilizzare per questo pool di worker. Per impostazione predefinita, il valore è 1.
  • accelerator-type: il tipo di GPU. Fai clic qui per conoscere i tipi supportati. In questo esempio, abbiamo specificato una GPU NVIDIA Tesla V100.
  • accelerator-count: il numero di GPU per ogni VM nel pool di worker da utilizzare. Per impostazione predefinita il valore è 1.
  • executor-image-uri: l'URI di un'immagine container che eseguirà il pacchetto fornito. È impostata sulla nostra immagine di base.
  • local-package-path: il percorso locale di una cartella che contiene il codice di addestramento.
  • python-module: il nome del modulo Python da eseguire all'interno del pacchetto fornito.

Analogamente a quando hai eseguito il comando locale, vedrai l'immagine Docker in fase di creazione e il job di addestramento verrà avviato. Tranne che anziché vedere l'output del job di addestramento, verrà visualizzato il seguente messaggio che conferma l'avvio del job di addestramento. Tieni presente che la prima volta che esegui il comando custom-jobs create, potrebbero essere necessari alcuni minuti per la creazione e il push dell'immagine.

training_started

Torna alla sezione Vertex AI Training della console Cloud e in JOB PERSONALIZZATI dovresti vedere il tuo job in esecuzione.

training_job

Il completamento del job richiederà circa 20 minuti.

Al termine, dovresti vedere i seguenti artefatti del modello salvati nella directory model_output del tuo bucket.

model_output

🎉 Complimenti! 🎉

Hai imparato come utilizzare Vertex AI per:

  • Containerizzazione ed esecuzione del codice di addestramento a livello locale
  • Inviare job di addestramento a Vertex AI Training con la pacchettizzazione automatica

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

8. Esegui la pulizia

Poiché abbiamo configurato il timeout del blocco note dopo 60 minuti di inattività, 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. Per eliminare completamente il blocco note, fai clic sul pulsante Elimina.

elimina

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

Elimina spazio di archiviazione