1. Omówienie
W tym module wykonasz pełny przepływ pracy trenowania ML w Google Cloud i wykorzystasz PyTorcha do utworzenia modelu. W środowisku notatników Cloud AI Platform dowiesz się, jak przygotować pakiet zadania treningowego, aby móc je uruchamiać w AI Platform Training za pomocą dostrajania hiperparametrów.
Czego się dowiesz
Poznasz takie zagadnienia jak:
- Tworzenie instancji notatek w AI Platform
- Tworzenie modelu PyTorch
- Wytrenuj model za pomocą dostrajania hiperparametrów w AI Platform trenowanie
Całkowity koszt uruchomienia tego modułu w Google Cloud wynosi około 1 USD.
2. 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 Cloud AI Platform Models API
Przejdź do sekcji Modele AI Platform w konsoli Cloud i kliknij Włącz, jeśli ta opcja nie jest jeszcze włączona.
Krok 2. 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 3. Utwórz instancję Notatników w AI Platform
Przejdź do sekcji Notatników AI Platform w konsoli Cloud i kliknij Nowa instancja. Następnie wybierz najnowszy typ instancji PyTorch (bez GPU):
Użyj opcji domyślnych lub, jeśli chcesz, nadaj mu nazwę niestandardową, a następnie kliknij Utwórz. Po utworzeniu instancji wybierz Otwórz JupyterLab:
Następnie w programie uruchamiającym otwórz instancję notatnika w Pythonie 3:
Możesz zaczynać!
Krok 5. Zaimportuj pakiety Pythona
W pierwszej komórce notatnika dodaj poniższe importy i uruchom komórkę. Aby go uruchomić, naciśnij przycisk ze strzałką w prawo w górnym menu lub naciśnij Command i Enter:
import datetime
import numpy as np
import os
import pandas as pd
import time
Zauważysz, że w tym miejscu nie importujemy PyTorch. Wynika to z faktu, że uruchamiamy zadanie trenowania w ramach trenowania AI Platform, a nie z naszej instancji notatnika.
3. Utwórz pakiet dla zadania trenowania
Aby uruchomić zadanie trenowania w AI Platform Training, potrzebujemy kodu trenowania umieszczonego lokalnie w instancji Notatników, a także zasobnika Cloud Storage, w którym będą przechowywane zasoby tego zadania. Najpierw utworzymy zasobnik na dane. Jeśli masz już taki kod, możesz pominąć ten krok.
Krok 1. Utwórz zasobnik Cloud Storage dla naszego modelu
Najpierw zdefiniujmy kilka zmiennych środowiskowych, których będziemy używać w dalszej części tego ćwiczenia. W poniższych wartościach wpisz nazwę projektu Google Cloud i nazwę zasobnika Cloud Storage, który chcesz utworzyć (musi być globalnie unikalna):
# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'
Teraz możemy utworzyć zasobnik na dane, o który wspomnimy, kiedy rozpoczniemy zadanie trenowania.
Aby utworzyć zasobnik, uruchom to polecenie gsutil
z poziomu notatnika:
!gsutil mb $BUCKET_URL
Krok 2. Utwórz pliki początkowe dla pakietu Pythona
Aby uruchomić zadanie trenowania w AI Platform, musimy skonfigurować nasz kod jako pakiet Pythona. Składa się on z pliku setup.py
znajdującego się w naszym katalogu głównym, który określa zewnętrzne zależności pakietów, podkatalogu o nazwie naszego pakietu (nazywamy go trainer/
) oraz pustego pliku __init__.py
w tym podkatalogu.
Najpierw zapiszmy plik setup.py. Aby zapisać plik w naszej instancji, używamy magii iPythona %%writefile. Określiliśmy 3 biblioteki zewnętrzne, których użyjemy w kodzie trenowania: PyTorch, Scikit-learn i Pandas.
%%writefile setup.py
from setuptools import find_packages
from setuptools import setup
REQUIRED_PACKAGES = ['torch>=1.5', 'scikit-learn>=0.20', 'pandas>=1.0']
setup(
name='trainer',
version='0.1',
install_requires=REQUIRED_PACKAGES,
packages=find_packages(),
include_package_data=True,
description='My training application package.'
)
Następnie utworzymy katalog „trener/” i w nim pusty plik init.py. Python używa tego pliku, aby rozpoznać, że jest to pakiet:
!mkdir trainer
!touch trainer/__init__.py
Teraz możesz zacząć tworzyć zadanie treningowe.
4. Wyświetl podgląd zbioru danych
W tym module skupiamy się na narzędziach do trenowania modeli, ale przyjrzyjmy się zbiorowi danych, którego będziemy używać do trenowania naszego modelu. Wykorzystamy zbiór danych przyrodniczy dostępny w BigQuery. Zawierają dane dotyczące narodzin w USA na przestrzeni kilku dekad. Użyjemy kilku kolumn ze zbioru danych, aby przewidywać masę urodzeniową dziecka. Oryginalny zbiór danych jest dość duży i użyjemy jego podzbioru, który Ci udostępniliśmy w zasobniku Cloud Storage.
Krok 1. Pobieranie zbioru danych naturalnych BigQuery
Pobierzmy wersję zbioru danych, którą udostępniliśmy Ci w Cloud Storage, do DataFrame biblioteki Pandas, a następnie wyświetlmy jej podgląd.
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()
Ten zbiór danych ma nieco mniej niż 100 000 wierszy. Do przewidywania masy urodzeniowej dziecka będziemy korzystać z 5 funkcji: wieku matki i ojca, tygodni ciąży, przyrostu wagi matki w kilogramach oraz płci dziecka w postaci wartości logicznej.
5. Zdefiniuj zadanie trenowania za pomocą dostrajania hiperparametrów
Zapiszemy nasz skrypt treningowy w pliku o nazwie model.py w utworzonym wcześniej podkatalogu trenera/. Nasze zadanie trenowania będzie uruchamiane na bazie AI Platform Training i będzie korzystać z usługi dostrajania hiperparametrów AI Platform, aby znaleźć optymalne hiperparametry do naszego modelu z wykorzystaniem optymalizacji Bayesa.
Krok 1. Utwórz skrypt treningowy
Najpierw utwórzmy plik Pythona przy użyciu skryptu treningowego. Potem przeanalizujemy, co się na nim dzieje. Uruchomienie tego polecenia %%writefile spowoduje zapisanie kodu modelu w lokalnym pliku Pythona:
%%writefile trainer/model.py
import argparse
import hypertune
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.utils import shuffle
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import normalize
def get_args():
"""Argument parser.
Returns:
Dictionary of arguments.
"""
parser = argparse.ArgumentParser(description='PyTorch MNIST')
parser.add_argument('--job-dir', # handled automatically by AI Platform
help='GCS location to write checkpoints and export ' \
'models')
parser.add_argument('--lr', # Specified in the config file
type=float,
default=0.01,
help='learning rate (default: 0.01)')
parser.add_argument('--momentum', # Specified in the config file
type=float,
default=0.5,
help='SGD momentum (default: 0.5)')
parser.add_argument('--hidden-layer-size', # Specified in the config file
type=int,
default=8,
help='hidden layer size')
args = parser.parse_args()
return args
def train_model(args):
# Get the data
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality = natality.dropna()
natality = shuffle(natality, random_state = 2)
natality.head()
natality_labels = natality['weight_pounds']
natality = natality.drop(columns=['weight_pounds'])
train_size = int(len(natality) * 0.8)
traindata_natality = natality[:train_size]
trainlabels_natality = natality_labels[:train_size]
testdata_natality = natality[train_size:]
testlabels_natality = natality_labels[train_size:]
# Normalize and convert to PT tensors
normalized_train = normalize(np.array(traindata_natality.values), axis=0)
normalized_test = normalize(np.array(testdata_natality.values), axis=0)
train_x = torch.Tensor(normalized_train)
train_y = torch.Tensor(np.array(trainlabels_natality))
test_x = torch.Tensor(normalized_test)
test_y = torch.Tensor(np.array(testlabels_natality))
# Define our data loaders
train_dataset = torch.utils.data.TensorDataset(train_x, train_y)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_dataset = torch.utils.data.TensorDataset(test_x, test_y)
test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)
# Define the model, while tuning the size of our hidden layer
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
criterion = nn.MSELoss()
# Tune hyperparameters in our optimizer
optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
epochs = 20
for e in range(epochs):
for batch_id, (data, label) in enumerate(train_dataloader):
optimizer.zero_grad()
y_pred = model(data)
label = label.view(-1,1)
loss = criterion(y_pred, label)
loss.backward()
optimizer.step()
val_mse = 0
num_batches = 0
# Evaluate accuracy on our test set
with torch.no_grad():
for i, (data, label) in enumerate(test_dataloader):
num_batches += 1
y_pred = model(data)
mse = criterion(y_pred, label.view(-1,1))
val_mse += mse.item()
avg_val_mse = (val_mse / num_batches)
# Report the metric we're optimizing for to AI Platform's HyperTune service
# In this example, we're mimizing error on our test set
hpt = hypertune.HyperTune()
hpt.report_hyperparameter_tuning_metric(
hyperparameter_metric_tag='val_mse',
metric_value=avg_val_mse,
global_step=epochs
)
def main():
args = get_args()
print('in main', args)
train_model(args)
if __name__ == '__main__':
main()
Zadanie szkoleniowe obejmuje 2 funkcje, które obejmują większość pracy.
get_args()
: analizuje argumenty wiersza poleceń przekazywane podczas tworzenia zadania treningowego, wraz z hiperparametrami, które mają być optymalizowane przez AI Platform. W tym przykładzie nasza lista argumentów zawiera tylko hiperparametry, które będziemy optymalizować – tempo uczenia się, pęd naszego modelu i liczbę neuronów w ukrytej warstwie.train_model()
: pobieramy tu dane do ramki DataFrame Pandas, normalizujemy je, konwertujemy na procesory PyTorch Tensor, a potem definiujemy nasz model. Do tworzenia modelu używamy interfejsu API PyTorchnn.Sequential
, który pozwala zdefiniować model jako stos warstw:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
Zwróć uwagę, że zamiast umieszczać na stałe rozmiar ukrytej warstwy naszego modelu, tworzymy go jako hiperparametr, który AI Platform dostroi. Więcej informacji na ten temat znajdziesz w następnej sekcji.
Krok 2. Korzystanie z usługi dostrajania hiperparametrów AI Platform
Zamiast ręcznie wypróbowywać różne wartości hiperparametrów i za każdym razem trenować model ponownie, użyjemy usługi optymalizacji hiperparametrów w Cloud AI Platform. Jeśli skonfigurujemy zadanie treningowe z argumentami hiperparametrów, AI Platform użyje optymalizacji Baidu, aby znaleźć idealne wartości dla określonych przez nas hiperparametrów.
Przy dostrajaniu hiperparametrów jedna próba składa się z jednego uruchomienia modelu treningowego z określoną kombinacją wartości hiperparametrów. W zależności od liczby przeprowadzonych prób AI Platform wykorzysta wyniki zakończonych prób, aby zoptymalizować wybrane hiperparametry w kolejnych. Aby skonfigurować dostrajanie hiperparametrów, rozpoczynając zadanie trenowania, musimy przekazać plik konfiguracyjny z danymi o każdym z optymalizacji hiperparametrów.
Następnie utwórz lokalnie plik konfiguracyjny:
%%writefile config.yaml
trainingInput:
hyperparameters:
goal: MINIMIZE
maxTrials: 10
maxParallelTrials: 5
hyperparameterMetricTag: val_mse
enableTrialEarlyStopping: TRUE
params:
- parameterName: lr
type: DOUBLE
minValue: 0.0001
maxValue: 0.1
scaleType: UNIT_LINEAR_SCALE
- parameterName: momentum
type: DOUBLE
minValue: 0.0
maxValue: 1.0
scaleType: UNIT_LINEAR_SCALE
- parameterName: hidden-layer-size
type: INTEGER
minValue: 8
maxValue: 32
scaleType: UNIT_LINEAR_SCALE
Dla każdego hiperparametru określamy jego typ, zakres wartości do wyszukania oraz skalę, do której należy zwiększyć wartość w różnych próbach.
Na początku pracy określamy też wskaźnik, pod kątem którego optymalizujemy kampanię. Zwróć uwagę, że pod koniec powyższej funkcji train_model()
zgłaszamy te dane do AI Platform po każdym zakończeniu okresu próbnego. Tutaj minimalizujemy błąd średniej kwadratowej wartości naszego modelu i chcemy używać hiperparametrów, które dają najniższy błąd średniokwadratowy. Nazwa tych danych (val_mse
) jest zgodna z nazwą używaną do raportowania, gdy pod koniec okresu próbnego wywołujemy funkcję report_hyperparameter_tuning_metric()
.
6. Uruchom zadanie trenowania w AI Platform
W tej sekcji rozpoczniemy zadanie trenowania modelu, dostrajając hiperparametry w AI Platform.
Krok 1. Zdefiniuj zmienne środowiskowe
Najpierw zdefiniujmy zmienne środowiskowe, których użyjemy do rozpoczęcia pracy nad naszym trenowaniem. Jeśli chcesz uruchomić zadanie w innym regionie, zaktualizuj zmienną REGION poniżej:
MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"
Każde zadanie trenowania w AI Platform powinno mieć unikalną nazwę. Uruchom to polecenie, aby zdefiniować zmienną nazwy zadania za pomocą sygnatury czasowej:
timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))
Krok 2. Rozpocznij szkolenie
Utworzymy zadanie treningowe za pomocą gcloud – Google Cloud CLI. Możemy uruchomić to polecenie bezpośrednio w notatniku, odwołując się do zmiennych zdefiniowanych powyżej:
!gcloud ai-platform jobs submit training $JOB_NAME \
--scale-tier basic \
--package-path $TRAIN_DIR \
--module-name $MAIN_TRAINER_MODULE \
--job-dir $JOB_DIR \
--region $REGION \
--runtime-version 2.1 \
--python-version 3.7 \
--config config.yaml
Jeśli zadanie zostało utworzone prawidłowo, przejdź do sekcji Zadania w konsoli AI Platform, aby monitorować logi.
Krok 3. Monitoruj zadanie
W sekcji Zadania w konsoli kliknij zadanie, które właśnie się rozpoczęło, aby wyświetlić szczegóły:
Po rozpoczęciu pierwszej rundy testów zobaczysz wartości hiperparametrów wybrane dla każdej próby:
Po zakończeniu testów w tym miejscu będzie zapisywana wartość Twojego wskaźnika optymalizacji (w tym przypadku val_mse
). Uruchomienie zadania powinno zająć 15–20 minut, a po zakończeniu zadania panel będzie wyglądać mniej więcej tak (dokładne wartości mogą się różnić):
Aby debugować potencjalne problemy i dokładnie monitorować zadanie, kliknij Wyświetl logi na stronie z informacjami o zadaniu:
Tutaj będą wyświetlane wszystkie instrukcje print()
w kodzie trenowania modelu. Jeśli napotkasz jakieś problemy, spróbuj dodać więcej instrukcji drukowanych i rozpocząć nowe zadanie trenowania.
Po zakończeniu zadania trenowania znajdź hiperparametry, które dały najniższą wartość parametru val_mse. Możesz ich użyć do trenowania i wyeksportowania ostatecznej wersji modelu lub użyć ich jako wskazówek przy rozpoczęciu innego zadania trenowania z dodatkowymi próbami dostrajania hiperparametrów.
7. Czyszczenie
Jeśli chcesz nadal korzystać z tego notatnika, zalecamy wyłączenie go, gdy nie jest używany. W interfejsie notatników w konsoli Cloud wybierz notatnik, a następnie kliknij Zatrzymaj:
Jeśli chcesz usunąć wszystkie zasoby utworzone w tym module, po prostu usuń instancję notatnika, zamiast ją zatrzymywać.
Za pomocą menu nawigacyjnego w konsoli Cloud przejdź do Cloud Storage i usuń oba zasobniki utworzone w celu przechowywania zasobów modelu.