1. Omówienie
W tym module dowiesz się, jak używać Vertex AI do dostrajania parametrów i rozproszonego trenowania. W tym laboratorium do kodu modelu używany jest TensorFlow, ale omawiane tu zagadnienia można zastosować również do innych platform ML.
Czego się nauczysz
Poznasz takie zagadnienia jak:
- Trenowanie modelu przy użyciu trenowania rozproszonego w kontenerze niestandardowym
- Uruchom kilka prób treningu kodu w celu automatycznego dostrajania hiperparametrów
Łączny koszt przeprowadzenia tego laboratorium w Google Cloud wynosi około 6 USD.
2. Wprowadzenie do Vertex AI
Ten moduł wykorzystuje 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 za pomocą AutoML i modele niestandardowe były dostępne za pomocą oddzielnych usług. Nowa oferta łączy oba te interfejsy API z innymi nowymi usługami. Możesz też przenieść istniejące projekty do Vertex AI. Jeśli chcesz podzielić się opinią, 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ę. W tym module omówimy trenowanie i Workbench.
3. Omówienie przypadku użycia
W tym module użyjesz dostrajania hiperparametrów, aby znaleźć optymalne parametry modelu klasyfikacji obrazów wytrenowanego na zbiorze danych horses or humans z zbiorów danych TensorFlow.
Dostrajanie hiperparametrów
Dostosowywanie hiperparametrów za pomocą funkcji Vertex AI Training polega na uruchamianiu wielu prób aplikacji treningowej z wartościami wybranych hiperparametrów ustawionymi w określonych przez Ciebie granicach. Vertex AI śledzi wyniki każdej próby i wprowadza korekty w przypadku kolejnych prób.
Aby korzystać z dostrajania hiperparametrów w Vertex AI Training, musisz wprowadzić 2 zmiany w kodzie trenowania:
- W głównym module treningowym zdefiniuj argument wiersza poleceń dla każdego hiperparametru, który chcesz dostroić.
- Użyj wartości przekazanych w tych argumentach, aby ustawić odpowiedni hiperparametr w kodzie aplikacji.
Trenowanie rozproszone
Jeśli masz pojedynczy procesor graficzny, TensorFlow użyje tego akceleratora, aby przyspieszyć trenowanie modelu bez dodatkowych działań z Twojej strony. Jeśli jednak chcesz uzyskać dodatkową wydajność dzięki użyciu wielu procesorów graficznych, musisz użyć tf.distribute
, czyli modułu TensorFlow do wykonywania obliczeń na wielu urządzeniach.
W tym laboratorium używamy tf.distribute.MirroredStrategy
, który można dodać do aplikacji do trenowania, wprowadzając tylko kilka zmian w kodzie. Ta strategia tworzy kopię modelu na każdym GPU na komputerze. Kolejne aktualizacje gradientu będą przeprowadzane synchronicznie. Oznacza to, że każdy procesor graficzny oblicza ruch do przodu i do tyłu przez model na innym wycinku danych wejściowych. Obliczone gradienty z każdego z tych kawałków są następnie agregowane na wszystkich procesorach graficznych i uśredniane w ramach procesu zwanego all-reduce. Parametry modelu są aktualizowane za pomocą tych średnich gradientów.
Nie musisz znać szczegółów, aby ukończyć ten moduł, ale jeśli chcesz dowiedzieć się więcej o tym, jak działa rozproszone trenowanie w TensorFlow, obejrzyj film poniżej:
4. Konfigurowanie środowiska
Aby uruchomić to ćwiczenie, musisz mieć projekt Google Cloud Platform z włączonym rozliczeniem. Aby utworzyć projekt, wykonaj te instrukcje.
Krok 1. Włącz 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 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.
Krok 4. Utwórz instancję Vertex AI Workbench
W sekcji Vertex AI w konsoli Cloud kliknij Workbench:
Włącz interfejs Notebooks API, jeśli nie jest jeszcze włączony.
Po włączeniu tej opcji kliknij ZARZĄDZANE NOTATKI:
Następnie wybierz NOWY NOTATNIK.
Nadaj notatnikowi nazwę i kliknij Ustawienia zaawansowane.
W sekcji Ustawienia zaawansowane włącz funkcję wyłączania 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.
W sekcji Zabezpieczenia wybierz „Włącz terminal”, jeśli nie jest jeszcze włączony.
Pozostałe ustawienia zaawansowane możesz pozostawić bez zmian.
Następnie kliknij Utwórz. Przygotowanie instancji może potrwać kilka minut.
Po utworzeniu instancji kliknij Otwórz JupyterLab.
Gdy po raz pierwszy użyjesz nowego wystąpienia, zostaniesz poproszony o uwierzytelnienie. W tym celu postępuj zgodnie z instrukcjami w interfejsie.
5. Pisanie kodu trenowania
Aby rozpocząć, w menu Launcher otwórz okno Terminala w instancji notatek:
Utwórz nowy katalog o nazwie vertex-codelab
i umieść w nim dysk CD.
mkdir vertex-codelab
cd vertex-codelab
Aby utworzyć katalog dla kodu szkoleniowego i plik Pythona, w którym dodasz kod, wykonaj te czynności:
mkdir trainer
touch trainer/task.py
W katalogu vertex-codelab
powinien teraz znajdować się ten plik:
+ trainer/
+ task.py
Następnie otwórz utworzony plik task.py
i wklej cały kod podany poniżej.
import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune
import os
NUM_EPOCHS = 10
BATCH_SIZE = 64
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(batch_size):
'''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(batch_size)
# Create validation dataset
validation_data = data['test'].map(preprocess_data)
validation_data = validation_data.batch(batch_size)
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()
# Create distribution strategy
strategy = tf.distribute.MirroredStrategy()
# Get data
GLOBAL_BATCH_SIZE = BATCH_SIZE * strategy.num_replicas_in_sync
train_data, validation_data = create_dataset(GLOBAL_BATCH_SIZE)
# Wrap variable creation within strategy scope
with strategy.scope():
model = create_model(args.num_units, args.learning_rate, args.momentum)
# Train model
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()
Przyjrzyjmy się bliżej kodom i składnikom związanym z rozproszonym trenowaniem i dostrajaniem hiperparametrów.
Trenowanie rozproszone
- W funkcji
main()
tworzony jest obiektMirroredStrategy
. Następnie dodajesz zmienne modelu do zakresu strategii. Ten krok informuje TensorFlow, które zmienne powinny być lustrzanymi odbiciami na kartach GPU. - Wielkość wsadu jest zwiększana o
num_replicas_in_sync
. Skalowanie rozmiaru wsadu jest sprawdzoną metodą w przypadku korzystania ze strategii synchronicznego równoległości danych w TensorFlow. Więcej informacji znajdziesz tutaj
Dostrajanie hiperparametrów
- Skrypt importuje bibliotekę
hypertune
. Podczas kompilowania obrazu kontenera musimy się upewnić, że ta biblioteka została zainstalowana. - 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 ustawiania odpowiedniego hiperparametru w kodzie (np. setlearning_rate = args.learning_rate
). - Na końcu funkcji
main()
bibliotekahypertune
służy do definiowania danych, które chcesz optymalizować. W TensorFlow metoda Kerasmodel.fit
zwraca obiektHistory
. AtrybutHistory.history
to rekord wartości utraty i wartości danych w kolejnych epokach. Jeśli przekażesz dane weryfikacyjne domodel.fit
, atrybutHistory.history
będzie też zawierał wartości utracone podczas weryfikacji i wartości wskaźników. Jeśli na przykład trenujesz model przez 3 epoki z danymi walidacyjnymi i podajesz jako daneaccuracy
, atrybutHistory.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.
6. Konteneryzowanie kodu
Pierwszym krokiem w konteneryzacji kodu jest utworzenie pliku Dockerfile. W pliku Dockerfile musisz uwzględnić wszystkie polecenia potrzebne do uruchomienia obrazu. Zainstaluje wszystkie niezbędne biblioteki i skonfiguruje punkt wejścia dla kodu trenowania.
Krok 1. Zapisz plik Dockerfile
W terminalu sprawdź, czy jesteś w katalogu vertex-codelab
, i utwórz pusty plik Dockerfile:
touch Dockerfile
W katalogu vertex-codelab
powinien teraz znajdować się ten plik:
+ Dockerfile
+ trainer/
+ task.py
Otwórz plik Dockerfile i wklej do niego ten kod:
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 używa obrazu Dockera TensorFlow Enterprise 2.7 na potrzeby głębokiego uczenia się na GPU. Kontenery do głębokiego uczenia się w Google Cloud są dostarczane z wstępnie zainstalowanymi popularnymi platformami do tworzenia systemów uczących się i narzędzi do analizy danych. Po pobraniu tego obrazu plik Dockerfile konfiguruje punkt wejścia dla kodu trenowania.
Krok 2. 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'
Zdefiniuj zmienną z identyfikatorem URI obrazu kontenera w Google Container Registry:
IMAGE_URI="gcr.io/$PROJECT_ID/horse-human-codelab:latest"
Konfigurowanie Dockera
gcloud auth configure-docker
Następnie utwórz kontener, uruchamiając to polecenie w katalogu głównym vertex-codelab
:
docker build ./ -t $IMAGE_URI
Na koniec prześlij go do Google Container Registry:
docker push $IMAGE_URI
Krok 3. Utwórz zasobnik Cloud Storage
W naszym zadaniu treningowym podamy ścieżkę do zasobnika stagingowego.
Aby utworzyć nowy zasobnik w projekcie, uruchom w terminalu to polecenie:
BUCKET_NAME="gs://${PROJECT_ID}-hptune-bucket"
gsutil mb -l us-central1 $BUCKET_NAME
7. Uruchom zadanie dostrajania hiperparametrów
Krok 1. Utwórz niestandardowe zadanie treningowe z dostrajaniem hiperparametrów
W programie uruchamiającym otwórz nowy notatnik TensorFlow 2.
Zaimportuj pakiet Vertex AI SDK dla Pythona.
from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt
Aby uruchomić zadanie dostrajania hiperparametrów, musisz najpierw zdefiniować element worker_pool_specs
, który określa typ maszyny i obraz Dockera. Poniższa specyfikacja definiuje 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": 2
},
"replica_count": 1,
"container_spec": {
"image_uri": "gcr.io/{PROJECT_ID}/horse-human-codelab:latest"
}
}]
Następnie zdefiniuj element parameter_spec
, który jest słownikiem określającym parametry, które chcesz optymalizować. 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 hiperboliczne mogą być typu Double, Integer, Categorical lub Discrete. Jeśli wybierzesz typ podwójny lub całkowity, musisz podać minimalną i maksymalną wartość. Jeśli wybierzesz opcję Kategoryczna lub Rozłączna, musisz podać wartości. W przypadku typów Double i Integer musisz też podać wartość Scaling. Więcej informacji o wybieraniu najlepszej skali 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.
# Dicionary 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'}
Po zdefiniowaniu specyfikacji utworzysz CustomJob
, czyli typową 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='horses-humans',
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',
custom_job=my_custom_job,
metric_spec=metric_spec,
parameter_spec=parameter_spec,
max_trial_count=6,
parallel_trial_count=2,
search_algorithm=None)
hp_job.run()
Oto kilka argumentów:
- max_trial_count: musisz wyznaczyć górną granicę liczby wersji próbnych, w których usługa będzie działać. 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 używasz równoległych prób, usługa udostępnia wiele klastrów przetwarzania treningu. Zwiększenie liczby równoległych prób skraca czas działania 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.
Po rozpoczęciu zadania możesz śledzić jego stan w interfejsie na karcie ZADANIE DOSTRAJANIA HIPERPARAMETRÓW.
Po zakończeniu zadania możesz wyświetlić i posortować wyniki prób, aby znaleźć najlepszą kombinację wartości hiperparametrów.
🎉 Gratulacje! 🎉
Poznałeś/poznałaś już te sposoby korzystania z Vertex AI:
- Uruchamianie zadania dostrajania hiperparametrów z wykorzystaniem rozproszonego treningu
Więcej informacji o różnych elementach Vertex AI znajdziesz w dokumentacji.
8. 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ę, w konsoli Vertex AI Workbench kliknij przycisk Zatrzymaj. Jeśli chcesz całkowicie usunąć zeszyt, kliknij przycisk Usuń.
Aby usunąć zasobnik Cloud Storage, w menu nawigacyjnym konsoli Cloud przejdź do usługi Storage, wybierz zasobnik i kliknij Usuń: