Parallele Hyperparameter Optimization (HPO) auf Container Runtime für ML

Die Snowflake ML Hyperparameter Optimization (HPO) API ist ein modellunabhängiges Framework, das ein effizientes, parallelisiertes Hyperparameter-Tuning von Modellen mit gängigen Tuning-Algorithmen ermöglicht.

Heute ist diese API für die Verwendung innerhalb eines Snowflake Notebooks verfügbar, das so konfiguriert ist, dass es Container Runtime auf Snowpark Container Services (SPCS) verwendet. Nachdem Sie ein solches Notebook erstellt haben, können Sie folgende Aufgaben ausführen:

  • Trainieren eines Modells mit einem beliebigen Open-Source-Paket und Verwenden dieser API, um den Hyperparameter-Tuning-Prozess zu verteilen

  • Trainieren eines Modells mit APIs für verteiltes Training von Snowflake ML und Skalieren von HPO bei gleichzeitiger Skalierung jedes Trainingslaufs

Der vom Notebook initiierte HPO-Workload wird innerhalb von Snowpark Container Services auf den CPU- oder GPU-Instanzen ausgeführt und skaliert bis zu den Kernen (CPUs oder GPUs), die auf einem einzelnen Knoten im SPCS-Computepool verfügbar sind.

Die parallelisierte HPO-API bietet die folgenden Vorteile:

  • Eine einzige API, die automatisch alle komplexen Aufgaben der Verteilung des Trainings auf mehrere Ressourcen übernimmt

  • Die Möglichkeit, mit praktisch jedem Framework oder Algorithmus zu trainieren, unter Verwendung von Open-Source-ML-Frameworks oder der Modellierungs-APIs von Snowflake ML

  • Eine Auswahl an Tuning- und Sampling-Optionen, einschließlich Bayes’scher und zufälliger Suchalgorithmen sowie verschiedener kontinuierlicher und nicht-kontinuierlicher Sampling-Funktionen

  • Enge Datenintegration mit dem Rest von Snowflake, z. B. effiziente Datenaufnahme (Ingestion) über Snowflake-Datensets oder -Datenframes und automatische Erfassung der ML-Datenherkunft

Beispiele

Dieses Beispiel veranschaulicht einen typischen HPO-Anwendungsfall, bei dem zunächst Daten aus einer Snowflake-Tabelle über Container Runtime DataConnector API eingelesen werden. Anschließend wird eine Trainingsfunktion definiert, die ein XGBoost-Modell erstellt. Die Tuner-Weboberfläche bietet die Tuning-Funktionalität, basierend auf der gegebenen Trainingsfunktion und dem Suchraum.

from snowflake.ml.modeling.tune import get_tuner_context
from snowflake.ml.modeling import tune

# Define a training function, with any models you choose within it.
def train_func():
    # A context object provided by HPO API to expose data for the current HPO trial
    tuner_context = get_tuner_context()
    config = tuner_context.get_hyper_params()
    dm = tuner_context.get_dataset_map()

    model = xgb.XGBClassifier(**config, random_state=42)
    model.fit(dm["x_train"].to_pandas(), dm["y_train"].to_pandas())
    accuracy = accuracy_score(
        dm["y_train"].to_pandas(), model.predict(dm["x_train"].to_pandas())
    )
    tuner_context.report(metrics={"accuracy": accuracy}, model=model)

tuner = tune.Tuner(
    train_func=train_func,
    search_space={
        "n_estimators": tune.uniform(50, 200),
        "max_depth": tune.uniform(3, 10),
        "learning_rate": tune.uniform(0.01, 0.3),
    },
    tuner_config=tune.TunerConfig(
        metric="accuracy",
        mode="max",
        search_alg=search_algorithm.BayesOpt(),
        num_trials=2,
        max_concurrent_trials=1,
    ),
)

tuner_results = tuner.run(dataset_map=dataset_map)
# Access the best result info with tuner_results.best_result
Copy

Die erwartete Ausgabe sieht ungefähr wie folgt aus:

accuracy  should_checkpoint  trial_id   time_total_s  config/learning_rate  config/max_depth  config/n_estimators
1.0       True               ec632254   7.161971      0.118617              9.655             159.799091

Das Objekt tuner_results enthält alle Ergebnisse, das beste Modell und den besten Modellpfad.

print(tuner_results.results)
print(tuner_results.best_model)
print(tuner_results.best_model_path)
Copy

Übersicht zu API

Die HPO-API befindet sich im Namespace snowflake.ml.modeling.tune. Die wichtigste HPO-API ist die tune.Tuner-Klasse. Wenn Sie diese Klasse instanziieren, geben Sie Folgendes an:

  • Eine Trainingsfunktion, die zu einem Modell passt

  • Einen Suchraum (tune.SearchSpace), der die Methode zur Auswahl von Hyperparametern definiert

  • Ein Tuner-Konfigurationsobjekt (tune.TunerConfig), das den Suchalgorithmus, die zu optimierende Metrik und die Anzahl der Versuche definiert

Nachdem Sie Tuner instanziiert haben, rufen Sie die Methode run mit einer Datensetzuordnung auf (die für jedes Eingabedatenset eine DataConnector angibt), um den Tuning-Prozess zu starten.

Für weitere Informationen führen Sie die folgenden Python-Anweisungen aus, um die Dokumentation zu jeder Klasse abzurufen:

from snowflake.ml.modeling import tune

help(tune.Tuner)
help(tune.TunerConfig)
help(tune.SearchSpace)
Copy

Einschränkungen

Die Bayes’sche Optimierung funktioniert nur mit der einheitlichen Sampling-Funktion. Die Bayes’sche Optimierung stützt sich auf Gauß’sche Prozesse als Ersatzmodelle und erfordert daher kontinuierliche Suchräume. Sie ist nicht kompatibel mit diskreten Parametern, die mit den Methoden tune.randint oder tune.choice ausgewählt werden. Um diese Beschränkung zu umgehen, verwenden Sie entweder tune.uniform und wandeln den Parameter innerhalb der Trainingsfunktion um, oder Sie wechseln zu einem Sampling-Algorithmus, der sowohl diskrete als auch kontinuierliche Räume verarbeitet, wie z. B. tune.RandomSearch.

Problembehandlung

Fehlermeldung

Mögliche Ursachen

Mögliche Lösungen

Ungültige Suchraumkonfiguration: BayesOpt verlangt, dass alle Sampling-Funktionen vom Typ „Uniform“ sind.

Die Bayes’sche Optimierung funktioniert nur mit einheitlichem Sampling, nicht mit diskreten Stichproben. (Siehe Einschränkungen oben.)

  • Verwenden Sie tune.uniform und geben Sie das Ergebnis in Ihre Trainingsfunktion ein.

  • Wechseln Sie zum Algorithmus RandomSearch, der sowohl diskrete als auch nicht-diskrete Stichproben akzeptiert.

Unzureichende CPU-Ressourcen. Benötigt: 16, Verfügbar: 8. Kann sich auf CPU oder GPU beziehen. Die Anzahl der erforderlichen und verfügbaren Ressourcen kann unterschiedlich sein.

max_concurrent_trials ist auf einen Wert eingestellt, der höher als die verfügbaren Kerne ist.

Die vollständige Fehlermeldung beschreibt mehrere Optionen, die Sie ausprobieren können.