Hyperparameter-Optimierung in Fabric durchführen (Vorschau)
Die Hyperparameter-Optimierung ist der Prozess der Suche nach den optimalen Werten für die Parameter eines Machine Learning-Modells, die sich auf die Leistung auswirken. Dies kann insbesondere beim Umgang mit komplexen Modellen und großen Datasets schwierig und zeitaufwändig sein, . In diesem Artikel zeigen wir Ihnen, wie Sie die Hyperparameter-Optimierung in Fabric durchführen.
In diesem Lernprogramm verwenden wir das California Housing DataSet, das Informationen über den durchschnittlichen Wert des Hauses und andere Features für verschiedene Erhebungsblöcke in Kalifornien enthält. Sobald die Daten vorbereitet wurden, trainieren wir ein SynapseML LightGBM-Modell, um auf Basis der Features den Wert des Hauses vorherzusagen. Als Nächstes verwenden wir FLAML, eine schnelle und einfache AutoML-Bibliothek, um die besten Hyperparameter für das LightGBM-Modell zu ermitteln. Schließlich vergleichen wir die Ergebnisse des optimierten Modells mit dem Baselinemodell, das die Standardparameter verwendet.
Wichtig
Dieses Feature befindet sich in der Vorschau.
Voraussetzungen
Erwerben Sie ein Microsoft Fabric-Abonnement. Registrieren Sie sich alternativ für eine kostenlose Microsoft Fabric-Testversion.
Melden Sie sich bei Microsoft Fabric an.
Wechseln Sie zur Synapse-Data Science-Benutzeroberfläche, indem Sie den Umschalter für die Benutzeroberfläche auf der linken Seite Ihrer Homepage verwenden.
- Erstellen Sie eine neue Fabric-Umgebung, oder stellen Sie sicher, dass Sie mit der Fabric Runtime 1.2 (Spark 3.4 (oder höher) und Delta 2.4) arbeiten
- Erstellen Sie ein neues Notebook.
- Verbinden Sie Ihr Notebook mit einem Lakehouse. Wählen Sie auf der linken Seite Ihres Notebooks Hinzufügen aus, um ein vorhandenes Lakehouse hinzuzufügen oder ein neues zu erstellen.
Erstellen von Trainings- und Testdatensätzen
In diesem Abschnitt bereiten wir die Schulungs- und Testdatensätze für das LightGBM-Modell vor. Wir verwenden das California Housing DataSet von Sklearn. Wir erstellen einen Spark-DataFrame aus den Daten und verwenden einen VectorAssembler, um die Features in einer einzelnen Vektorspalte zu kombinieren.
from sklearn.datasets import fetch_california_housing
from pyspark.sql import SparkSession
# Load the Scikit-learn California Housing dataset
sklearn_dataset = fetch_california_housing()
# Convert the Scikit-learn dataset to a Pandas DataFrame
import pandas as pd
pandas_df = pd.DataFrame(sklearn_dataset.data, columns=sklearn_dataset.feature_names)
pandas_df['target'] = sklearn_dataset.target
# Create a Spark DataFrame from the Pandas DataFrame
spark_df = spark.createDataFrame(pandas_df)
# Display the data
display(spark_df)
Anschließend teilen wir die Daten mit dem Zufallsfaktor in drei Teilmengen auf: Training, Validierung und Test, mit 85%, 12,75% und 2,25% der Daten. Wir verwenden die Trainings- und Validierungssätze für die Hyperparameter-Optimierung und den Testsatz für die Modellauswertung.
from pyspark.ml.feature import VectorAssembler
# Combine features into a single vector column
featurizer = VectorAssembler(inputCols=sklearn_dataset.feature_names, outputCol="features")
data = featurizer.transform(spark_df)["target", "features"]
# Split the data into training, validation, and test sets
train_data, test_data = data.randomSplit([0.85, 0.15], seed=41)
train_data_sub, val_data_sub = train_data.randomSplit([0.85, 0.15], seed=41)
Einrichten des ML-Experiments
Konfigurieren von MLflow
Bevor wir die Hyperparameter-Optimierung durchführen, müssen wir eine Trainingsfunktion definieren, die verschiedene Werte von Hyperparametern annehmen und ein LightGBM-Modell mit den Trainingsdaten analysieren kann. Darüber hinaus müssen wir die Leistung des Modells für die Validierungsdaten anhand des R2-Scores bewerten, der aussagt, wie gut das Modell zu den Daten passt.
Dazu importieren wir zunächst die erforderlichen Module und richten das MLflow-Experiment ein. MLflow ist eine Open-Source-Plattform für die Verwaltung des gesamten Machine Learning-Lebenszyklus. Es hilft uns, die Ergebnisse verschiedener Modelle und Hyperparameter nachzuverfolgen und zu vergleichen.
# Import MLflow and set up the experiment name
import mlflow
mlflow.set_experiment("flaml_tune_sample")
# Enable automatic logging of parameters, metrics, and models
mlflow.autolog(exclusive=False)
Festlegen des Protokolliergrads
Hier konfigurieren wir die Protokollierungsstufe, um unnötige Ausgaben aus der Synapse.ml-Bibliothek zu unterdrücken und die Protokolle sauberer zu halten.
import logging
logging.getLogger('synapse.ml').setLevel(logging.ERROR)
Trainieren eines Baselinemodells
Als Nächstes definieren wir die Trainingsfunktion, die vier Hyperparameter als Eingaben akzeptiert: Alpha, LearningRate, NumLeaves und NumIterations. Dies sind die Hyperparameter, die wir später mithilfe von FLAML optimieren möchten.
Die Trainings-Funktion verwendet auch zwei DataFrames als Eingaben: train_data und val_data, die jeweils die Trainings- und Validierungsdatensätze sind. Die Trainings-Funktion gibt zwei Ausgaben zurück: das trainierte Modell und die R2-Bewertung für die Validierungsdaten.
# Import LightGBM and RegressionEvaluator
from synapse.ml.lightgbm import LightGBMRegressor
from pyspark.ml.evaluation import RegressionEvaluator
def train(alpha, learningRate, numLeaves, numIterations, train_data=train_data_sub, val_data=val_data_sub):
"""
This train() function:
- takes hyperparameters as inputs (for tuning later)
- returns the R2 score on the validation dataset
Wrapping code as a function makes it easier to reuse the code later for tuning.
"""
with mlflow.start_run() as run:
# Capture run_id for prediction later
run_details = run.info.run_id
# Create a LightGBM regressor with the given hyperparameters and target column
lgr = LightGBMRegressor(
objective="quantile",
alpha=alpha,
learningRate=learningRate,
numLeaves=numLeaves,
labelCol="target",
numIterations=numIterations,
dataTransferMode="bulk"
)
# Train the model on the training data
model = lgr.fit(train_data)
# Make predictions on the validation data
predictions = model.transform(val_data)
# Define an evaluator with R2 metric and target column
evaluator = RegressionEvaluator(predictionCol="prediction", labelCol="target", metricName="r2")
# Compute the R2 score on the validation data
eval_metric = evaluator.evaluate(predictions)
mlflow.log_metric("r2_score", eval_metric)
# Return the model and the R2 score
return model, eval_metric, run_details
Schließlich verwenden wir die Trainings-Funktion, um ein Baselinemodell mit den Standardwerten der Hyperparameter zu trainieren. Außerdem bewerten wir das Baselinemodell für die Testdaten und drucken die R2-Bewertung aus.
# Train the baseline model with the default hyperparameters
init_model, init_eval_metric, init_run_id = train(alpha=0.2, learningRate=0.3, numLeaves=31, numIterations=100, train_data=train_data, val_data=test_data)
# Print the R2 score of the baseline model on the test data
print("R2 of initial model on test dataset is: ", init_eval_metric)
Durchführen der Hyperparameter-Optimierung mit FLAML
FLAML ist eine schnelle und einfache AutoML-Bibliothek, die automatisch die besten Hyperparameter für ein bestimmtes Modell und DataSet finden kann. Es verwendet eine kostengünstige Suchstrategie, die sich an das Feedback der Auswertungsmetrik anpasst. In diesem Abschnitt verwenden wir FLAML, um die Hyperparameter des LightGBM-Modells zu optimieren, die wir im vorherigen Abschnitt definiert haben.
Definieren der Optimierungs-Funktion
Um FLAML zu verwenden, müssen wir eine Optimierungs-Funktion definieren, die ein config-Schlüsselverzeichnis als Eingabe verwendet und ein Schlüsselverzeichnis mit der Auswertungsmetrik als Schlüssel und dem Metrikwert als Wert zurückgibt.
Das config-Schlüsselverzeichnis enthält die Hyperparameter, die wir optimieren möchten, und deren Werte. Die Optimierungs-Funktion verwendet die Trainings-Funktion, die wir zuvor definiert haben, um das Modell mit der angegebenen Konfiguration zu trainieren und auszuwerten.
# Import FLAML
import flaml
# Define the tune function
def flaml_tune(config):
# Train and evaluate the model with the given config
_, metric, run_id = train(**config)
# Return the evaluation metric and its value
return {"r2": metric}
Definieren des Suchbereichs
Als Nächstes müssen wir den Suchbereich für die Hyperparameter definieren, die wir optimieren möchten. Der Suchbereich ist ein Schlüsselverzeichnis, das die Hyperparameter-Namen den Werte-Bereichen zuordnet, die wir untersuchen möchten. FLAML bietet einige praktische Funktionen für die Definition verschiedener Arten von Bereichen, z. B. Uniform, Loguniform und Randint.
In diesem Fall möchten wir die folgenden vier Hyperparameter optimieren: Alpha, LearningRate, NumLeaves und NumIterations.
# Define the search space
params = {
# Alpha is a continuous value between 0 and 1
"alpha": flaml.tune.uniform(0, 1),
# Learning rate is a continuous value between 0.001 and 1
"learningRate": flaml.tune.uniform(0.001, 1),
# Number of leaves is an integer value between 30 and 100
"numLeaves": flaml.tune.randint(30, 100),
# Number of iterations is an integer value between 100 and 300
"numIterations": flaml.tune.randint(100, 300),
}
Definieren von Hyperparametern
Abschließend müssen wir eine Hyperparameter-Testversion definieren, die FLAML zur Optimierung der Hyperparameter verwendet. Wir müssen die Optimierungs-Funktion, den Suchbereich, das Zeitbudget, die Anzahl der Beispiele, den Metrik-Namen, den Modus und die Ausführlichkeitsebene an die Funktion flaml.tune.run weitergeben. Außerdem müssen wir einen geschachtelten MLflow-Lauf starten, um die Ergebnisse der Testversion nachzuverfolgen.
flaml.tune.run function
wird ein Analyseobjekt zurückgeben, das die beste Konfiguration und den besten Metrikwert enthält.
# Start a nested MLflow run
with mlflow.start_run(nested=True, run_name="Child Run: "):
# Run the hyperparameter trial with FLAML
analysis = flaml.tune.run(
# Pass the tune function
flaml_tune,
# Pass the search space
params,
# Set the time budget to 120 seconds
time_budget_s=120,
# Set the number of samples to 100
num_samples=100,
# Set the metric name to r2
metric="r2",
# Set the mode to max (we want to maximize the r2 score)
mode="max",
# Set the verbosity level to 5
verbose=5,
)
Nachdem die Testversion abgeschlossen ist, können wir die beste Konfiguration und den besten Metrikwert aus dem Analyseobjekt anzeigen.
# Get the best config from the analysis object
flaml_config = analysis.best_config
# Print the best config
print("Best config: ", flaml_config)
print("Best score on validation data: ", analysis.best_result["r2"])
Vergleichen der Ergebnisse
Nachdem wir die besten Hyperparameter mit FLAML gefunden haben, müssen wir auswerten, wie viel dieselben die Modellleistung verbessern. Dazu verwenden wir die Trainings-Funktion, um ein neues Modell mit den besten Hyperparametern im ganzen Trainings-DataSet zu erstellen. Anschließend verwenden wir den Test-DataSet, um die R2-Bewertung sowohl für das neue Modell als auch für das Baselinemodell zu berechnen.
# Train a new model with the best hyperparameters
flaml_model, flaml_metric, flaml_run_id = train(train_data=train_data, val_data=test_data, **flaml_config)
# Print the R2 score of the baseline model on the test dataset
print("On the test dataset, the initial (untuned) model achieved R^2: ", init_eval_metric)
# Print the R2 score of the new model on the test dataset
print("On the test dataset, the final flaml (tuned) model achieved R^2: ", flaml_metric)
Endgültiges Modell speichern
Nachdem wir unsere Hyperparameter-Testversion abgeschlossen haben, können wir nun das endgültige, abgestimmte Modell als ML-Modell in Fabric speichern.
# Specify the model name and the path where you want to save it in the registry
model_name = "housing_model" # Replace with your desired model name
model_path = f"runs:/{flaml_run_id}/model"
# Register the model to the MLflow registry
registered_model = mlflow.register_model(model_uri=model_path, name=model_name)
# Print the registered model's name and version
print(f"Model '{registered_model.name}' version {registered_model.version} registered successfully.")