1. Présentation
Dans cet atelier, vous allez suivre un workflow complet d'entraînement de ML sur Google Cloud en utilisant PyTorch pour créer votre modèle. Dans un environnement Cloud AI Platform Notebooks, vous allez apprendre à empaqueter votre job d'entraînement pour l'exécuter sur AI Platform Training avec des réglages d'hyperparamètres.
Objectifs de l'atelier
Vous allez apprendre à effectuer les opérations suivantes :
- Créer une instance AI Platform Notebooks
- Créer un modèle PyTorch
- Entraîner votre modèle avec le réglage des hyperparamètres sur AI Platform Training
Le coût total d'exécution de cet atelier sur Google Cloud est d'environ 1 $.
2. Configurer votre environnement
Pour suivre cet atelier de programmation, vous aurez besoin d'un projet Google Cloud Platform dans lequel la facturation est activée. Pour créer un projet, suivez ces instructions.
Étape 1: Activez l'API Cloud AI Platform Models
Accédez à la section Modèles AI Platform de Cloud Console, puis cliquez sur "Activer" si elle n'est pas déjà activée.
Étape 2: Activez l'API Compute Engine
Accédez à Compute Engine et cliquez sur Activer si ce n'est pas déjà fait. Vous en aurez besoin pour créer votre instance de notebook.
Étape 3: Créez une instance AI Platform Notebooks
Accédez à la section AI Platform Notebooks de la console Cloud, puis cliquez sur Nouvelle instance. Sélectionnez ensuite le dernier type d'instance PyTorch (sans GPU):
Utilisez les options par défaut ou donnez-lui un nom personnalisé si vous le souhaitez, puis cliquez sur Créer. Une fois l'instance créée, sélectionnez Ouvrir JupyterLab:
Ensuite, ouvrez une instance de notebook Python 3 à partir du lanceur:
Vous êtes prêt à commencer !
Étape 5: Importez les packages Python
Dans la première cellule de votre notebook, ajoutez les importations suivantes et exécutez la cellule. Vous pouvez l'exécuter en appuyant sur la flèche vers la droite dans le menu supérieur ou en appuyant sur Commande+Entrée:
import datetime
import numpy as np
import os
import pandas as pd
import time
Vous remarquerez que PyTorch n'est pas importé ici. En effet, nous exécutons le job d'entraînement sur AI Platform Training, et non à partir de notre instance de notebook.
3. Créer un package pour le job d'entraînement
Pour exécuter notre job d'entraînement sur AI Platform Training, nous avons besoin du code d'entraînement empaqueté localement dans notre instance Notebooks et d'un bucket Cloud Storage pour stocker les éléments de notre job. Commençons par créer un bucket de stockage. Vous pouvez ignorer cette étape si vous en avez déjà une.
Étape 1: Créez un bucket Cloud Storage pour notre modèle
Commençons par définir certaines variables d'environnement que nous utiliserons tout au long de cet atelier de programmation. Renseignez les valeurs ci-dessous avec le nom de votre projet Google Cloud et le nom du bucket Cloud Storage que vous souhaitez créer (ils doivent être uniques):
# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'
Nous sommes maintenant prêts à créer un bucket de stockage, vers lequel nous indiquerons lorsque nous lancerons le job d'entraînement.
Exécutez la commande gsutil
suivante depuis votre notebook pour créer un bucket:
!gsutil mb $BUCKET_URL
Étape 2: Créez les fichiers initiaux du package Python
Pour exécuter un job d'entraînement sur AI Platform, nous devons configurer notre code en tant que package Python. Il se compose d'un fichier setup.py
dans notre répertoire racine qui spécifie les dépendances de package externes, d'un sous-répertoire portant le nom du package (nous l'appellerons ici trainer/
) et d'un fichier __init__.py
vide dans ce sous-répertoire.
Tout d'abord, écrivons notre fichier setup.py. Nous utilisons les commandes magiques %%writefile d'iPython pour enregistrer le fichier dans notre instance. Dans cet exemple, nous avons indiqué trois bibliothèques externes que nous allons utiliser dans notre code d'entraînement: PyTorch, Scikit-learn et 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.'
)
Créons ensuite notre répertoire trainer/ et le fichier init.py vide qu'il contient. Python utilise ce fichier pour reconnaître qu'il s'agit d'un package:
!mkdir trainer
!touch trainer/__init__.py
Nous sommes maintenant prêts à créer le job d'entraînement.
4. Prévisualiser l'ensemble de données
Cet atelier se concentre sur les outils permettant d'entraîner des modèles, mais examinons rapidement l'ensemble de données qui nous permettra d'entraîner le modèle à comprendre. Nous allons utiliser l'ensemble de données sur la natalité disponible dans BigQuery. Il contient des données sur la naissance provenant des États-Unis sur plusieurs décennies. Nous allons utiliser quelques colonnes de l'ensemble de données pour prédire le poids de naissance d'un bébé. L'ensemble de données d'origine est assez volumineux, et nous allons en utiliser un sous-ensemble que nous avons mis à votre disposition dans un bucket Cloud Storage.
Étape 1: Téléchargez l'ensemble de données BigQuery sur la natalité
Nous allons télécharger la version de l'ensemble de données que nous avons mis à votre disposition dans Cloud Storage dans un DataFrame Pandas et la prévisualiser.
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()
Cet ensemble de données contient un peu moins de 100 000 lignes. Nous allons utiliser cinq caractéristiques pour prédire le poids de naissance d'un bébé: l'âge de la mère et du père, les semaines de grossesse, la prise de poids de la mère en livres et le sexe du bébé représenté sous forme d'une valeur booléenne.
5. Définir le job d'entraînement avec des réglages d'hyperparamètres
Nous allons écrire notre script d'entraînement dans un fichier nommé model.py dans le sous-répertoire trainer/ que nous avons créé précédemment. Notre job d'entraînement sera exécuté sur AI Platform Training et utilisera également le service de réglage des hyperparamètres d'AI Platform pour trouver les hyperparamètres optimaux pour notre modèle à l'aide de l'optimisation bayésienne.
Étape 1: Créez le script d'entraînement
Commençons par créer le fichier Python avec notre script d'entraînement. Ensuite, nous analyserons ce qu'il s'y passe. L'exécution de cette commande %%writefile permet d'écrire le code du modèle dans un fichier Python local:
%%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()
Le job d'entraînement comprend deux fonctions où l'essentiel du travail est effectué.
get_args()
: analyse les arguments de ligne de commande que nous transmettrons lors de la création du job d'entraînement, ainsi que les hyperparamètres que nous voulons qu'AI Platform optimise. Dans cet exemple, notre liste d'arguments n'inclut que les hyperparamètres que nous allons optimiser : le taux d'apprentissage de notre modèle, le momentum et le nombre de neurones dans notre couche cachée.train_model()
: ici, nous téléchargeons les données dans un DataFrame Pandas, nous les normalisons, les convertissons en Tensors PyTorch, puis nous définissons notre modèle. Pour créer notre modèle, nous utilisons l'API PyTorchnn.Sequential
, qui nous permet de définir notre modèle sous la forme d'une pile de couches:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
Notez qu'au lieu de coder en dur la taille de la couche cachée de notre modèle, nous en faisons un hyperparamètre qu'AI Platform réglera pour nous. Vous trouverez plus d'informations à ce sujet dans la section suivante.
Étape 2: Utiliser le service de réglage des hyperparamètres d'AI Platform
Au lieu d'essayer manuellement différentes valeurs d'hyperparamètres et de réentraîner le modèle à chaque fois, nous allons utiliser le service d'optimisation des hyperparamètres de Cloud AI Platform. Si nous configurons notre job d'entraînement avec des arguments d'hyperparamètres, AI Platform utilisera l'optimisation bayésienne pour trouver les valeurs idéales pour les hyperparamètres spécifiés.
Dans le réglage des hyperparamètres, un seul essai consiste en un cycle d'entraînement du modèle avec une combinaison spécifique de valeurs d'hyperparamètres. En fonction du nombre d'essais que nous exécutons, AI Platform utilise les résultats des essais terminés pour optimiser les hyperparamètres qu'il sélectionne pour les futurs essais. Pour configurer le réglage des hyperparamètres, nous devons transmettre un fichier de configuration lorsque nous lançons le job d'entraînement, avec des données sur chacun des hyperparamètres que nous optimisons.
Ensuite, créez ce fichier de configuration localement:
%%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
Pour chaque hyperparamètre, nous spécifions le type, la plage de valeurs à rechercher et l'échelle sur laquelle augmenter la valeur sur différents essais.
Au début de la tâche, nous spécifions également la métrique sur laquelle porte l'optimisation. Notez qu'à la fin de la fonction train_model()
ci-dessus, nous signalons cette métrique à AI Platform chaque fois qu'un essai se termine. Ici, nous minimisons l'erreur quadratique moyenne de notre modèle. Nous voulons donc utiliser les hyperparamètres qui entraînent la plus faible erreur quadratique moyenne pour notre modèle. Le nom de cette métrique (val_mse
) correspond à celui que nous utilisons pour la signaler lorsque nous appelons report_hyperparameter_tuning_metric()
à la fin d'un essai.
6. Exécuter un job d'entraînement sur AI Platform
Dans cette section, nous allons démarrer le job d'entraînement de modèle avec le réglage des hyperparamètres sur AI Platform.
Étape 1: Définissez des variables d'environnement
Commençons par définir certaines variables d'environnement que nous utiliserons pour lancer le job d'entraînement. Si vous souhaitez exécuter votre job dans une autre région, mettez à jour la variable REGION ci-dessous:
MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"
Chaque job d'entraînement sur AI Platform doit avoir un nom unique. Exécutez la commande suivante pour définir une variable pour le nom de votre job à l'aide d'un horodatage:
timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))
Étape 2: Démarrez le job d'entraînement
Nous allons créer notre job d'entraînement à l'aide de gcloud, la Google Cloud CLI. Nous pouvons exécuter cette commande directement dans notre notebook, en faisant référence aux variables que nous avons définies ci-dessus:
!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
Si votre job a été créé correctement, accédez à la section Tâches de la console AI Platform pour surveiller les journaux.
Étape 3: Surveiller votre tâche
Une fois dans la section "Jobs" (Tâches) de la console, cliquez sur le job que vous venez de démarrer pour en afficher les détails:
Au début de votre première série d'essais, vous pouvez voir les valeurs d'hyperparamètres sélectionnées pour chaque essai:
Une fois les essais terminés, la valeur obtenue de votre métrique d'optimisation (dans le cas présent, val_mse
) est enregistrée ici. L'exécution du job devrait prendre entre 15 et 20 minutes. Une fois le job terminé, le tableau de bord ressemblera à ceci (les valeurs exactes pourront varier):
Pour déboguer les problèmes potentiels et surveiller votre job plus en détail, cliquez sur Afficher les journaux sur la page de détails des jobs:
Chaque instruction print()
de votre code d'entraînement de modèle s'affichera ici. Si vous rencontrez des problèmes, essayez d'ajouter d'autres instructions d'impression et de démarrer un nouveau job d'entraînement.
Une fois votre job d'entraînement terminé, recherchez les hyperparamètres ayant généré la valeur val_mse la plus basse. Vous pouvez les utiliser pour entraîner et exporter une version finale de votre modèle, ou les utiliser pour lancer un autre job d'entraînement avec d'autres essais de réglage des hyperparamètres.
7. Nettoyage
Si vous souhaitez continuer à utiliser cet ordinateur portable, nous vous recommandons de le désactiver lorsqu'il n'est pas utilisé. À partir de l'interface utilisateur de Notebooks dans Cloud Console, sélectionnez le notebook, puis cliquez sur Arrêter:
Si vous souhaitez supprimer toutes les ressources que vous avez créées au cours de cet atelier, il vous suffit de supprimer l'instance de notebook au lieu de l'arrêter.
À l'aide du menu de navigation de Cloud Console, accédez à "Storage" (Stockage) et supprimez les deux buckets que vous avez créés pour stocker les ressources de votre modèle.