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 gelten jedoch auch für andere ML-Frameworks.
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 die Ausführung dieses Labs in Google Cloud belaufen sich auf etwa 6$.
2. Einführung in Vertex AI
In diesem Lab wird das neueste KI-Produktangebot von Google Cloud verwendet. Vertex AI integriert die ML-Angebote in Google Cloud für eine nahtlose Entwicklung. Bisher konnten auf mit AutoML trainierte Modelle und benutzerdefinierte Modelle über separate Dienste zugegriffen werden. Das neue Angebot kombiniert beide zusammen mit anderen neuen Produkten in einer einzigen API. Sie können auch vorhandene Projekte zu Vertex AI migrieren. Wenn du Feedback hast, sieh auf der Supportseite nach.
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 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 gewählten Hyperparameter innerhalb 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 Haupt-Trainingsmodul für jeden abzustimmenden Hyperparameter 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, beschleunigt TensorFlow das Modelltraining mit diesem Beschleuniger, ohne dass Sie etwas tun müssen. 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 Ihren Trainingsanwendungen mit nur wenigen Codeänderungen hinzufügen können. Bei dieser Strategie wird auf jeder GPU auf Ihrem Computer eine Kopie des Modells erstellt. Die nachfolgenden Farbverlaufsaktualisierungen erfolgen synchron. Das bedeutet, dass jede GPU die Vorwärts- und Rückwärtsdurchläufe durch das Modell für einen anderen Ausschnitt der Eingabedaten berechnet. Die berechneten Gradienten aus den einzelnen Segmenten werden dann über alle GPUs aggregiert und in einem als All-Reduce bezeichneten Prozess gemittelt. Die Modellparameter werden anhand dieser 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 Video unten an:
4. Umgebung einrichten
Sie benötigen ein Google Cloud-Projekt mit aktivierter Abrechnung, um dieses Codelab ausführen zu können. 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 Option noch nicht aktiviert ist.
Schritt 2: Container Registry API aktivieren
Rufen Sie die Container Registry auf und wählen Sie Aktivieren aus, falls noch nicht geschehen. Sie verwenden es, um einen Container für Ihren benutzerdefinierten Trainingsjob zu erstellen.
Schritt 3: Vertex AI API aktivieren
Rufen Sie den Bereich „Vertex AI“ der Cloud Console auf und klicken Sie auf Vertex AI API aktivieren.
Schritt 4: Vertex AI Workbench-Instanz erstellen
Klicken Sie in der Cloud Console im Bereich „Vertex AI“ 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 NOTIZBUCH aus.
Geben Sie einen Namen für das Notebook ein 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 Notebook wird also automatisch heruntergefahren, wenn es nicht verwendet wird, sodass keine unnötigen Kosten entstehen.
Wählen Sie 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.
Wählen Sie nach dem Erstellen der Instanz JupyterLab öffnen aus.
Wenn Sie eine neue Instanz zum ersten Mal verwenden, werden Sie zur Authentifizierung aufgefordert. Folgen Sie dazu der Anleitung auf der Benutzeroberfläche.
5. Trainingscode schreiben
Öffnen Sie zuerst über das Launcher-Menü ein Terminalfenster in Ihrer Notebook-Instanz:
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
Ihr vertex-codelab
-Verzeichnis sollte jetzt so aussehen:
+ trainer/
+ task.py
Öffnen Sie als Nächstes die Datei task.py
, die Sie gerade erstellt haben, und fügen Sie den gesamten Code unten 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 die Komponenten, die speziell für die verteilte Trainings- und Hyperparameterabstimmung verwendet werden.
Verteiltes Training
- In der Funktion
main()
wird dasMirroredStrategy
-Objekt erstellt. Als Nächstes legen Sie fest, dass die Modellvariablen im Geltungsbereich der Strategie erstellt werden. In diesem Schritt wird TensorFlow mitgeteilt, welche Variablen in den GPUs gespiegelt werden sollen. - Die Batchgröße wird um den Wert von
num_replicas_in_sync
skaliert. 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 Script importiert die
hypertune
-Bibliothek. Später, wenn wir das Container-Image erstellen, müssen wir diese Bibliothek installieren. - Die Funktion
get_args()
definiert ein Befehlszeilenargument für jeden Hyperparameter, den Sie abstimmen möchten. In diesem Beispiel werden die Hyperparameter Lernrate, der Momentum-Wert im Optimierer und die Anzahl der Einheiten in der letzten verborgenen Schicht des Modells angepasst. Sie können aber auch mit anderen experimentieren. Der in diesen Argumenten übergebene Wert wird dann verwendet, um den entsprechenden Hyperparameter im Code festzulegen (z. B.learning_rate = args.learning_rate
festlegen). - 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
enthält Werte für den Trainingsverlust und Messwerte für aufeinanderfolgende Epochen. Wenn Sie Validierungsdaten anmodel.fit
übergeben, enthält dasHistory.history
-Attribut auch Werte für Validierungsverluste und Messwerte. Wenn Sie beispielsweise ein Modell mit Validierungsdaten für drei Epochen trainiert undaccuracy
als Messwert angegeben haben, sieht das AttributHistory.history
in etwa so aus wie das folgende Wörterbuch.
{
"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 Dienst zur Hyperparameter-Abstimmung 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 einen beliebigen String für hyperparameter_metric_tag
auswählen. Sie müssen ihn jedoch später noch einmal verwenden, wenn Sie den Job zur Hyperparameter-Abstimmung starten.
6. Code containerisieren
Der erste Schritt bei der Containerisierung Ihres Codes besteht darin, ein Dockerfile zu erstellen. Im Dockerfile geben Sie alle Befehle an, die zum Ausführen des Images erforderlich sind. Dadurch werden alle erforderlichen Bibliotheken installiert und der Einstiegspunkt für den Trainingscode eingerichtet.
Schritt 1: Dockerfile schreiben
Achten Sie darauf, dass Sie sich im Terminal 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"]
In diesem Dockerfile wird das Deep Learning Container TensorFlow Enterprise 2.7 GPU Docker-Image verwendet. Die Deep Learning Container in Google Cloud sind mit vielen gängigen ML- und Data-Science-Frameworks vorinstalliert. Nach dem Herunterladen dieses Images wird in diesem Dockerfile der Einstiegspunkt für den Trainingscode eingerichtet.
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 Ihres vertex-codelab
-Verzeichnisses Folgendes ausführen:
docker build ./ -t $IMAGE_URI
Übertragen Sie die Datei anschließ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 im Terminal 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 über den 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, in der der Maschinentyp und das Docker-Image angegeben werden. In der folgenden Spezifikation wird eine Maschine mit zwei NVIDIA Tesla V100-GPUs definiert.
Ersetzen Sie {PROJECT_ID}
in image_uri
durch Ihr Projekt.
# 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"
}
}]
Als Nächstes definieren Sie parameter_spec
. Das ist ein Dictionary, in dem die Parameter angegeben werden, die Sie optimieren möchten. Der Dictionary-Schlüssel ist der String, den Sie dem Befehlszeilenargument für jeden Hyperparameter zugewiesen haben. Der Dictionary-Wert ist die Parameterspezifikation.
Für jeden Hyperparameter müssen Sie den Typ sowie die Grenzen für die Werte definieren, die vom Abgleichsdienst ausprobiert werden sollen. Hyperparameter können vom Typ „Dezimalzahl“, „Ganzzahl“, „Kategorisch“ oder „Diskret“ sein. Wenn Sie den Typ „Dezimalzahl“ oder „Ganzzahl“ auswählen, müssen Sie einen Mindest- und einen Höchstwert angeben. Wenn Sie „Kategorisch“ 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 erfahren Sie mehr darüber, wie Sie die richtige 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 Spezifikation, die Sie definieren müssen, ist metric_spec
. Das ist ein Wörterbuch, das den zu optimierenden Messwert darstellt. Der Wörterbuchschlüssel ist die hyperparameter_metric_tag
, die Sie im Code Ihrer Trainingsanwendung festgelegt haben, und der Wert ist das Zielvorhaben für die Optimierung.
# 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'}
Nachdem Sie die Spezifikationen definiert haben, erstellen Sie eine CustomJob
. Dies ist die gemeinsame Spezifikation, mit der Ihr Job in jedem der Hyperparameter-Abstimmungstests ausgeführt wird.
Ersetzen Sie {YOUR_BUCKET}
durch den zuvor erstellten Bucket.
# 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 die 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()
Hier sind einige Argumente:
- max_trial_count: Sie müssen eine Obergrenze für die Anzahl der Tests festlegen, die der Dienst ausführen soll. Mehr Tests führen in der Regel zu besseren Ergebnissen. Es gibt jedoch einen Punkt, ab dem zusätzliche Tests wenig oder gar 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 ausgewä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 beeinträchtigen. Das liegt daran, dass die Standardabstimmungsstrategie die Ergebnisse vorheriger Tests verwendet, um die Werte in nachfolgenden Tests zuzuweisen.
- 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 Hyperparameterwerte 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 aufrufen und sortieren, um die beste Kombination von Hyperparameterwerten zu ermitteln.
🎉 Glückwunsch! 🎉
Sie haben gelernt, wie Sie Vertex AI für Folgendes verwenden:
- 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 ein Zeitlimit erreicht wird, müssen wir uns keine Gedanken über das Herunterfahren der Instanz machen. Wenn Sie die Instanz manuell herunterfahren möchten, klicken Sie in der Console im Bereich „Vertex AI Workbench“ auf die Schaltfläche „Beenden“. 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“: