1. Übersicht
In diesem Lab erfahren Sie, wie Sie Vertex AI für die Hyperparameter-Abstimmung und das verteilte Training verwenden. In diesem Lab wird TensorFlow für den Modellcode verwendet, die Konzepte sind aber auch auf andere ML-Frameworks anwendbar.
Lerninhalte
Die folgenden Themen werden behandelt:
- Modell mit verteiltem Training in einem benutzerdefinierten Container trainieren
- Mehrere Tests Ihres Trainingscodes für die automatische Hyperparameter-Abstimmung starten
Die Gesamtkosten für die Ausführung dieses Labs in Google Cloud betragen etwa 6$.
2. Einführung in Vertex AI
In diesem Lab wird das neueste KI-Produkt von Google Cloud verwendet. Vertex AI vereint die ML-Angebote von Google Cloud in einer nahtlosen Entwicklungsumgebung. Bisher musste auf mit AutoML trainierte und benutzerdefinierte Modelle über verschiedene Dienste zugegriffen werden. Das neue Angebot kombiniert diese und weitere, neue Produkte zu einer einzigen API. Sie können auch vorhandene Projekte zu Vertex AI migrieren. Wenn Sie Feedback haben, lesen Sie die Supportseite.
Vertex AI umfasst 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 verwenden Sie die Hyperparameter-Abstimmung, um optimale Parameter für ein Bildklassifizierungsmodell zu ermitteln, das mit dem Dataset „horses or humans“ 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 gewählten Hyperparameter innerhalb von Ihnen festgelegten Limits ausgeführt. Vertex AI verfolgt die Ergebnisse jedes Versuchs und nimmt Anpassungen für nachfolgende Versuche 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 Haupt-Trainingsmodul für jeden abzustimmenden Hyperparameter ein Befehlszeilenargument.
- Verwenden Sie den Wert, der in diesen Argumenten übergeben wird, um den entsprechenden Hyperparameter im Code Ihrer Anwendung festzulegen.
Verteiltes Training
Wenn Sie eine einzelne GPU haben, verwendet TensorFlow diesen Beschleuniger, um das Modelltraining zu beschleunigen, ohne dass Sie etwas tun müssen. Wenn Sie jedoch eine zusätzliche Leistungssteigerung durch die Verwendung mehrerer GPUs erzielen möchten, müssen Sie tf.distribute verwenden. Das ist das TensorFlow-Modul zum Ausführen einer Berechnung auf mehreren Geräten.
In diesem Lab wird tf.distribute.MirroredStrategy verwendet, das Sie mit nur wenigen Codeänderungen zu 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. Das bedeutet, dass jede GPU die Vorwärts- und Rückwärtsdurchläufe durch das Modell auf einem anderen Teil der Eingabedaten berechnet. Die berechneten Gradienten aus jedem dieser Teile werden dann auf allen GPUs aggregiert und in einem Prozess namens All-Reduce gemittelt. Die Modellparameter werden mit diesen gemittelten Gradienten aktualisiert.
Sie müssen die Details nicht kennen, um dieses Lab abzuschließen. Wenn Sie jedoch mehr darüber erfahren möchten, wie verteiltes Training in TensorFlow funktioniert, sehen Sie sich das folgende Video an:
4. Umgebung einrichten
Für dieses Codelab benötigen Sie ein Google Cloud-Projekt, in dem die Abrechnung aktiviert ist. Eine Anleitung zum Erstellen eines Projekts finden Sie hier.
Schritt 1: Compute Engine API aktivieren
Rufen Sie Compute Engine auf und wählen Sie Aktivieren aus, falls die API noch nicht aktiviert ist.
Schritt 2: Container Registry API aktivieren
Rufen Sie die Container Registry auf und wählen Sie Aktivieren aus, falls die API noch nicht aktiviert ist. Sie verwenden sie, um einen Container für Ihren benutzerdefinierten Trainingsjob zu erstellen.
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 sie noch nicht aktiviert ist.

Klicken Sie nach der Aktivierung auf VERWALTETE NOTEBOOKS:

Wählen Sie dann NEUES NOTEBOOK aus.

Geben Sie Ihrem Notebook einen Namen und klicken Sie dann 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 automatisch heruntergefahren wird, wenn es nicht verwendet wird, damit keine unnötigen Kosten entstehen.

Wählen Sie unter „Sicherheit“ die Option „Terminal aktivieren“ aus, falls sie noch nicht aktiviert ist.

Sie können alle anderen erweiterten Einstellungen unverändert lassen.
Klicken Sie dann auf Erstellen. Die Bereitstellung der Instanz dauert einige Minuten.
Nachdem die Instanz erstellt wurde, klicken Sie auf JupyterLab öffnen.

Wenn Sie eine neue Instanz zum ersten Mal verwenden, werden Sie aufgefordert, sich zu authentifizieren. Folgen Sie dazu der Anleitung auf der Benutzeroberfläche.

5. Trainingscode schreiben
Öffnen Sie im Launcher-Menü ein Terminalfenster in Ihrer Notebook-Instanz:

Erstellen Sie ein neues Verzeichnis mit dem Namen vertex-codelab und wechseln Sie zu diesem Verzeichnis.
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 der Sie den Code hinzufügen:
mkdir trainer
touch trainer/task.py
Das Verzeichnis vertex-codelab sollte jetzt Folgendes enthalten:
+ trainer/
+ task.py
Öffnen Sie als Nächstes die gerade erstellte Datei task.py und fügen Sie den gesamten folgenden 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()
Sehen wir uns den Code genauer an und untersuchen wir die Komponenten, die speziell für das verteilte Training und die Hyperparameter-Abstimmung verwendet werden.
Verteiltes Training
- In der Funktion
main()wird das ObjektMirroredStrategyerstellt. Als Nächstes umschließen Sie die Erstellung Ihrer Modellvariablen mit dem Bereich der Strategie. Mit diesem Schritt wird TensorFlow mitgeteilt, welche Variablen auf den GPUs gespiegelt werden sollen. - Die Batchgröße wird mit
num_replicas_in_syncskaliert. Das Skalieren der Batchgröße ist eine Best Practice bei der Verwendung synchroner Datenparallelitätsstrategien in TensorFlow. Weitere Informationen hier.
Hyperparameter-Abstimmung
- Das Skript importiert die Bibliothek
hypertune. Wenn wir später das Container-Image erstellen, müssen wir darauf achten, dass diese Bibliothek installiert ist. - Die Funktion
get_args()definiert ein Befehlszeilenargument für jeden abzustimmenden Hyperparameter. In diesem Beispiel werden die Lernrate, der Momentum-Wert im Optimierer und die Anzahl der Einheiten in der letzten verborgenen Schicht des Modells abgestimmt. Sie können aber auch mit anderen Hyperparametern experimentieren. Der Wert, der in diesen Argumenten übergeben wird, wird dann verwendet, um den entsprechenden Hyperparameter im Code festzulegen (z. B.learning_rate = args.learning_rate). - Am Ende der Funktion
main()wird die Bibliothekhypertuneverwendet, um den zu optimierenden Messwert zu definieren. In TensorFlow gibt die Keras-Methodemodel.fiteinHistory-Objekt zurück. Das AttributHistory.historyenthält die Werte für den Trainingsverlust und die Messwerte für aufeinanderfolgende Epochen. Wenn Sie Validierungsdaten anmodel.fitübergeben, enthält das AttributHistory.historyauch die Werte für den Validierungsverlust und die Messwerte. Wenn Sie beispielsweise ein Modell für drei Epochen mit Validierungsdaten trainiert undaccuracyals Messwert angegeben haben, sieht das AttributHistory.historyähnlich wie das folgende Dictionary 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 der Hyperparameter-Abstimmungsdienst die Werte ermitteln soll, mit denen die Validierungsgenauigkeit des Modells maximiert wird, definieren Sie den Messwert als letzten Eintrag (oder NUM_EPOCS - 1) der Liste val_accuracy. Übergeben Sie diesen Messwert dann an eine Instanz von HyperTune. Sie können für hyperparameter_metric_tag eine beliebige String verwenden. Sie müssen die String jedoch später noch einmal verwenden, wenn Sie den Hyperparameter-Abstimmungsjob starten.
6. Code in Container verpacken
Der erste Schritt zum Verpacken Ihres Codes in einen Container besteht darin, ein Dockerfile zu erstellen. Das Dockerfile enthält alle Befehle, die zum Ausführen des Images erforderlich sind. Es installiert alle erforderlichen Bibliotheken und richtet den Einstiegspunkt für den Trainingscode ein.
Schritt 1: Dockerfile schreiben
Achten Sie im Terminal darauf, dass Sie sich im Verzeichnis vertex-codelab befinden, und erstellen Sie ein leeres Dockerfile:
touch Dockerfile
Das Verzeichnis vertex-codelab sollte jetzt Folgendes enthalten:
+ 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 Docker-Image „TensorFlow Enterprise 2.7 GPU“ von Deep Learning Containers. In den Deep Learning Containers in Google Cloud sind viele gängige ML- und Data-Science-Frameworks vorinstalliert. Nach dem Herunterladen dieses 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 eine Variable mit dem URI Ihres Container-Images in der Google Container Registry:
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 von vertex-codelab den folgenden Befehl ausführen:
docker build ./ -t $IMAGE_URI
Laden Sie ihn schließlich in die Google Container Registry hoch:
docker push $IMAGE_URI
Schritt 3: Cloud Storage-Bucket erstellen
In unserem Trainingsjob übergeben wir den Pfad zu einem Staging-Bucket.
Führen Sie im 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 angeben. Die folgende Spezifikation definiert eine Maschine mit zwei NVIDIA Tesla V100-GPUs.
Sie müssen {PROJECT_ID} im 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 die parameter_spec. Das ist ein Dictionary, das die zu optimierenden Parameter angibt. Der Dictionary-Schlüssel ist die String, die Sie dem Befehlszeilenargument für jeden Hyperparameter zugewiesen haben, und der Dictionary-Wert ist die Parameterspezifikation.
Für jeden Hyperparameter müssen Sie den Typ sowie die Grenzen für die Werte definieren, die der Abstimmungsdienst testen soll. 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 einen Höchstwert angeben. Wenn Sie „Categorical“ oder „Discrete“ auswählen, müssen Sie die Werte angeben. Für die Typen „Double“ und „Integer“ müssen Sie auch den Skalierungswert angeben. In diesem Video erfahren Sie mehr darüber, wie Sie die beste Skalierung auswählen.
# 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. Das ist ein Dictionary, das den zu optimierenden Messwert darstellt. Der Dictionary-Schlüssel ist das hyperparameter_metric_tag, das Sie im Code Ihrer Trainingsanwendung festgelegt haben, 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 einen CustomJob. Das ist die allgemeine Spezifikation, die verwendet wird, um Ihren Job für jeden der Hyperparameter-Abstimmungstests auszuführen.
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 und führen Sie dann den HyperparameterTuningJob 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()
Beachten Sie einige Argumente:
- max_trial_count: Sie müssen eine Obergrenze für die Anzahl der Tests festlegen, die der Dienst ausführt. Mehr Tests führen in der Regel zu besseren Ergebnissen, aber es gibt einen Punkt, ab dem rückläufige Ergebnisse geliefert werden und zusätzliche Tests danach wenig oder keinen Einfluss auf den Messwert haben, den Sie optimieren möchten. Es empfiehlt sich, mit einer kleineren Anzahl von Tests zu beginnen und sich ein Bild davon zu machen, wie sich die gewählten Hyperparameter auswirken, bevor Sie die Anzahl erhöhen.
- parallel_trial_count: Wenn Sie parallele Tests verwenden, stellt der Dienst mehrere Trainingsverarbeitungscluster bereit. Wenn Sie die Anzahl der parallelen Tests erhöhen, verkürzt sich die Ausführungszeit des Hyperparameter-Abstimmungsjobs. Dies kann jedoch die Effektivität des Jobs insgesamt verringern. Das liegt daran, dass die Standardstrategie für die Abstimmung die Ergebnisse vorheriger Tests verwendet, um die Werte für nachfolgende Tests festzulegen.
- search_algorithm: Sie können den Suchalgorithmus auf „grid“, „random“ oder „default“ (None) festlegen. Die Standardoption wendet die Bayes'sche Optimierung an, um den Bereich möglicher Hyperparameterwerte zu durchsuchen. Das ist der empfohlene Algorithmus. Weitere Informationen zu diesem Algorithmus hier.
Sobald der Job gestartet wurde, können Sie den Status auf der Benutzeroberfläche auf dem Tab HYPERPARAMETER-ABSTIMMUNGSJOBS verfolgen.

Nach Abschluss des Jobs können Sie die Ergebnisse Ihrer Tests ansehen und sortieren, um die beste Kombination von Hyperparameter-Werten zu ermitteln.

🎉 Das wars! 🎉
Sie haben gelernt, wie Sie Vertex AI für Folgendes verwenden:
- Hyperparameter-Abstimmungsjob mit verteiltem Training ausführen
Weitere Informationen zu den verschiedenen Bereichen von Vertex AI finden Sie in der Dokumentation.
8. Bereinigen
Da wir das Notebook so konfiguriert haben, dass es nach 60 Minuten Inaktivität eine Zeitüberschreitung auslöst, müssen wir uns nicht um das Herunterfahren der Instanz kümmern. Wenn Sie die Instanz manuell herunterfahren möchten, klicken Sie im Bereich „Vertex AI Workbench“ der Console auf die Schaltfläche „Beenden“. Wenn Sie das Notebook vollständig löschen möchten, klicken Sie auf die Schaltfläche „Löschen“.

Wenn Sie den Storage-Bucket löschen möchten, rufen Sie im Navigationsmenü der Cloud Console „Storage“ auf, wählen Sie den Bucket aus und klicken Sie auf „Löschen“:
