Vertex AI: użyj automatycznego pakowania, aby dostroić Berta za pomocą Hugging Face w Vertex AI Training

1. Omówienie

W tym module dowiesz się, jak uruchomić niestandardowe zadanie trenowania w Vertex AI Training za pomocą funkcji automatycznego pakowania. Niestandardowe zadania trenowania w Vertex AI korzystają z kontenerów. Jeśli nie chcesz tworzyć własnego obrazu, możesz skorzystać z automatycznego pakowania, które skompiluje niestandardowy obraz Dockera na podstawie Twojego kodu, prześle go do Container Registry i uruchomi CustomJob na podstawie tego obrazu.

Czego się nauczysz

Poznasz takie zagadnienia jak:

Całkowity koszt uruchomienia tego modułu w Google Cloud wynosi około 2 USD.

2. Omówienie zastosowania

Korzystając z bibliotek z Hugging Face, dopniesz model Bert na podstawie zbioru danych IMDB. Model określa, czy recenzja filmu jest pozytywna czy negatywna. Zbiór danych zostanie pobrany z biblioteki zbiorów danych Hugging Face, a model Bert z biblioteki konwerterów Hugging Face.

3. Wprowadzenie do Vertex AI

W tym module wykorzystano najnowszą ofertę usług AI dostępną w Google Cloud. Vertex AI integruje rozwiązania ML w Google Cloud, zapewniając bezproblemowe środowisko programistyczne. Wcześniej modele wytrenowane za pomocą AutoML i modele niestandardowe były dostępne za pomocą oddzielnych usług. Nowa oferta jest łączona w 1 interfejs API wraz z innymi nowymi usługami. Możesz też przenieść istniejące projekty do Vertex AI. Jeśli masz jakieś uwagi, odwiedź stronę pomocy.

Vertex AI zawiera wiele różnych usług, które obsługują kompleksowe przepływy pracy związane z systemami uczącymi się. Ten moduł będzie dotyczył szkolenia i Workbench.

Omówienie usługi Vertex

4. Konfigurowanie środowiska

Aby uruchomić to ćwiczenie, musisz mieć projekt Google Cloud Platform z włączonym rozliczeniem. Aby utworzyć projekt, postępuj zgodnie z tymi instrukcjami.

Krok 1. Włącz interfejs Compute Engine API

Przejdź do Compute Engine i wybierz Włącz, jeśli usługa nie jest jeszcze włączona.

Krok 2. Włącz interfejs Vertex AI API

Przejdź do sekcji Vertex AI w konsoli Cloud i kliknij Włącz interfejs Vertex AI API.

Panel Vertex AI

Krok 3. Włącz interfejs Container Registry API

Otwórz Container Registry i wybierz Włącz, jeśli nie jest jeszcze włączony. Użyjesz go do utworzenia kontenera dla niestandardowego zadania trenowania.

Krok 4. Utwórz instancję Vertex AI Workbench

W konsoli Cloud w sekcji Vertex AI kliknij Workbench:

Menu Vertex AI

Następnie kliknij ZARZĄDZANE NOTATKI:

Notebooks_UI

Następnie wybierz NOWY NOTATNIK.

new_notebook

Nadaj zeszytowi nazwę, a potem kliknij Ustawienia zaawansowane.

create_notebook

W sekcji Ustawienia zaawansowane włącz funkcję wyłączania bezczynności i ustaw liczbę minut na 60. Oznacza to, że notebook automatycznie się wyłączy, gdy nie będzie używany, dzięki czemu nie poniesiesz niepotrzebnych kosztów.

idle_timeout

Pozostałe ustawienia zaawansowane możesz pozostawić bez zmian.

Następnie kliknij Utwórz.

Po utworzeniu instancji kliknij Otwórz JupyterLab.

open_jupyterlab

Gdy po raz pierwszy użyjesz nowego wystąpienia, zostaniesz poproszony o uwierzytelnienie.

uwierzytelnij

5. Pisanie kodu trenowania

Aby rozpocząć, w menu Launcher otwórz okno Terminala w instancji notatek:

launcher_terminal

Utwórz nowy katalog o nazwie autopkg-codelab i przejdź do niego.

mkdir autopkg-codelab
cd autopkg-codelab

Aby utworzyć katalog z kodem szkoleniowym i plik Pythona, w którym dodasz kod, uruchom w terminalu następujące polecenie:

mkdir trainer
touch trainer/task.py

W katalogu autopkg-codelab/ powinien teraz znajdować się ten plik:

+ trainer/
    + task.py

Następnie otwórz utworzony plik task.py i skopiuj kod poniżej.

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()

Kilka uwag na temat kodu:

  • CHECKPOINT to model, który chcemy dostroić. W tym przypadku używamy Bert.
  • Metoda TFAutoModelForSequenceClassification wczyta określoną architekturę modelu językowego wraz z wagami w TensorFlow i doda nagłówek klasyfikacji z losowo zainicjowanymi wagami. W tym przypadku mamy problem klasyfikacji binarnej (dodatnia lub ujemna), więc dla tego klasyfikatora podajemy wartość num_labels=2.

6. Konteneryzowanie i uruchamianie kodu trenowania lokalnie

Za pomocą polecenia gcloud ai custom-jobs local-run możesz utworzyć obraz kontenera Dockera na podstawie kodu trenowania i uruchomić ten obraz jako kontener na komputerze lokalnym. Uruchamianie kontenera lokalnie powoduje, że kod trenowania jest wykonywany w sposób podobny do tego, w jaki jest wykonywany w ramach trenowania w Vertex AI. Może to ułatwić debugowanie problemów z kodem przed wykonaniem niestandardowego trenowania w Vertex AI.

W zadaniu trenowania wyeksportujemy wytrenowany model do zasobnika Cloud Storage. W terminalu uruchom to polecenie, aby zdefiniować zmienną środowiskową dla projektu. Pamiętaj, aby zastąpić your-cloud-project identyfikatorem projektu:

PROJECT_ID='your-cloud-project'

Następnie utwórz zasobnik. Jeśli masz już zasób, możesz go użyć.

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

Gdy uruchamiamy niestandardowe zadanie trenowania w Vertex AI Training, użyjemy GPU. Ponieważ nie określiliśmy instancji Workbench z kartami graficznymi, do testowania lokalnego użyjemy obrazu z procesorem. W tym przykładzie użyjemy gotowego kontenera Vertex AI Training.

Aby ustawić identyfikator URI obrazu Dockera, który ma być używany jako podstawa kontenera, uruchom to polecenie:

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

Następnie nadaj nazwę wynikowemu obrazowi Dockera utworzonemu przez lokalne polecenie run.

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

Nasz kod treningowy korzysta z danych i bibliotek transformatorów Hugging Face. Te biblioteki nie są zawarte w obrazie wybranym jako obraz podstawowy, dlatego musimy je podać jako wymagania. W tym celu utworzymy plik requirements.txt w naszym katalogu autopkg-codelab.

Upewnij się, że jesteś w katalogu autopkg-codelab, i wpisz w terminalu:

touch requirements.txt

W katalogu autopkg-codelab powinien teraz znajdować się ten plik:

+ requirements.txt
+ trainer/
    + task.py

Otwórz plik wymagań i wklej ten kod:

datasets==1.18.2
transformers==4.16.2

Na koniec uruchom polecenie gcloud ai custom-jobs local-run, aby rozpocząć trenowanie w instancji zarządzanej 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

Powinieneś zobaczyć kompilowanie obrazu Dockera. Zależności dodane do pliku requirements.txt zostaną zainstalowane pip. Pierwsze wykonanie tego polecenia może potrwać kilka minut. Po skompilowaniu obrazu uruchomi się pliktask.py i rozpocznie się trenowanie modelu. Powinien pojawić się ekran podobny do tego:

local_training

Ponieważ nie używamy lokalnie karty graficznej, trenowanie modelu zajmie dużo czasu. Zamiast czekać na zakończenie zadania, możesz nacisnąć Ctrl+C i anulować lokalne trenowanie.

Pamiętaj, że jeśli chcesz przeprowadzić dalsze testy, możesz również bezpośrednio uruchomić obraz utworzony powyżej bez ponownego opakowania.

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

7. Tworzenie zadania niestandardowego

Po przetestowaniu trybu lokalnego użyjemy funkcji automatycznego pakowania, aby uruchomić niestandardowe zadanie trenowania w Treningu Vertex AI. Wystarczy jedno polecenie, aby:

  • Utwórz niestandardowy obraz Dockera na podstawie swojego kodu.
  • Prześlij obraz do Container Registry.
  • Utwórz CustomJob na podstawie obrazu.

Wróć do terminala i wejdź o jeden poziom wyżej katalogu autopkg-codelab.

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

Określ gotowy obraz GPU TensorFlow w Vertex AI Training jako obraz podstawowy dla niestandardowego zadania trenowania.

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

Następnie uruchom polecenie gcloud ai custom-jobs create. Najpierw to polecenie utworzy niestandardowy obraz Dockera na podstawie kodu trenowania. Obraz podstawowy to gotowy kontener Vertex AI Training skonfigurowany jako BASE_GPU_IMAGE. Funkcja automatycznego pakowania zainstaluje pip zbiory danych i biblioteki transformerów zgodnie z opisem w naszym pliku 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

Przyjrzyjmy się argumentowi worker-pool-spec. Określa konfigurację puli instancji roboczych używaną przez zadanie niestandardowe. Aby utworzyć niestandardowe zadanie z kilkoma pulami instancji roboczych na potrzeby rozproszonego treningu, możesz określić wiele specyfikacji puli instancji roboczych. W tym przykładzie określamy tylko jedną pulę instancji roboczych, ponieważ nasz kod trenowania nie jest skonfigurowany do trenowania rozproszonego.

Oto niektóre z najważniejszych pól tej specyfikacji:

  • machine-type (wymagany): typ maszyny. Kliknij tutaj, aby wyświetlić obsługiwane typy.
  • replica-count: liczba replik zadań roboczych, które mają być użyte przez ten pulę zadań roboczych. Domyślnie wartość wynosi 1.
  • accelerator-type: typ układów GPU. Kliknij tutaj, aby zobaczyć obsługiwane typy. W tym przykładzie użyliśmy jednego procesora graficznego NVIDIA Tesla V100.
  • accelerator-count: liczba GPU dla każdej maszyny wirtualnej w puli roboczej, do której ma być użyta. Domyślnie wartość wynosi 1.
  • executor-image-uri: identyfikator URI obrazu kontenera, który będzie uruchamiać podany pakiet. Jest ono ustawione na nasze zdjęcie podstawowe.
  • local-package-path: ścieżka lokalna folderu zawierającego kod trenowania.
  • python-module: nazwa modułu Pythona, który ma być uruchamiany w podanym pakiecie.

Podobnie jak w przypadku polecenia lokalnego, zobaczysz obraz Dockera, który jest kompilowany, a potem rozpocznie się zadanie treningowe. Z tą różnicą, że zamiast danych wyjściowych zadania treningowego zobaczysz ten komunikat potwierdzający uruchomienie zadania treningowego. Pamiętaj, że przy pierwszym uruchomieniu polecenia custom-jobs create kompilacja i przesłanie obrazu może potrwać kilka minut.

training_started

Wróć do sekcji Vertex AI Training w konsoli Cloud. Twoje zadanie powinno być uruchomione w obszarze NIESTANDARDOWE ZADANIA.

training_job

Zajmie to około 20 minut.

Po zakończeniu procesu w katalogu model_output w Twoim zasobie powinny pojawić się zapisane artefakty modelu.

model_output

🎉 Gratulacje! 🎉

Poznałeś/poznałaś już te sposoby korzystania z Vertex AI:

  • Konteneryzowanie i uruchamianie kodu trenowania lokalnie
  • Przesyłanie zadań treningowych do Vertex AI Training za pomocą automatycznego pakowania

Więcej informacji o różnych elementach Vertex AI znajdziesz w dokumentacji.

8. Czyszczenie

Skonfigurowaliśmy notatnik tak, aby przekraczał limit czasu po 60 minutach bezczynności, więc nie musimy się martwić wyłączeniem instancji. Jeśli chcesz ręcznie wyłączyć instancję, w konsoli Vertex AI Workbench kliknij przycisk Zatrzymaj. Jeśli chcesz całkowicie usunąć zeszyt, kliknij przycisk Usuń.

usuń

Aby usunąć zasobnik Cloud Storage, w menu nawigacyjnym konsoli Cloud przejdź do usługi Storage, wybierz zasobnik i kliknij Usuń:

Usuń miejsce na dane