1. Übersicht
In diesem Lab verwenden Sie Vertex AI, um einen Trainingsjob mit mehreren Workern für ein TensorFlow-Modell auszuführen.
Lerninhalte
Die folgenden Themen werden behandelt:
- Trainingsanwendungscode für das Training mit mehreren Workern ändern
- Multi-Worker-Trainingsjob über die Vertex AI-UI konfigurieren und starten
- Multi-Worker-Trainingsjob mit dem Vertex SDK konfigurieren und starten
Die Gesamtkosten für das Lab in Google Cloud betragen etwa 5$.
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. Bisher konnten auf mit AutoML trainierte Modelle und benutzerdefinierte Modelle über separate Dienste zugegriffen werden. 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 liegt der Schwerpunkt auf den unten aufgeführten Produkten: Training und Workbench.
3. Anwendungsfall – Übersicht
In diesem Lab nutzen Sie Lerntransfers, um ein Bildklassifizierungsmodell mit dem Cassava-Dataset aus TensorFlow-Datasets zu trainieren. Die verwendete Architektur ist ein ResNet50-Modell aus der Bibliothek tf.keras.applications
, das mit dem Imagenet-Dataset vortrainiert wurde.
Warum 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 auf einer einzelnen Maschine oder mehreren Maschinen (jeweils mit potenziell mehreren GPUs) zusätzliche Leistung erzielen möchten, müssen Sie tf.distribute
verwenden. Dies ist die TensorFlow-Bibliothek zum Ausführen einer Berechnung auf mehreren Geräten. Ein Gerät bezieht sich auf eine CPU oder einen Beschleuniger wie GPUs oder TPUs auf einer Maschine, auf der TensorFlow Vorgänge ausführen kann.
Die einfachste Möglichkeit für den Einstieg in verteiltes Training ist eine einzelne Maschine mit mehreren GPU-Geräten. Eine TensorFlow-Verteilungsstrategie aus dem tf.distribute
-Modul verwaltet die Koordination der Datenverteilung und Gradientenaktualisierungen auf allen GPUs. Wenn Sie das Training auf einem einzelnen Host bewältigt haben und noch weiter skalieren möchten, kann das Hinzufügen mehrerer Maschinen zu Ihrem Cluster zu einer noch größeren Leistungssteigerung beitragen. Sie können einen Cluster von Maschinen nutzen, die nur CPU-fähig sind oder jeweils eine oder mehrere GPUs haben. In diesem Lab wird der letzte Fall behandelt. Außerdem wird gezeigt, wie Sie mit MultiWorkerMirroredStrategy
das Training eines TensorFlow-Modells auf mehrere Maschinen in Vertex AI verteilen.
MultiWorkerMirroredStrategy
ist eine synchrone Datenparallelitätsstrategie, die Sie mit nur wenigen Codeänderungen verwenden können. Auf jedem Gerät im Cluster wird eine Kopie des Modells erstellt. Die nachfolgenden Gradientenaktualisierungen erfolgen synchron. Das bedeutet, dass jedes Worker-Gerät die Vor- und Rückläufe durch das Modell anhand eines anderen Segments der Eingabedaten berechnet. Die aus jedem dieser Segmente berechneten Gradienten werden dann über alle Geräte auf einem Computer und alle Maschinen im Cluster hinweg aggregiert und (in der Regel ein Durchschnittswert) in einem Prozess reduziert, der als All-Reduce bezeichnet wird. Die Optimierung führt dann die Parameteraktualisierungen mit diesen reduzierten Gradienten durch und hält so die Geräte synchron. Im folgenden Video erfahren Sie mehr über verteiltes Training mit TensorFlow:
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
Rufen Sie Compute Engine auf und wählen Sie Aktivieren aus, falls die Option noch nicht aktiviert ist. Sie benötigen dies zum Erstellen Ihrer Notebookinstanz.
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 in der Cloud Console den Bereich Vertex AI 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 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ä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.
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. Trainingsanwendungscode containerisieren
Zum Senden dieses Trainingsjobs an Vertex fügen Sie den Code Ihrer Trainingsanwendung in einen Docker-Container ein und übertragen diesen Container per Push in Google Container Registry. Mit diesem Ansatz können Sie ein Modell trainieren, das mit einem beliebigen Framework erstellt wurde.
Öffnen Sie zuerst über das Launcher-Menü ein Terminalfenster in Ihrer Notebook-Instanz:
Erstellen Sie ein neues Verzeichnis mit dem Namen cassava
und fügen Sie es mit cd ein:
mkdir cassava
cd cassava
Schritt 1: Dockerfile erstellen
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.
Erstellen Sie über Ihr Terminal ein leeres Dockerfile:
touch Dockerfile
Öffnen Sie das Dockerfile und fügen Sie Folgendes ein:
FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7
WORKDIR /
# 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. Die Deep Learning Container auf Google Cloud sind mit vielen gängigen ML- und Data-Science-Frameworks vorinstalliert. Nach dem Herunterladen des Images richtet dieses Dockerfile den Einstiegspunkt für den Trainingscode ein. Sie haben diese Dateien noch nicht erstellt. Im nächsten Schritt fügen Sie den Code zum Trainieren und Abstimmen des Modells hinzu.
Schritt 2: Cloud Storage-Bucket erstellen
In diesem Trainingsjob exportieren Sie das trainierte TensorFlow-Modell in einen Cloud Storage-Bucket. 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'
Führen Sie als Nächstes den folgenden Befehl in Ihrem Terminal aus, um einen neuen Bucket in Ihrem Projekt zu erstellen.
BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET
Schritt 3: Trainingscode für das Modell hinzufügen
Führen Sie im Terminal 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 cassava/
-Verzeichnis sollte nun Folgendes vorhanden sein:
+ Dockerfile
+ trainer/
+ task.py
Öffnen Sie als Nächstes die soeben erstellte Datei task.py
und kopieren Sie den unten stehenden Code. Ersetzen Sie {your-gcs-bucket}
durch den Namen des Cloud Storage-Buckets, den Sie gerade erstellt haben.
import tensorflow as tf
import tensorflow_datasets as tfds
import os
PER_REPLICA_BATCH_SIZE = 64
EPOCHS = 2
# TODO: replace {your-gcs-bucket} with the name of the Storage bucket you created earlier
BUCKET = 'gs://{your-gcs-bucket}/mwms'
def preprocess_data(image, label):
'''Resizes and scales images.'''
image = tf.image.resize(image, (300,300))
return tf.cast(image, tf.float32) / 255., label
def create_dataset(batch_size):
'''Loads Cassava dataset and preprocesses data.'''
data, info = tfds.load(name='cassava', as_supervised=True, with_info=True)
number_of_classes = info.features['label'].num_classes
train_data = data['train'].map(preprocess_data,
num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_data = train_data.shuffle(1000)
train_data = train_data.batch(batch_size)
train_data = train_data.prefetch(tf.data.experimental.AUTOTUNE)
# Set AutoShardPolicy
options = tf.data.Options()
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
train_data = train_data.with_options(options)
return train_data, number_of_classes
def create_model(number_of_classes):
'''Creates and compiles pretrained ResNet50 model.'''
base_model = tf.keras.applications.ResNet50(weights='imagenet', include_top=False)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(1016, activation='relu')(x)
predictions = tf.keras.layers.Dense(number_of_classes, activation='softmax')(x)
model = tf.keras.Model(inputs=base_model.input, outputs=predictions)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.0001),
metrics=['accuracy'])
return model
def _is_chief(task_type, task_id):
'''Helper function. Determines if machine is chief.'''
return task_type == 'chief'
def _get_temp_dir(dirpath, task_id):
'''Helper function. Gets temporary directory for saving model.'''
base_dirpath = 'workertemp_' + str(task_id)
temp_dir = os.path.join(dirpath, base_dirpath)
tf.io.gfile.makedirs(temp_dir)
return temp_dir
def write_filepath(filepath, task_type, task_id):
'''Helper function. Gets filepath to save model.'''
dirpath = os.path.dirname(filepath)
base = os.path.basename(filepath)
if not _is_chief(task_type, task_id):
dirpath = _get_temp_dir(dirpath, task_id)
return os.path.join(dirpath, base)
def main():
# Create strategy
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get data
global_batch_size = PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync
train_data, number_of_classes = create_dataset(global_batch_size)
# Wrap variable creation within strategy scope
with strategy.scope():
model = create_model(number_of_classes)
model.fit(train_data, epochs=EPOCHS)
# Determine type and task of the machine from
# the strategy cluster resolver
task_type, task_id = (strategy.cluster_resolver.task_type,
strategy.cluster_resolver.task_id)
# Based on the type and task, write to the desired model path
write_model_path = write_filepath(BUCKET, task_type, task_id)
model.save(write_model_path)
if __name__ == "__main__":
main()
Bevor Sie den Container erstellen, werfen wir einen genaueren Blick auf den Code, der MultiWorkerMirroredStrategy
aus der tf.distribute.Strategy
API verwendet.
Der Code enthält einige Komponenten, die erforderlich sind, damit der Code mit MultiWorkerMirroredStrategy
funktioniert.
- Die Daten müssen in Shards aufgeteilt werden, d. h., jedem Worker wird ein Teil des gesamten Datensatzes zugewiesen. Daher wird in jedem Schritt eine globale Batchgröße von sich nicht überlappenden Dataset-Elementen von jedem Worker verarbeitet. Dieses Fragmentierung erfolgt automatisch mit
tf.data.experimental.AutoShardPolicy
, für dasFILE
oderDATA
festgelegt werden kann. In diesem Beispiel legt die Funktioncreate_dataset()
denAutoShardPolicy
aufDATA
fest, da das Maniotik-Dataset nicht in mehreren Dateien heruntergeladen wird. Wenn du die Richtlinie jedoch nicht auf „DATA
“ setzt, wird die standardmäßige Richtlinie „AUTO
“ wirksam und das Endergebnis ist das gleiche. Weitere Informationen zur Dataset-Fragmentierung mitMultiWorkerMirroredStrategy
- In der
main()
-Funktion wird dasMultiWorkerMirroredStrategy
-Objekt erstellt. Als Nächstes schließen Sie die Erstellung Ihrer Modellvariablen in den Bereich der Strategie ein. In diesem wichtigen Schritt wird TensorFlow mitgeteilt, welche Variablen in den Replikaten gespiegelt werden sollen. - Die Batchgröße wird um
num_replicas_in_sync
hochskaliert. Dadurch wird sichergestellt, dass jedes Replikat bei jedem Schritt die gleiche Anzahl von Beispielen verarbeitet. Das Skalieren der Batchgröße ist eine Best Practice bei der Verwendung von Strategien zur synchronen Datenparallelität in TensorFlow. - Bei mehreren Workern ist das Speichern des Modells etwas komplizierter, da das Ziel für jeden Worker unterschiedlich sein muss. Der Haupt-Worker speichert das Modell im gewünschten Modellverzeichnis, während die anderen Worker das Modell in temporären Verzeichnissen speichern. Es ist wichtig, dass diese temporären Verzeichnisse eindeutig sind, um zu verhindern, dass mehrere Worker in denselben Speicherort schreiben. Das Speichern kann kollektive Operationen umfassen, was bedeutet, dass alle Worker retten müssen und nicht nur der Chief. Die Funktionen
_is_chief()
,_get_temp_dir()
,write_filepath()
undmain()
enthalten Boilerplate-Code, mit dem das Modell gespeichert werden kann.
Wenn Sie MultiWorkerMirroredStrategy
in einer anderen Umgebung verwendet haben, haben Sie möglicherweise die Umgebungsvariable TF_CONFIG
eingerichtet. Vertex AI legt TF_CONFIG
automatisch für Sie fest, sodass Sie diese Variable nicht auf jeder Maschine im Cluster definieren müssen.
Schritt 4: 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/multiworker:cassava"
Docker konfigurieren
gcloud auth configure-docker
Erstellen Sie dann den Container, indem Sie im Stammverzeichnis Ihres cassava
-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
Nachdem der Container in Container Registry übertragen wurde, können Sie den Trainingsjob starten.
6. Multi-Worker-Trainingsjob in Vertex AI ausführen
In diesem Lab wird das benutzerdefinierte Training über einen benutzerdefinierten Container in Google Container Registry verwendet. Sie können aber auch einen Trainingsjob mit den vordefinierten Containern ausführen.
Gehen Sie zuerst im Vertex-Bereich der Cloud Console zum Abschnitt Training:
Schritt 1: Trainingsjob konfigurieren
Klicken Sie auf Erstellen, um die Parameter für den Trainingsjob einzugeben.
- Wählen Sie unter Dataset die Option Kein verwaltetes Dataset aus.
- Wählen Sie dann Benutzerdefiniertes Training (erweitert) als Trainingsmethode aus und klicken Sie auf Weiter.
- Geben Sie
multiworker-cassava
(oder einen anderen Namen für Ihr Modell) bei Modellname ein. - Klicken Sie auf Weiter.
Wählen Sie im Schritt „Containereinstellungen“ die Option Benutzerdefinierter Container aus:
Geben Sie im ersten Feld (Container-Image) den Wert der Variablen IMAGE_URI
aus dem vorherigen Abschnitt ein. Sie sollte gcr.io/your-cloud-project/multiworker:cassava
mit Ihrer eigenen Projekt-ID lauten. Lassen Sie die restlichen Felder leer und klicken Sie auf Weiter.
Überspringen Sie den Schritt „HHyperparameter“, indem Sie noch einmal auf Continue klicken.
Schritt 2: Compute-Cluster konfigurieren
Vertex AI bietet 4 Worker-Pools, um die verschiedenen Arten von Maschinenaufgaben abzudecken.
Worker-Pool 0 konfiguriert den Primär-, Chief-, Planer- oder „Master“. In MultiWorkerMirroredStrategy
werden alle Maschinen als Worker bezeichnet. Das sind die physischen Maschinen, auf denen die replizierte Berechnung ausgeführt wird. Zusätzlich dazu, dass jeder Rechner ein Worker ist, muss es einen Worker geben, der zusätzliche Arbeit übernimmt, z. B. das Speichern von Prüfpunkten und das Schreiben von Zusammenfassungsdateien in TensorBoard. Diese Maschine wird als „Chief“ bezeichnet. Es gibt immer nur einen Chief Worker, sodass Ihre Worker-Anzahl für den Worker-Pool 0 immer 1 ist.
Lassen Sie unter Computing und Preise die ausgewählte Region unverändert und konfigurieren Sie Worker-Pool 0 so:
In Worker-Pool 1 konfigurieren Sie die Worker für den Cluster.
Konfigurieren Sie Worker-Pool 1 so:
Der Cluster ist jetzt so konfiguriert, dass er zwei reine CPU-Maschinen hat. Wenn der Code der Trainingsanwendung ausgeführt wird, verteilt MultiWorkerMirroredStrategy
das Training auf beide Maschinen.
MultiWorkerMirroredStrategy
hat nur die Aufgabentypen „Chief“ und „Worker“, sodass die zusätzlichen Worker-Pools nicht konfiguriert werden müssen. Wenn Sie jedoch ParameterServerStrategy
von TensorFlow verwenden, würden Sie Ihre Parameterserver in Worker-Pool 2 konfigurieren. Wenn Sie Ihrem Cluster einen Evaluator hinzufügen möchten, konfigurieren Sie diese Maschine im Worker-Pool 3.
Klicken Sie auf Training starten, um den Hyperparameter-Abstimmungsjob zu starten. Im Abschnitt "Training" der Konsole auf dem Tab TRAININGSPIPELINES sehen Sie den neu gestarteten Job:
🎉 Glückwunsch! 🎉
Sie haben gelernt, wie Sie mit Vertex AI Folgendes tun können:
- Einen Trainingsjob für mehrere Worker für Trainingscode starten, der in einem benutzerdefinierten Container bereitgestellt wird In diesem Beispiel haben Sie ein TensorFlow-Modell verwendet. Sie können aber ein mit einem beliebigen Framework erstelltes Modell mithilfe benutzerdefinierter oder integrierter Container trainieren.
Weitere Informationen zu den verschiedenen Teilen von Vertex finden Sie in der Dokumentation.
7. [Optional] Vertex SDK verwenden
Im vorherigen Abschnitt wurde gezeigt, wie der Trainingsjob über die Benutzeroberfläche gestartet wird. In diesem Abschnitt wird eine alternative Methode zum Senden des Trainingsjobs mithilfe der Vertex Python API beschrieben.
Kehren Sie zu Ihrer Notebook-Instanz zurück und erstellen Sie über den Launcher ein TensorFlow 2-Notebook:
Importieren Sie das Vertex AI SDK.
from google.cloud import aiplatform
Um den Trainingsjob mit mehreren Workern zu starten, müssen Sie zuerst die Worker-Pool-Spezifikation definieren. Die Verwendung von GPUs in der Spezifikation ist völlig optional. Sie können accelerator_type
und accelerator_count
entfernen, wenn Sie einen reinen CPU-Cluster wie im vorherigen Abschnitt gezeigt benötigen.
# The spec of the worker pools including machine type and Docker image
# Be sure to replace {YOUR-PROJECT-ID} with your project ID.
worker_pool_specs=[
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
},
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
}
]
Erstellen Sie als Nächstes einen CustomJob
und führen Sie ihn aus. Für das Staging müssen Sie {YOUR_BUCKET}
durch einen Bucket in Ihrem Projekt ersetzen. Sie können denselben Bucket verwenden, den Sie zuvor erstellt haben.
# Replace YOUR_BUCKET
my_multiworker_job = aiplatform.CustomJob(display_name='multiworker-cassava-sdk',
worker_pool_specs=worker_pool_specs,
staging_bucket='gs://{YOUR_BUCKET}')
my_multiworker_job.run()
Im Abschnitt "Training" der Konsole auf dem Tab BENUTZERDEFINIERTE JOBS sehen Sie Ihren Trainingsjob:
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 Speicher-Bucket löschen möchten, klicken Sie in der Cloud Console im Navigationsmenü auf „Speicher“, wählen Sie den Bucket aus und klicken Sie auf „Löschen“: