Vertex AI: Hyperparameter-Abstimmung

1. Übersicht

In diesem Lab verwenden Sie Vertex AI, um einen Hyperparameter-Abstimmungsjob für ein TensorFlow-Modell auszuführen. 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:

  • Trainingsanwendungscode für die automatisierte Hyperparameter-Abstimmung ändern
  • Hyperparameter-Abstimmungsjob über die Vertex AI-UI konfigurieren und starten
  • Hyperparameter-Abstimmungsjob mit dem Vertex AI Python SDK konfigurieren und starten

Die Gesamtkosten für das Lab in Google Cloud betragen etwa $3.

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 liegt der Fokus auf den unten aufgeführten Produkten: Training und Workbench.

Vertex-Produktübersicht

3. Richten Sie Ihre Umgebung ein.

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. 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 den Bereich Vertex AI in der Cloud Console auf und klicken Sie auf Vertex AI API aktivieren.

Vertex AI-Dashboard

Schritt 4: Vertex AI Workbench-Instanz erstellen

Klicken Sie im Bereich Vertex AI der Cloud Console auf Workbench:

Vertex AI-Menü

Aktivieren Sie die Notebooks API, falls noch nicht geschehen.

Notebook_api

Klicken Sie nach der Aktivierung auf VERWALTETE NOTEBOOKS:

Notebooks_UI

Wählen Sie dann NEUES NOTEBOOK aus.

new_notebook

Geben Sie Ihrem Notebook einen Namen und klicken Sie auf Erweiterte Einstellungen.

create_notebook

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.

idle_timeout

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

enable_terminal

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.

open_jupyterlab

Wenn Sie zum ersten Mal eine neue Instanz verwenden, werden Sie zur Authentifizierung aufgefordert. Folgen Sie dazu den Schritten in der Benutzeroberfläche.

Authentifizieren

4. Trainingsanwendungscode containerisieren

Das Modell, das Sie in diesem Lab trainieren und abstimmen, ist ein Bildklassifizierungsmodell, das mit dem Pferde- oder Mensch-Dataset aus TensorFlow-Datasets trainiert wurde.

Zum Senden dieses Hyperparameter-Abstimmungsjobs an Vertex AI fügen Sie Ihren Trainingsanwendungscode in einen Docker-Container ein und verschieben diesen Container per Push in Google Container Registry. Mit diesem Ansatz können Sie Hyperparameter für ein Modell abstimmen, das mit einem beliebigen Framework erstellt wurde.

Öffnen Sie dazu im Launcher-Menü ein Terminalfenster in Ihrer Notebookinstanz:

Terminal im Notebook öffnen

Erstellen Sie ein neues Verzeichnis mit dem Namen horses_or_humans und fügen Sie es mit cd ein:

mkdir horses_or_humans
cd horses_or_humans

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. Alle erforderlichen Bibliotheken, einschließlich der CloudML Hypertune-Bibliothek, werden installiert und der Einstiegspunkt für den Trainingscode wird eingerichtet.

Erstellen Sie im Terminal ein leeres Dockerfile:

touch Dockerfile

Ö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. 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: 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 horses_or_humans/-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.

import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune

NUM_EPOCHS = 10


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():
  '''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(64)

  # Create validation dataset
  validation_data = data['test'].map(preprocess_data)
  validation_data  = validation_data.batch(64)

  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()
  train_data, validation_data = create_dataset()
  model = create_model(args.num_units, args.learning_rate, args.momentum)
  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()

Bevor Sie den Container erstellen, werfen wir einen genaueren Blick auf den Code. Es gibt einige Komponenten, die für die Verwendung des Hyperparameter-Abstimmungsdienstes spezifisch sind.

  1. Das Skript importiert die hypertune-Bibliothek. Das Dockerfile aus Schritt 1 enthält eine Anleitung zur pip-Installation dieser Bibliothek.
  2. 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.
  3. Am Ende der Funktion main() wird die Bibliothek hypertune verwendet, um den Messwert zu definieren, den Sie optimieren möchten. In TensorFlow gibt die Keras-Methode model.fit ein History-Objekt zurück. Das Attribut History.history ist ein Datensatz mit Trainingsverlustwerten und -messwerten in aufeinanderfolgenden Epochen. Wenn Sie Validierungsdaten an model.fit übergeben, enthält das Attribut History.history auch Validierungsverlust und Messwerte. Wenn Sie beispielsweise ein Modell über drei Epochen mit Validierungsdaten trainiert und accuracy als Messwert angegeben haben, sieht das History.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.

Schritt 3: 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:hypertune"

Docker konfigurieren

gcloud auth configure-docker

Erstellen Sie dann den Container, indem Sie im Stammverzeichnis Ihres horses_or_humans-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 einen Hyperparameter-Abstimmungsjob für benutzerdefinierte Modelle starten.

5. Hyperparameter-Abstimmungsjob in Vertex AI ausführen

In diesem Lab wird benutzerdefiniertes Training über einen benutzerdefinierten Container in Google Container Registry verwendet. Sie können aber auch einen Hyperparameter-Abstimmungsjob mit einem vordefinierten Vertex AI-Container ausführen.

Gehen Sie zuerst im Vertex-Bereich der Cloud Console zum Abschnitt Training:

uCAIP-Menü

Schritt 1: Trainingsjob konfigurieren

Klicken Sie auf Erstellen, um die Parameter für Ihren Hyperparameter-Abstimmungsjob 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 horses-humans-hyptertune (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:

Benutzerdefinierte Containeroption

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/horse-human:hypertune mit Ihrem eigenen Projektnamen lauten. Lassen Sie die restlichen Felder leer und klicken Sie auf Weiter.

Schritt 2: Hyperparameter-Abstimmungsjob konfigurieren

Wählen Sie Hyperparameter-Abstimmung aktivieren aus.

Hyperparameter

Hyperparameter konfigurieren

Als Nächstes müssen Sie die Hyperparameter hinzufügen, die Sie als Befehlszeilenargumente im Code der Trainingsanwendung festgelegt haben. Wenn Sie einen Hyperparameter hinzufügen, müssen Sie zuerst den Namen angeben. Dieser sollte mit dem Namen des Arguments übereinstimmen, den Sie an argparse übergeben haben.

learning_rate_name

Anschließend wählen Sie den Typ sowie die Grenzen für die Werte aus, die der Abstimmungsdienst verwenden wird. 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.

learning_rate_typelearning_rate_name

Für die Typen Double und Integer müssen Sie außerdem den Skalierungswert angeben.

learning_rate_scale

Nachdem Sie den Hyperparameter learning_rate hinzugefügt haben, fügen Sie Parameter für momentum und num_units hinzu.

momentum_config

numneruons_config

Messwert konfigurieren

Nachdem Sie die Hyperparameter hinzugefügt haben, geben Sie als Nächstes den Messwert, den Sie optimieren möchten, sowie das Ziel an. Dies sollte mit dem hyperparameter_metric_tag übereinstimmen, den Sie in Ihrer Trainingsanwendung festgelegt haben.

metric_config

Der Vertex AI-Hyperparameter-Abstimmungsdienst führt mehrere Tests Ihrer Trainingsanwendung mit den in den vorherigen Schritten konfigurierten Werten aus. 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. Wenn die Ergebnisse jedoch abnehmen, wirken sich zusätzliche Tests nur geringfügig oder gar nicht auf den Messwert aus, 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 eine Skalierung auf eine große Anzahl von Tests durchführen.

Außerdem müssen Sie eine Obergrenze für die Anzahl der parallelen Tests festlegen. Wenn Sie die Anzahl der parallelen Tests erhöhen, reduziert 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. Wenn Sie zu viele Tests parallel ausführen, werden Versuche gestartet, ohne den Nutzen des Ergebnisses der noch laufenden Tests zu nutzen.

Zu Demonstrationszwecken können Sie die Anzahl der Tests auf 15 und die maximale Anzahl paralleler Tests auf 3 festlegen. Sie können mit verschiedenen Zahlen experimentieren. Dies kann jedoch zu einer längeren Abstimmungszeit und höheren Kosten führen.

trial_config

Der letzte Schritt besteht darin, die Option „Standard“ als Suchalgorithmus auszuwählen. Dieser Suchalgorithmus verwendet Google Vizier, um die Bayes'sche Optimierung für die Hyperparameter-Abstimmung durchzuführen. Weitere Informationen zu diesem Algorithmus

algorithm_config

Klicken Sie auf Weiter.

Schritt 3: Computing konfigurieren

Lassen Sie die ausgewählte Region unter Computing und Preise unverändert und konfigurieren Sie Worker-Pool 0 wie folgt.

Maschinentyp

Klicken Sie auf Training starten, um den Hyperparameter-Abstimmungsjob zu starten. Im Abschnitt "Training" der Konsole auf dem Tab HYPERPARAMETER-FUNKTIONSJOBS wird in etwa Folgendes angezeigt:

Hyperparam-Jobs

Wenn er abgeschlossen ist, können Sie auf den Jobnamen klicken und die Ergebnisse der Abstimmungstests ansehen.

Hyperparam-Ausgabe

🎉 Glückwunsch! 🎉

Sie haben gelernt, wie Sie mit Vertex AI Folgendes tun können:

  • Einen Hyperparameter-Abstimmungsjob 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 Modell trainieren, das mit einem beliebigen Framework erstellt wurde. Dazu verwenden Sie benutzerdefinierte Container.

Weitere Informationen zu den verschiedenen Teilen von Vertex finden Sie in der Dokumentation.

6. [Optional] Vertex SDK verwenden

Im vorherigen Abschnitt wurde gezeigt, wie der Hyperparameter-Abstimmungsjob über die Benutzeroberfläche gestartet wird. In diesem Abschnitt wird eine alternative Methode zum Senden des Hyperparameter-Abstimmungsjobs mithilfe der Vertex Python API beschrieben.

Erstellen Sie im Launcher ein TensorFlow 2-Notebook.

new_notebook

Importieren Sie das Vertex AI 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 folgenden Spezifikationen definieren. 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": 1
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human:hypertune"
    }
}]


# Dictionary 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'}

# 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)
}

Erstellen Sie als Nächstes ein CustomJob. Für das Staging müssen Sie {YOUR_BUCKET} durch einen Bucket in Ihrem Projekt ersetzen.

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans-sdk-job',
                              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-sdk-job',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=15,
    parallel_trial_count=3)

hp_job.run()

7. 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.

Instanz beenden

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“:

Speicher löschen