Vertex AI: dostrajanie hiperparametrów

1. Omówienie

W tym module wykorzystasz Vertex AI do uruchomienia zadania dostrajania hiperparametrów na potrzeby modelu TensorFlow. Chociaż w tym module do tworzenia kodu modelu używany jest TensorFlow, podane koncepcje mają też zastosowanie do innych platform ML.

Czego się nauczysz

Poznasz takie zagadnienia jak:

  • Zmodyfikuj kod aplikacji treningowej na potrzeby automatycznego dostrajania hiperparametrów
  • Konfigurowanie i uruchamianie zadania dostrajania hiperparametrów w interfejsie użytkownika Vertex AI
  • Skonfiguruj i uruchom zadanie dostrajania hiperparametrów za pomocą pakietu SDK Vertex AI w języku Python.

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

2. Wprowadzenie do Vertex AI

W tym module wykorzystano najnowszą ofertę usług AI dostępną w Google Cloud. Vertex AI integruje ofertę systemów uczących się z całego Google Cloud, tworząc bezproblemowe środowisko programistyczne. Wcześniej modele wytrenowane z użyciem AutoML i modele niestandardowe były dostępne w oddzielnych usługach. 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 obejmuje wiele różnych usług, które obsługują kompleksowe przepływy pracy ML. W tym module skupimy się na wyróżnionych poniżej usługach: Training i Workbench.

Omówienie usługi Vertex

3. Skonfiguruj środowisko

Aby uruchomić to ćwiczenia z programowania, musisz mieć projekt Google Cloud Platform z włączonymi płatnościami. Aby utworzyć projekt, postępuj zgodnie z tymi instrukcjami.

Krok 1. Włącz Compute Engine API

Przejdź do Compute Engine i wybierz opcję Włącz, jeśli nie jest jeszcze włączona. Będzie Ci to potrzebne do utworzenia instancji notatnika.

Krok 2. Włącz 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 3. 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 4. Utwórz instancję Vertex AI Workbench

W sekcji Vertex AI w konsoli Cloud kliknij Workbench:

Menu Vertex AI

Włącz Notebooks API, jeśli nie jest jeszcze włączone.

Notebook_api

Po włączeniu kliknij ZARZĄDZANE NOTATKI:

Notebooks_UI

Następnie wybierz NOWY NOTATNIK.

new_notebook

Nadaj notatnikowi nazwę i kliknij Ustawienia zaawansowane.

create_notebook

W sekcji Ustawienia zaawansowane włącz wyłączanie w trybie bezczynności i ustaw liczbę minut na 60. Oznacza to, że Twój notatnik automatycznie wyłączy się, gdy nie będzie używany, aby nie ponosić niepotrzebnych kosztów.

idle_timeout

W sekcji Zabezpieczenia wybierz „Włącz terminal”. , jeśli nie jest jeszcze włączona.

enable_terminal

Inne ustawienia zaawansowane możesz pozostawić bez zmian.

Następnie kliknij Utwórz. Udostępnienie instancji zajmie kilka minut.

Po utworzeniu instancji wybierz Otwórz JupyterLab.

open_jupyterlab

Przy pierwszym użyciu nowej instancji zobaczysz prośbę o uwierzytelnienie. W tym celu postępuj zgodnie z instrukcjami w interfejsie.

uwierzytelnij

4. Konteneryzowanie kodu aplikacji do trenowania

Model, który będziesz trenować i dostrajać w tym module, to model klasyfikacji obrazów wytrenowany na zbiorze danych koni lub ludzi ze zbiorów danych TensorFlow.

Musisz przesłać to zadanie dostrajania hiperparametrów do Vertex AI, umieszczając kod aplikacji treningowej w kontenerze Dockera i przenosząc ten kontener do Google Container Registry. Dzięki tej metodzie możesz dostroić hiperparametry na potrzeby modelu utworzonego na dowolnej platformie.

Aby rozpocząć, w menu Menu z aplikacjami otwórz okno terminala w instancji notatnika:

Otwórz terminal w notatniku

Utwórz nowy katalog o nazwie horses_or_humans i znajdź do niego dysk CD:

mkdir horses_or_humans
cd horses_or_humans

Krok 1. Utwórz plik Dockerfile

Pierwszym krokiem w konteneryzacji kodu jest utworzenie pliku Dockerfile. W pliku Dockerfile znajdziesz wszystkie polecenia potrzebne do uruchomienia obrazu. Zainstaluje wszystkie niezbędne biblioteki, w tym bibliotekę CloudML Hypertune, oraz skonfiguruje punkt wejścia kodu trenowania.

W terminalu utwórz pusty plik Dockerfile:

touch Dockerfile

Otwórz plik Dockerfile i skopiuj do niego poniższy plik:

FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7

WORKDIR /

# Installs hypertune library
RUN pip install cloudml-hypertune

# Copies the trainer code to the docker image.
COPY trainer /trainer

# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]

Ten plik Dockerfile wykorzystuje obraz Dockera GPU TensorFlow Enterprise 2.7. Kontenery do deep learningu w Google Cloud mają wstępnie zainstalowane wiele popularnych platform do uczenia maszynowego i platformy do badania danych. Po pobraniu tego obrazu plik Dockerfile konfiguruje punkt wejścia dla kodu trenowania. Nie utworzono jeszcze tych plików – w następnym kroku dodasz kod do trenowania i dostrajania modelu.

Krok 2. Dodaj kod trenowania modelu

W terminalu uruchom to polecenie, aby utworzyć katalog na kod trenowania i plik Pythona, w którym dodasz kod:

mkdir trainer
touch trainer/task.py

W katalogu horses_or_humans/ powinny znajdować się teraz te elementy:

+ Dockerfile
+ trainer/
    + task.py

Następnie otwórz utworzony przed chwilą plik task.py i skopiuj poniższy kod.

import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune

NUM_EPOCHS = 10


def get_args():
  '''Parses args. Must include all hyperparameters you want to tune.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--learning_rate',
      required=True,
      type=float,
      help='learning rate')
  parser.add_argument(
      '--momentum',
      required=True,
      type=float,
      help='SGD momentum value')
  parser.add_argument(
      '--num_units',
      required=True,
      type=int,
      help='number of units in last hidden layer')
  args = parser.parse_args()
  return args


def preprocess_data(image, label):
  '''Resizes and scales images.'''

  image = tf.image.resize(image, (150,150))
  return tf.cast(image, tf.float32) / 255., label


def create_dataset():
  '''Loads Horses Or Humans dataset and preprocesses data.'''

  data, info = tfds.load(name='horses_or_humans', as_supervised=True, with_info=True)

  # Create train dataset
  train_data = data['train'].map(preprocess_data)
  train_data  = train_data.shuffle(1000)
  train_data  = train_data.batch(64)

  # Create validation dataset
  validation_data = data['test'].map(preprocess_data)
  validation_data  = validation_data.batch(64)

  return train_data, validation_data


def create_model(num_units, learning_rate, momentum):
  '''Defines and compiles model.'''

  inputs = tf.keras.Input(shape=(150, 150, 3))
  x = tf.keras.layers.Conv2D(16, (3, 3), activation='relu')(inputs)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(32, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(64, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(num_units, activation='relu')(x)
  outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)
  model = tf.keras.Model(inputs, outputs)
  model.compile(
      loss='binary_crossentropy',
      optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
      metrics=['accuracy'])
  return model


def main():
  args = get_args()
  train_data, validation_data = create_dataset()
  model = create_model(args.num_units, args.learning_rate, args.momentum)
  history = model.fit(train_data, epochs=NUM_EPOCHS, validation_data=validation_data)

  # DEFINE METRIC
  hp_metric = history.history['val_accuracy'][-1]

  hpt = hypertune.HyperTune()
  hpt.report_hyperparameter_tuning_metric(
      hyperparameter_metric_tag='accuracy',
      metric_value=hp_metric,
      global_step=NUM_EPOCHS)


if __name__ == "__main__":
    main()

Zanim utworzysz kontener, przyjrzyjmy się kodowi. Usługa dostrajania hiperparametrów ma kilka charakterystycznych elementów.

  1. Skrypt importuje bibliotekę hypertune. Pamiętaj, że plik Dockerfile z kroku 1 zawiera instrukcje dotyczące instalacji tej biblioteki przy użyciu pip.
  2. Funkcja get_args() definiuje argument wiersza poleceń dla każdego hiperparametru, który chcesz dostroić. W tym przykładzie dostrojone hiperparametry to szybkość uczenia się, wartość pędu w optymalizatorze i liczba jednostek w ostatniej ukrytej warstwie modelu. Możesz też eksperymentować z innymi. Wartość przekazywana w tych argumentach jest następnie używana do ustawienia odpowiedniego hiperparametru w kodzie.
  3. Na końcu funkcji main() biblioteka hypertune służy do określenia danych, które chcesz optymalizować. W TensorFlow metoda model.fit Kera zwraca obiekt History. Atrybut History.history zawiera zapis wartości strat trenowania i wartości wskaźników w kolejnych epokach. Jeśli przekażesz dane weryfikacyjne do model.fit, atrybut History.history będzie też zawierać wartości utracone podczas weryfikacji i wskaźniki. Jeśli na przykład wytrenujesz model z 3 epokami z danymi do weryfikacji i podasz accuracy jako wskaźnik, atrybut History.history będzie wyglądać podobnie do tego słownika.
{
 "accuracy": [
   0.7795261740684509,
   0.9471358060836792,
   0.9870933294296265
 ],
 "loss": [
   0.6340447664260864,
   0.16712145507335663,
   0.04546636343002319
 ],
 "val_accuracy": [
   0.3795261740684509,
   0.4471358060836792,
   0.4870933294296265
 ],
 "val_loss": [
   2.044623374938965,
   4.100203514099121,
   3.0728273391723633
 ]

Jeśli chcesz, aby usługa dostrajania hiperparametrów wykrywała wartości maksymalizujące dokładność walidacji modelu, zdefiniuj wskaźnik jako ostatnią pozycję (lub NUM_EPOCS - 1) na liście val_accuracy. Następnie przekaż ten wskaźnik do instancji HyperTune. Możesz wybrać dowolny ciąg dla hyperparameter_metric_tag, ale trzeba będzie użyć go później, gdy uruchomisz zadanie dostrajania hiperparametrów.

Krok 3. Utwórz kontener

W terminalu uruchom to polecenie, aby zdefiniować zmienną env dla swojego projektu, pamiętając o zastąpieniu your-cloud-project identyfikatorem projektu:

PROJECT_ID='your-cloud-project'

Zdefiniuj zmienną za pomocą identyfikatora URI obrazu kontenera w Google Container Registry:

IMAGE_URI="gcr.io/$PROJECT_ID/horse-human:hypertune"

Skonfiguruj Dockera

gcloud auth configure-docker

Następnie utwórz kontener, uruchamiając to polecenie z poziomu głównego katalogu horses_or_humans:

docker build ./ -t $IMAGE_URI

Na koniec wypchnij go do Google Container Registry:

docker push $IMAGE_URI

Po przekazaniu kontenera do Container Registry możesz teraz uruchomić zadanie dostrajania hiperparametrów modelu niestandardowego.

5. Uruchamianie zadania dostrajania hiperparametrów w Vertex AI

W tym module używane jest trenowanie niestandardowe za pomocą niestandardowego kontenera w Google Container Registry, ale możesz też uruchomić zadanie dostrajania hiperparametrów za pomocą gotowego kontenera Vertex AI.

Zacznij od sekcji Trenowanie w sekcji Vertex w konsoli Cloud:

Menu uCAIP

Krok 1. Skonfiguruj zadanie trenowania

Kliknij Utwórz, aby podać parametry zadania dostrajania hiperparametrów.

  • W sekcji Zbiór danych wybierz Brak zarządzanego zbioru danych.
  • Następnie wybierz Trenowanie niestandardowe (zaawansowane) jako metodę trenowania i kliknij Dalej.
  • W polu Nazwa modelu wpisz horses-humans-hyptertune (lub inną nazwę modelu)
  • Kliknij Dalej.

W kroku „Ustawienia kontenera” wybierz Kontener niestandardowy:

Opcja kontenera niestandardowego

W pierwszym polu (Obraz kontenera) wpisz wartość zmiennej IMAGE_URI z poprzedniej sekcji. Powinien to być: gcr.io/your-cloud-project/horse-human:hypertune z nazwą Twojego projektu. Pozostałe pola pozostaw puste i kliknij Dalej.

Krok 2. Skonfiguruj zadanie dostrajania hiperparametrów

Wybierz Włącz dostrajanie hiperparametrów.

Hiperparametry

Konfigurowanie hiperparametrów

Następnie musisz dodać hiperparametry ustawione jako argumenty wiersza poleceń w kodzie aplikacji treningowej. Dodając hiperparametr, musisz najpierw podać jego nazwę. Powinna ona odpowiadać nazwie argumentu przekazanej do argparse.

learning_rate_name

Następnie wybierz typ oraz granice wartości, które będzie próbować zastosować usługa dostrajania. Jeśli wybierzesz typ Liczba podwójna lub Liczba całkowita, musisz podać wartość minimalną i maksymalną. Jeśli wybierzesz Kategorialne lub Dyskretne, musisz podać wartości.

learning_rate_typelearning_rate_name

W przypadku typów Podwójna liczba i Liczba całkowita musisz też podać wartość Skalowanie.

learning_rate_scale

Po dodaniu hiperparametru learning_rate dodaj parametry momentum i num_units.

momentum_config

numneruons_config

Skonfiguruj wskaźnik

Po dodaniu hiperparametrów musisz też podać dane, które chcesz zoptymalizować, oraz cel. Powinno być takie samo jak hyperparameter_metric_tag skonfigurowane w aplikacji do trenowania.

metric_config

Usługa dostrajania hiperparametrów Vertex AI uruchomi wiele prób aplikacji treningowej z wartościami skonfigurowanymi w poprzednich krokach. Musisz wyznaczyć górną granicę liczby wersji próbnych usługi. Większa liczba prób prowadzi zwykle do lepszych wyników, ale występuje wtedy spadek zysków, po których dodatkowe testy mają znikomy wpływ na dane, które próbujesz zoptymalizować, lub nie mają ich wcale. Sprawdzoną metodą jest, aby rozpocząć od mniejszej liczby prób i poznać wpływ wybranych hiperparametrów, zanim przeskalujesz je do dużej liczby prób.

Musisz też ustawić górną granicę liczby równoległych prób. Zwiększenie liczby równoległych prób skróci czas wykonywania zadania dostrajania hiperparametrów. ale może też ogólnie zmniejszyć efektywność zadania. Dzieje się tak, ponieważ domyślna strategia dostrajania wykorzystuje wyniki poprzednich prób do przypisania wartości w kolejnych próbach. Jeśli uruchomisz zbyt wiele prób równolegle, niektóre próby zaczną się bez korzyści wynikających z ich wyników.

Dla celów demonstracyjnych możesz ustawić liczbę prób na 15, a maksymalną liczbę równoległych prób na 3. Możesz eksperymentować z różnymi wartościami, ale może to wydłużyć czas dostrajania i zwiększyć koszty.

trial_config

Ostatnim krokiem jest wybranie domyślnego algorytmu wyszukiwania, co spowoduje, że narzędzie Google Vizier przeprowadzi optymalizację Bayesa do dostrajania hiperparametrów. Więcej informacji o tym algorytmie

algorithm_config

Kliknij Dalej.

Krok 3. Skonfiguruj jednostki obliczeniowe

W sekcji Obliczenia i ceny pozostaw wybrany region bez zmian i skonfiguruj Pula instancji roboczych 0 w ten sposób.

Typ maszyny

Kliknij Rozpocznij trenowanie, aby uruchomić zadanie dostrajania hiperparametrów. W sekcji Training (Szkolenia) na karcie HYPERPARAMETER TUNING JOBS (ZADANIA DOCELOWE REKLAM HIPERPARAMETER) w konsoli zobaczysz coś takiego:

Zadania hiperparametrów

Po zakończeniu możesz kliknąć nazwę zadania i wyświetlić wyniki prób dostrajania.

Dane wyjściowe hiperparametru

🎉 Gratulacje! 🎉

Wiesz już, jak używać Vertex AI do:

  • Uruchom zadanie dostrajania hiperparametrów na potrzeby kodu trenowania podanego w kontenerze niestandardowym. W tym przykładzie użyto modelu TensorFlow, ale możesz wytrenować model utworzony za pomocą dowolnej platformy, korzystając z niestandardowych kontenerów.

Więcej informacji o różnych częściach Vertex znajdziesz w dokumentacji.

6. [Opcjonalnie] Użyj pakietu Vertex SDK

W poprzedniej sekcji pokazaliśmy, jak uruchomić zadanie dostrajania hiperparametrów za pomocą interfejsu użytkownika. W tej sekcji zobaczysz alternatywny sposób przesyłania zadania dostrajania hiperparametrów przy użyciu interfejsu Vertex Python API.

W Menu z aplikacjami utwórz notatnik TensorFlow 2.

new_notebook

Zaimportuj pakiet Vertex AI SDK.

from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt

Aby uruchomić zadanie dostrajania hiperparametrów, musisz najpierw zdefiniować poniższe specyfikacje. Musisz zastąpić zmienną {PROJECT_ID} w image_uri swoim projektem.

# The spec of the worker pools including machine type and Docker image
# Be sure to replace PROJECT_ID in the `image_uri` with your project.

worker_pool_specs = [{
    "machine_spec": {
        "machine_type": "n1-standard-4",
        "accelerator_type": "NVIDIA_TESLA_V100",
        "accelerator_count": 1
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human:hypertune"
    }
}]


# Dictionary representing metrics to optimize.
# The dictionary key is the metric_id, which is reported by your training job,
# And the dictionary value is the optimization goal of the metric.
metric_spec={'accuracy':'maximize'}

# Dictionary representing parameters to optimize.
# The dictionary key is the parameter_id, which is passed into your training
# job as a command line argument,
# And the dictionary value is the parameter specification of the metric.
parameter_spec = {
    "learning_rate": hpt.DoubleParameterSpec(min=0.001, max=1, scale="log"),
    "momentum": hpt.DoubleParameterSpec(min=0, max=1, scale="linear"),
    "num_units": hpt.DiscreteParameterSpec(values=[64, 128, 512], scale=None)
}

Następnie utwórz CustomJob. Musisz zastąpić obiekt {YOUR_BUCKET} zasobnikiem na potrzeby testowania w projekcie.

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans-sdk-job',
                              worker_pool_specs=worker_pool_specs,
                              staging_bucket='gs://{YOUR_BUCKET}')

Następnie utwórz i uruchom HyperparameterTuningJob.

hp_job = aiplatform.HyperparameterTuningJob(
    display_name='horses-humans-sdk-job',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=15,
    parallel_trial_count=3)

hp_job.run()

7. 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ę, kliknij przycisk Zatrzymaj w sekcji Vertex AI Workbench w konsoli. Jeśli chcesz całkowicie usunąć notatnik, kliknij przycisk Usuń.

Zatrzymaj instancję

Aby usunąć zasobnik na dane, w menu nawigacyjnym w konsoli Google Cloud otwórz Cloud Storage, wybierz swój zasobnik i kliknij Usuń:

Usuń miejsce na dane