Prototyp w środowisku produkcyjnym: dostrajanie hiperparametrów

1. Omówienie

W tym module użyjesz Vertex AI do uruchomienia zadania dopasowywania parametrów w treningu Vertex AI.

Ten moduł należy do serii filmów Prototyp – produkcja. Zanim rozpoczniesz ten moduł, ukończ poprzedni moduł. Aby dowiedzieć się więcej, możesz obejrzeć towarzyszącą serię filmów:

.

Czego się nauczysz

Poznasz takie zagadnienia jak:

  • Zmień kod aplikacji do trenowania, aby automatycznie dostrajać hiperparametry
  • Konfigurowanie i uruchamianie zadania dostrajania hiperparametrów za pomocą pakietu Vertex AI Python SDK

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

2. Wprowadzenie do Vertex AI

Ten moduł wykorzystuje 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.

Vertex AI zawiera wiele różnych usług, które obsługują kompleksowe przepływy pracy ML. Ten moduł będzie dotyczył podanych niżej usług: szkolenia i Workbench.

Omówienie usługi Vertex

3. Konfigurowanie środowiska

Aby skonfigurować środowisko, wykonaj czynności opisane w laboratorium Trenowanie niestandardowych modeli za pomocą Vertex AI.

4. Konteneryzowanie kodu aplikacji do trenowania

Przesyłasz to zadanie trenowania do Vertex AI, umieszczając kod aplikacji do trenowania w kontenerze Dockera i przesyłając ten kontener do Google Artifact Registry. Dzięki temu możesz trenować i dostrajać model utworzony za pomocą dowolnego frameworku.

Aby rozpocząć, otwórz okno terminala w menu Launchera w notatniku Workbench utworzonym w poprzednich laboratoriach.

Otwórz terminal w notatniku

Krok 1. Napisz kod treningowy

Utwórz nowy katalog o nazwie flowers-hptune i przejdź do niego:

mkdir flowers-hptune
cd flowers-hptune

Uruchom te polecenia, aby utworzyć katalog dla kodu szkoleniowego i plik Pythona, w którym umieścisz kod podany poniżej.

mkdir trainer
touch trainer/task.py

W katalogu flowers-hptune/ powinny znajdować się teraz te elementy:

+ trainer/
    + task.py

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

W polu BUCKET_ROOT zastąp wartość {your-gcs-bucket} zasobnikiem Cloud Storage, w którym przechowywany jest zbiór danych o kwiatach utworzony w sekcji Laboratorium 1.

import tensorflow as tf
import numpy as np
import os
import hypertune
import argparse

## Replace {your-gcs-bucket} !!
BUCKET_ROOT='/gcs/{your-gcs-bucket}'

# Define variables
NUM_CLASSES = 5
EPOCHS=10
BATCH_SIZE = 32

IMG_HEIGHT = 180
IMG_WIDTH = 180

DATA_DIR = f'{BUCKET_ROOT}/flower_photos'

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 create_datasets(data_dir, batch_size):
  '''Creates train and validation datasets.'''

  train_dataset = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(IMG_HEIGHT, IMG_WIDTH),
    batch_size=batch_size)

  validation_dataset = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(IMG_HEIGHT, IMG_WIDTH),
    batch_size=batch_size)

  train_dataset = train_dataset.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
  validation_dataset = validation_dataset.cache().prefetch(buffer_size=tf.data.AUTOTUNE)

  return train_dataset, validation_dataset


def create_model(num_units, learning_rate, momentum):
  '''Creates model.'''

  model = tf.keras.Sequential([
    tf.keras.layers.Resizing(IMG_HEIGHT, IMG_WIDTH),
    tf.keras.layers.Rescaling(1./255, input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
    tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(num_units, activation='relu'),
    tf.keras.layers.Dense(NUM_CLASSES, activation='softmax')
  ])

  model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
              loss=tf.keras.losses.SparseCategoricalCrossentropy(),
              metrics=['accuracy'])
  
  return model

def main():
  args = get_args()
  train_dataset, validation_dataset = create_datasets(DATA_DIR, BATCH_SIZE)
  model = create_model(args.num_units, args.learning_rate, args.momentum)
  history = model.fit(train_dataset, validation_data=validation_dataset, epochs=EPOCHS)

  # 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=EPOCHS)


if __name__ == "__main__":
    main()

Zanim utworzysz kontener, przyjrzyj się bliżej kodom. Niektóre komponenty są przeznaczone do korzystania z usługi doboru hiperparametrów.

  1. Skrypt importuje bibliotekę hypertune.
  2. Funkcja get_args() definiuje argument wiersza poleceń dla każdego hiperparametru, który chcesz dostroić. W tym przykładzie dostrajane są hiperparametry: tempo uczenia się, wartość momentum w optymalizatorze i liczba jednostek w ostatniej warstwie ukrytej modelu, ale możesz też eksperymentować z innymi. Wartość przekazana 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 definiowania danych, które chcesz optymalizować. W TensorFlow metoda keras model.fit 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 trenujesz model przez 3 epoki z danymi walidacyjnymi i podajesz jako dane accuracy, 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 znajdowała wartości maksymalizujące dokładność walidacji modelu, zdefiniuj metrykę jako ostatni wpis (lub NUM_EPOCS - 1) na liście val_accuracy. Następnie prześlij te dane do wystąpienia elementu HyperTune. W polu hyperparameter_metric_tag możesz wpisać dowolny ciąg tekstowy, ale później, gdy uruchomisz zadanie dostrajania hiperparametrów, będziesz musiał(-a) użyć tego samego ciągu.

Krok 2. Utwórz plik Dockerfile

Aby skonteneryzować kod, musisz utworzyć plik Dockerfile. W pliku Dockerfile musisz uwzględnić wszystkie polecenia potrzebne do uruchomienia obrazu. Spowoduje to zainstalowanie wszystkich niezbędnych bibliotek i ustawienie punktu wejścia dla kodu trenowania.

W terminalu utwórz pusty plik Dockerfile w katalogu flowers-hptune:

touch Dockerfile

W katalogu flowers-hptune/ powinien teraz znajdować się ten plik:

+ Dockerfile
+ trainer/
    + task.py

Otwórz plik Dockerfile i skopiuj do niego ten kod. Zauważysz, że jest on prawie taki sam jak plik Dockerfile, którego użyto w pierwszym module, ale teraz instalujemy bibliotekę cloudml-hypertune.

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

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"]

Krok 3. Utwórz kontener

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'

zdefiniować repozytorium w Artifact Registry, Użyjemy repozytorium utworzonego w pierwszym laboratorium.

REPO_NAME='flower-app'

Zdefiniuj zmienną z identyfikatorem URI obrazu kontenera w Google Artifact Registry:

IMAGE_URI=us-central1-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/flower_image_hptune:latest

Skonfiguruj Dockera

gcloud auth configure-docker \
    us-central1-docker.pkg.dev

Następnie utwórz kontener, uruchamiając to polecenie w katalogu głównym flower-hptune:

docker build ./ -t $IMAGE_URI

Na koniec przekaż go do Artifact Registry:

docker push $IMAGE_URI

Po przeniesieniu kontenera do Artifact Registry możesz rozpocząć zadanie trenowania.

5. Uruchamianie zadania dostrajania hiperparametrów za pomocą pakietu SDK

Z tej sekcji dowiesz się, jak skonfigurować i przesłać zadanie strojenia hiperparametrów za pomocą interfejsu Vertex Python API.

W menu 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ć worker_pool_specs, które określa typ maszyny i obraz Dockera. W specyfikacji poniżej określono jedną maszynę z 2 procesorami graficznymi NVIDIA Tesla V100.

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": "us-central1-docker.pkg.dev/{PROJECT_ID}/flower-app/flower_image_hptune:latest"
    }
}]

Następnie zdefiniuj parameter_spec, czyli słownik określający parametry, które chcesz zoptymalizować. Klucz słownika to ciąg tekstowy przypisany do argumentu wiersza poleceń dla każdego hiperparametru, a wartość słownika to specyfikacja parametru.

W przypadku każdego parametru musisz zdefiniować typ oraz zakresy wartości, które będzie testować usługa do strojenia. Parametry nadrzędne mogą być typu podwójnego, całkowitego, wielowymiarowego lub dyskretnego. Jeśli wybierzesz typ Liczba podwójna lub Liczba całkowita, musisz podać wartość minimalną i maksymalną. Jeśli wybierzesz opcję Kategoryczna lub Rozłączna, musisz podać wartości. W przypadku typów Podwójna liczba i Liczba całkowita musisz też podać wartość Skalowanie. Więcej informacji o wyborze najlepszej wagi znajdziesz w tym filmie.

# 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)
}

Ostatnią specyfikacją do zdefiniowania jest metric_spec, czyli słownik reprezentujący dane, które mają zostać zoptymalizowane. Kluczem słownika jest hyperparameter_metric_tag ustawiony w kodzie aplikacji do trenowania, a wartością jest cel optymalizacji.

# Dictionary representing metric 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'}

Po zdefiniowaniu specyfikacji utworzysz zadanie niestandardowe, które jest wspólną specyfikacją, która będzie używana do uruchamiania zadania w ramach każdej próby dostrajania hiperparametrów.

Zastąp {YOUR_BUCKET} utworzony wcześniej zasobnik.

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='flowers-hptune-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='flowers-hptune-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()

Oto kilka argumentów:

  • max_trial_count: musisz ustawić górną granicę liczby prób, które usługa będzie wykonywać. W ogóle im więcej prób, tym lepsze wyniki, ale w pewnym momencie następuje spadek skuteczności, po którym kolejne próby nie mają już wpływu na dane, które próbujesz zoptymalizować. Najlepiej zacząć od mniejszej liczby prób i przed zwiększeniem skali sprawdzić, jak duży wpływ mają wybrane hiperparametry.
  • parallel_trial_count: jeśli korzystasz z równoległych prób, usługa udostępnia wiele klastrów przetwarzania trenowania. Zwiększenie liczby równoległych prób skraca czas wykonania zadania dostrajania hiperparametrów, ale może zmniejszyć ogólną skuteczność zadania. Dzieje się tak, ponieważ domyślna strategia dostrajania korzysta z wyników poprzednich prób do przypisywania wartości w kolejnych próbach.
  • search_algorithm: algorytm wyszukiwania możesz ustawić jako siatkowy, losowy lub domyślny (brak). Domyślna opcja stosuje optymalizację bayesowską do wyszukiwania przestrzeni możliwych wartości hiperparametrów i jest zalecanym algorytmem. Więcej informacji o tym algorytmie znajdziesz tutaj.

W konsoli możesz sprawdzać postępy zadania.

hp_job

Po zakończeniu każdej z nich możesz sprawdzić wyniki i zestaw wartości o najlepszej skuteczności.

hp_results

🎉 Gratulacje! 🎉

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

  • Uruchamianie automatycznego zadania dostrajania hiperparametrów

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

6. Czyszczenie

Notebook został skonfigurowany tak, aby wyłączał się po 60 minutach bezczynności, więc nie musisz się martwić zamykaniem 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ąć zeszyt, kliknij przycisk Usuń.

Zatrzymaj instancję

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

Usuwanie miejsca na dane