1. Übersicht
In diesem Lab erfahren Sie, wie Sie Vertex AI für die Hyperparameter-Abstimmung und verteiltes Training verwenden. In diesem Lab wird TensorFlow für den Modellcode verwendet. Die Konzepte lassen sich aber auch auf andere ML-Frameworks anwenden.
Lerninhalte
Die folgenden Themen werden behandelt:
- Modell mit verteiltem Training in einem benutzerdefinierten Container trainieren
- Mehrere Tests Ihres Trainingscodes für die automatisierte Hyperparameter-Abstimmung starten
Die Gesamtkosten für das Lab in Google Cloud betragen etwa $6.
2. Einführung in Vertex AI
In diesem Lab wird das neueste KI-Produktangebot von Google Cloud verwendet. Vertex AI bindet die ML-Angebote in Google Cloud in eine nahtlose Entwicklungsumgebung ein. Zuvor waren mit AutoML trainierte und benutzerdefinierte Modelle über separate Dienste zugänglich. Das neue Angebot vereint beides in einer einzigen API sowie weitere neue Produkte. Sie können auch vorhandene Projekte zu Vertex AI migrieren. Wenn Sie uns Feedback geben möchten, besuchen Sie die Supportseite.
Vertex AI enthält viele verschiedene Produkte zur Unterstützung von End-to-End-ML-Workflows. In diesem Lab konzentrieren wir uns auf Training und Workbench.
3. Anwendungsfall – Übersicht
In diesem Lab ermitteln Sie mithilfe der Hyperparameter-Abstimmung optimale Parameter für ein Bildklassifizierungsmodell, das mit dem Pferde- oder Mensch-Dataset aus TensorFlow-Datasets trainiert wurde.
Hyperparameter-Abstimmung
Bei der Hyperparameter-Abstimmung mit Vertex AI Training werden mehrere Tests Ihrer Trainingsanwendung mit Werten für Ihre ausgewählten Hyperparameter innerhalb der von Ihnen festgelegten Limits ausgeführt. Vertex AI verfolgt die Ergebnisse jedes Tests und nimmt Anpassungen für nachfolgende Tests vor.
Wenn Sie die Hyperparameter-Abstimmung mit Vertex AI Training verwenden möchten, müssen Sie zwei Änderungen an Ihrem Trainingscode vornehmen:
- Definieren Sie in Ihrem Haupttrainingsmodul für jeden Hyperparameter, den Sie abstimmen möchten, ein Befehlszeilenargument.
- Verwenden Sie den mit diesen Argumenten übergebenen Wert, um den entsprechenden Hyperparameter im Code Ihrer Anwendung festzulegen.
Verteiltes Training
Wenn Sie eine einzelne GPU haben, verwendet TensorFlow diesen Beschleuniger, um das Modelltraining ohne zusätzlichen Aufwand für Sie zu beschleunigen. Wenn Sie jedoch durch die Verwendung mehrerer GPUs zusätzliche Leistung erzielen möchten, müssen Sie tf.distribute
verwenden. Das Modul von TensorFlow ist das Modul zur Ausführung einer Berechnung auf mehreren Geräten.
In diesem Lab wird tf.distribute.MirroredStrategy
verwendet, das Sie mit nur wenigen Codeänderungen Ihren Trainingsanwendungen hinzufügen können. Mit dieser Strategie wird eine Kopie des Modells auf jeder GPU auf Ihrem Computer erstellt. Die nachfolgenden Gradientenaktualisierungen erfolgen synchron. Dies bedeutet, dass jede GPU den Vor- und Rückwärtsdurchlauf durch das Modell anhand eines anderen Segments der Eingabedaten berechnet. Die berechneten Gradienten aus jedem dieser Segmente werden dann über alle GPUs aggregiert und in einem als All-Reduce bezeichneten Prozess gemittelt. Modellparameter werden mithilfe dieser gemittelten Farbverläufe aktualisiert.
Die Details sind für dieses Lab nicht erforderlich, aber wenn Sie mehr darüber erfahren möchten, wie verteiltes Training in TensorFlow funktioniert, sehen Sie sich das folgende Video an:
4. Umgebung einrichten
Sie benötigen ein Google Cloud Platform-Projekt mit aktivierter Abrechnung, um dieses Codelab auszuführen. Folgen Sie dieser Anleitung, um ein Projekt zu erstellen.
Schritt 1: Compute Engine API aktivieren
Gehen Sie zu Compute Engine und wählen Sie Aktivieren aus, falls dies noch nicht geschehen ist.
Schritt 2: Container Registry API aktivieren
Rufen Sie Container Registry auf und wählen Sie Aktivieren aus, falls noch nicht geschehen. Damit erstellen Sie einen Container für Ihren benutzerdefinierten Trainingsjob.
Schritt 3: Vertex AI API aktivieren
Rufen Sie den Bereich Vertex AI in der Cloud Console auf und klicken Sie auf Vertex AI API aktivieren.
Schritt 4: Vertex AI Workbench-Instanz erstellen
Klicken Sie im Bereich Vertex AI der Cloud Console auf Workbench:
Aktivieren Sie die Notebooks API, falls noch nicht geschehen.
Klicken Sie nach der Aktivierung auf VERWALTETE NOTEBOOKS:
Wählen Sie dann NEUES NOTEBOOK aus.
Geben Sie Ihrem Notebook einen Namen und klicken Sie auf Erweiterte Einstellungen.
Aktivieren Sie unter „Erweiterte Einstellungen“ das Herunterfahren bei Inaktivität und legen Sie die Anzahl der Minuten auf 60 fest. Das bedeutet, dass Ihr Notebook bei Nichtgebrauch automatisch heruntergefahren wird, sodass Ihnen keine unnötigen Kosten entstehen.
Wähle unter „Sicherheit“ die Option „Terminal aktivieren“ aus. falls es noch nicht aktiviert ist.
Alle anderen erweiterten Einstellungen können Sie unverändert lassen.
Klicken Sie dann auf Erstellen. Die Bereitstellung der Instanz kann einige Minuten dauern.
Nachdem die Instanz erstellt wurde, wählen Sie JupyterLab öffnen aus.
Wenn Sie zum ersten Mal eine neue Instanz verwenden, werden Sie zur Authentifizierung aufgefordert. Folgen Sie dazu den Schritten in der Benutzeroberfläche.
5. Trainingscode schreiben
Öffnen Sie dazu im Launcher-Menü ein Terminalfenster in Ihrer Notebookinstanz:
Erstellen Sie ein neues Verzeichnis mit dem Namen vertex-codelab
und fügen Sie es mit cd ein.
mkdir vertex-codelab
cd vertex-codelab
Führen Sie den folgenden Befehl aus, um ein Verzeichnis für den Trainingscode und eine Python-Datei zu erstellen, in die Sie den Code einfügen:
mkdir trainer
touch trainer/task.py
In Ihrem vertex-codelab
-Verzeichnis sollte nun Folgendes vorhanden sein:
+ trainer/
+ task.py
Öffnen Sie als Nächstes die Datei task.py
, die Sie gerade erstellt haben, und fügen Sie den gesamten unten stehenden Code ein.
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()
Werfen wir nun einen genaueren Blick auf den Code und die spezifischen Komponenten für verteiltes Training und Hyperparameter-Abstimmung.
Verteiltes Training
- In der
main()
-Funktion wird dasMirroredStrategy
-Objekt erstellt. Als Nächstes schließen Sie die Erstellung Ihrer Modellvariablen in den Bereich der Strategie ein. In diesem Schritt wird TensorFlow mitgeteilt, welche Variablen in den GPUs gespiegelt werden sollen. - Die Batchgröße wird um
num_replicas_in_sync
hochskaliert. Das Skalieren der Batchgröße ist eine Best Practice bei der Verwendung von Strategien zur synchronen Datenparallelität in TensorFlow. Weitere Informationen
Hyperparameter-Abstimmung
- Das Skript importiert die
hypertune
-Bibliothek. Wenn wir später das Container-Image erstellen, müssen wir sicherstellen, dass diese Bibliothek installiert wird. - Die Funktion
get_args()
definiert ein Befehlszeilenargument für jeden Hyperparameter, den Sie abstimmen möchten. In diesem Beispiel sind die abgestimmten Hyperparameter die Lernrate, der Impulswert im Optimierungstool und die Anzahl der Einheiten in der letzten verborgenen Schicht des Modells. Sie können aber gerne mit anderen experimentieren. Der mit diesen Argumenten übergebene Wert wird dann verwendet, um den entsprechenden Hyperparameter im Code festzulegen (z. B.learning_rate = args.learning_rate
). - Am Ende der Funktion
main()
wird die Bibliothekhypertune
verwendet, um den Messwert zu definieren, den Sie optimieren möchten. In TensorFlow gibt die Keras-Methodemodel.fit
einHistory
-Objekt zurück. Das AttributHistory.history
ist ein Datensatz mit Trainingsverlustwerten und -messwerten in aufeinanderfolgenden Epochen. Wenn Sie Validierungsdaten anmodel.fit
übergeben, enthält das AttributHistory.history
auch Validierungsverlust und Messwerte. Wenn Sie beispielsweise ein Modell über drei Epochen mit Validierungsdaten trainiert undaccuracy
als Messwert angegeben haben, sieht dasHistory.history
-Attribut wie im folgenden Wörterbuch aus.
{
"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
]
Wenn Sie möchten, dass der Hyperparameter-Abstimmungsdienst die Werte erkennt, die die Validierungsgenauigkeit des Modells maximieren, definieren Sie den Messwert als letzten Eintrag (oder NUM_EPOCS - 1
) der val_accuracy
-Liste. Übergeben Sie diesen Messwert dann an eine Instanz von HyperTune
. Sie können für hyperparameter_metric_tag
einen beliebigen String auswählen, müssen den String aber später noch einmal verwenden, wenn Sie den Hyperparameter-Abstimmungsjob starten.
6. Code containerisieren
Der erste Schritt bei der Containerisierung Ihres Codes besteht darin, ein Dockerfile zu erstellen. In das Dockerfile geben Sie alle Befehle ein, die zum Ausführen des Images erforderlich sind. Damit werden alle erforderlichen Bibliotheken installiert und der Einstiegspunkt für den Trainingscode eingerichtet.
Schritt 1: Dockerfile schreiben
Prüfen Sie im Terminal, ob Sie sich im Verzeichnis vertex-codelab
befinden, und erstellen Sie ein leeres Dockerfile:
touch Dockerfile
In Ihrem vertex-codelab
-Verzeichnis sollte nun Folgendes vorhanden sein:
+ Dockerfile
+ trainer/
+ task.py
Öffnen Sie das Dockerfile und kopieren Sie Folgendes hinein:
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"]
Dieses Dockerfile verwendet das Deep Learning Container TensorFlow Enterprise 2.7 GPU Docker-Image. In den Deep-Learning-Containern in Google Cloud sind viele gängige ML- und Data-Science-Frameworks vorinstalliert. Nach dem Herunterladen des Images richtet dieses Dockerfile den Einstiegspunkt für den Trainingscode ein.
Schritt 2: Container erstellen
Führen Sie im Terminal den folgenden Befehl aus, um eine Umgebungsvariable für Ihr Projekt zu definieren. Ersetzen Sie dabei your-cloud-project
durch die ID Ihres Projekts:
PROJECT_ID='your-cloud-project'
Definieren Sie in Google Container Registry eine Variable mit dem URI Ihres Container-Images:
IMAGE_URI="gcr.io/$PROJECT_ID/horse-human-codelab:latest"
Docker konfigurieren
gcloud auth configure-docker
Erstellen Sie dann den Container, indem Sie im Stammverzeichnis Ihres vertex-codelab
-Verzeichnisses Folgendes ausführen:
docker build ./ -t $IMAGE_URI
Übertragen Sie die Datei abschließend per Push in Google Container Registry:
docker push $IMAGE_URI
Schritt 3: Cloud Storage-Bucket erstellen
In unserem Trainingsjob übergeben Sie den Pfad zu einem Staging-Bucket.
Führen Sie in Ihrem Terminal den folgenden Befehl aus, um einen neuen Bucket in Ihrem Projekt zu erstellen.
BUCKET_NAME="gs://${PROJECT_ID}-hptune-bucket"
gsutil mb -l us-central1 $BUCKET_NAME
7. Hyperparameter-Abstimmungsjob starten
Schritt 1: Benutzerdefinierten Trainingsjob mit Hyperparameter-Abstimmung erstellen
Öffnen Sie im Launcher ein neues TensorFlow 2-Notebook.
Importieren Sie das Vertex AI Python SDK.
from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt
Um den Hyperparameter-Abstimmungsjob zu starten, müssen Sie zuerst die worker_pool_specs
definieren, die den Maschinentyp und das Docker-Image angibt. In der folgenden Spezifikation wird eine Maschine mit zwei NVIDIA Tesla V100-GPUs definiert.
Sie müssen {PROJECT_ID}
in image_uri
durch Ihr Projekt ersetzen.
# 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"
}
}]
Definieren Sie als Nächstes das parameter_spec
. Dabei handelt es sich um ein Wörterbuch, in dem die zu optimierenden Parameter angegeben werden. Der Wörterbuchschlüssel ist der String, den Sie dem Befehlszeilenargument für jeden Hyperparameter zugewiesen haben, und der Wörterbuchwert ist die Parameterspezifikation.
Für jeden Hyperparameter müssen Sie den Typ sowie die Grenzen für die Werte definieren, die der Abstimmungsdienst versucht. Hyperparameter können vom Typ „Double“, „Integer“, „Categorical“ oder „Discrete“ sein. Wenn Sie den Typ "Double" oder "Integer" auswählen, müssen Sie einen Mindest- und Höchstwert angeben. Wenn Sie „Kategorial“ oder „Diskret“ auswählen, müssen Sie die Werte angeben. Für die Typen Double und Integer müssen Sie außerdem den Skalierungswert angeben. In diesem Video erfährst du mehr darüber, wie du die beste Skalierung auswählst.
# 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)
}
Die letzte zu definierende Spezifikation ist metric_spec
. Dies ist ein Wörterbuch, das den zu optimierenden Messwert darstellt. Der Wörterbuchschlüssel ist die hyperparameter_metric_tag
, die Sie in Ihrem Trainingsanwendungscode festlegen, und der Wert ist das Optimierungsziel.
# 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'}
Sobald die Spezifikationen definiert sind, erstellen Sie eine CustomJob
. Dies ist die allgemeine Spezifikation, die zum Ausführen Ihres Jobs in jedem Hyperparameter-Abstimmungstest verwendet wird.
Sie müssen {YOUR_BUCKET}
durch den Bucket ersetzen, den Sie zuvor erstellt haben.
# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans',
worker_pool_specs=worker_pool_specs,
staging_bucket='gs://{YOUR_BUCKET}')
Erstellen Sie dann den HyperparameterTuningJob
und führen Sie ihn aus.
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()
Hier sind einige Argumente:
- max_trial_count: Sie müssen die Anzahl der Tests, die der Dienst ausführen wird, begrenzen. Mehr Testläufe führen in der Regel zu besseren Ergebnissen, allerdings werden die Ergebnisse ab einem bestimmten Zeitpunkt zurückgehen. Weitere Tests haben anschließend nur wenig oder keinen Einfluss auf den Messwert, den Sie optimieren möchten. Es empfiehlt sich, mit einer kleineren Anzahl von Tests zu beginnen und ein Gefühl dafür zu bekommen, wie wirkungsvoll die ausgewählten Hyperparameter sind, bevor Sie hochskalieren.
- parallel_trial_count: Wenn Sie parallele Tests verwenden, stellt der Dienst mehrere Trainingsverarbeitungscluster bereit. Wenn Sie die Anzahl der parallelen Tests erhöhen, verringert sich die Ausführungszeit des Hyperparameter-Abstimmungsjobs. kann jedoch die Effektivität des Jobs insgesamt reduzieren. Das liegt daran, dass die Standardabstimmungsstrategie Ergebnisse früherer Tests für die Zuweisung von Werten in nachfolgenden Tests verwendet.
- search_algorithm: Sie können den Suchalgorithmus auf die Raster-, die Zufalls- oder die Standardeinstellung (Keiner) einstellen. Bei der Standardoption wird die Bayes'sche Optimierung angewendet, um den Bereich möglicher Hyperparameter-Werte zu durchsuchen. Dies ist der empfohlene Algorithmus. Weitere Informationen zu diesem Algorithmus
Sobald der Job gestartet wird, können Sie den Status in der Benutzeroberfläche auf dem Tab HYPERPARAMETER-FUNINGJOBS verfolgen.
Sobald der Job abgeschlossen ist, können Sie die Ergebnisse Ihrer Tests anzeigen und sortieren, um die beste Kombination von Hyperparameter-Werten zu ermitteln.
🎉 Glückwunsch! 🎉
Sie haben gelernt, wie Sie mit Vertex AI Folgendes tun können:
- Hyperparameter-Abstimmungsjob mit verteiltem Training ausführen
Weitere Informationen zu den verschiedenen Teilen von Vertex AI finden Sie in der Dokumentation.
8. Bereinigen
Da wir das Notebook so konfiguriert haben, dass nach 60 Minuten Inaktivität eine Zeitüberschreitung auftritt, müssen wir uns nicht um das Herunterfahren der Instanz kümmern. Wenn Sie die Instanz manuell herunterfahren möchten, klicken Sie in der Console im Abschnitt Vertex AI Workbench auf die Schaltfläche „Stop“. Wenn Sie das Notizbuch vollständig löschen möchten, klicken Sie auf Löschen.
Wenn Sie den Storage-Bucket löschen möchten, gehen Sie im Navigationsmenü der Cloud Console zu „Storage“, wählen Sie den Bucket aus und klicken Sie auf „Löschen“: