Effectuer le réglage des hyperparamètres dans Fabric (aperçu)
Le réglage des hyperparamètres est le processus de recherche des valeurs optimales pour les paramètres d’un modèle Machine Learning qui affectent ses performances. Il peut s’avérer difficile et fastidieux, en particulier lorsqu’il s’agit de modèles complexes et de jeux de données volumineux. Dans cet article, nous allons vous montrer comment effectuer le réglage des hyperparamètres dans Fabric.
Dans ce tutoriel, nous allons utiliser le jeu de données de logement californien, qui contient des informations sur la valeur médiane de la maison et d’autres fonctionnalités pour différents blocs de recensement en Californie. Une fois les données prédéfinies, nous allons entraîner un modèle SynapseML LightGBM pour prédire la valeur de la maison en fonction des fonctionnalités. Ensuite, nous allons utiliser FLAML, une bibliothèque AutoML rapide et légère, pour trouver les meilleurs hyperparamètres pour le modèle LightGBM. Enfin, nous allons comparer les résultats du modèle paramétré avec le modèle de base qui utilise les paramètres par défaut.
Conditions préalables
Obtenez un abonnement Microsoft Fabric . Vous pouvez également vous inscrire à une version d’évaluation gratuite de Microsoft Fabric .
Connectez-vous à Microsoft Fabric.
Utilisez le sélecteur d’expérience en bas à gauche de votre page d’accueil pour basculer vers Fabric.
- Créez un environnement Fabric ou vérifiez que vous êtes en cours d’exécution sur Fabric Runtime 1.2 (Spark 3.4 (ou version ultérieure) et Delta 2.4)
- Créez un nouveau bloc-notes.
- Attachez votre bloc-notes à un lakehouse. Sur le côté gauche de votre bloc-notes, sélectionnez Ajouter pour ajouter un lakehouse existant ou en créer un.
Préparer des jeux de données d’entraînement et de test
Dans cette section, nous préparons les jeux de données d’entraînement et de test pour le modèle LightGBM. Nous utilisons le jeu de données de logement californien de Sklearn. Nous créons un dataframe Spark à partir des données et utilisons un VectorAssembler pour combiner les fonctionnalités en une seule colonne vectorielle.
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)
Nous fractionlons ensuite de façon aléatoire les données en trois sous-ensembles : entraînement, validation et test, avec respectivement 85%, 12,75%et 2,25% des données. Nous utilisons les jeux d’entraînement et de validation pour le réglage des hyperparamètres et le jeu de tests pour l’évaluation du modèle.
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)
Configurer l’expérience ML
Configurer MLflow
Avant d’effectuer le réglage des hyperparamètres, nous devons définir une fonction d’apprentissage qui peut prendre différentes valeurs d’hyperparamètres et entraîner un modèle LightGBM sur les données d’entraînement. Nous devons également évaluer les performances du modèle sur les données de validation à l’aide du score R2, qui mesure la façon dont le modèle correspond aux données.
Pour ce faire, nous allons d’abord importer les modules nécessaires et configurer l’expérience MLflow. MLflow est une plateforme open source permettant de gérer le cycle de vie du Machine Learning de bout en bout. Il nous aide à suivre et comparer les résultats de différents modèles et hyperparamètres.
# 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)
Définir le niveau de journalisation
Ici, nous configurons le niveau de journalisation pour supprimer les sorties inutiles de la bibliothèque Synapse.ml, en gardant les journaux plus propres.
import logging
logging.getLogger('synapse.ml').setLevel(logging.ERROR)
Entraîner le modèle de référence
Ensuite, nous définissons la fonction d’apprentissage qui prend quatre hyperparamètres comme entrées : alpha, learningRate, numLeaves et numIterations. Il s’agit des hyperparamètres que nous voulons régler ultérieurement à l’aide de FLAML.
La fonction d’apprentissage prend également deux dataframes en tant qu’entrées : train_data et val_data, qui sont respectivement les jeux de données d’entraînement et de validation. La fonction d’apprentissage retourne deux résultats : le modèle entraîné et le score R2 sur les données de validation.
# 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
Enfin, nous utilisons la fonction d’apprentissage pour entraîner un modèle de base avec les valeurs par défaut des hyperparamètres. Nous évaluons également le modèle de base sur les données de test et imprimons le score R2.
# 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)
Effectuer le réglage des hyperparamètres avec FLAML
FLAML est une bibliothèque AutoML rapide et légère qui peut trouver automatiquement les meilleurs hyperparamètres pour un modèle et un jeu de données donnés. Il utilise une stratégie de recherche à faible coût qui s’adapte aux commentaires de la métrique d’évaluation. Dans cette section, nous allons utiliser FLAML pour régler les hyperparamètres du modèle LightGBM que nous avons défini dans la section précédente.
Définir la fonction tune
Pour utiliser FLAML, nous devons définir une fonction d’optimisation qui prend un dictionnaire de configuration comme entrée et retourne un dictionnaire avec la métrique d’évaluation comme clé et la valeur de métrique comme valeur.
Le dictionnaire de configuration contient les hyperparamètres que nous voulons paramétrer et leurs valeurs. La fonction tune utilise la fonction d’apprentissage que nous avons définie précédemment pour entraîner et évaluer le modèle avec la configuration donnée.
# 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}
Définir l’espace de recherche
Ensuite, nous devons définir l’espace de recherche pour les hyperparamètres que nous voulons régler. L’espace de recherche est un dictionnaire qui mappe les noms d’hyperparamètres aux plages de valeurs que nous voulons explorer. FLAML fournit des fonctions pratiques pour définir différents types de plages, comme uniform, loguniform et randint.
Dans ce cas, nous voulons régler les quatre hyperparamètres suivants : alpha, learningRate, numLeaves et 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),
}
Définir un essai des hyperparamètres
Enfin, nous devons définir une version d’évaluation des hyperparamètres qui utilisera FLAML pour optimiser les hyperparamètres. Nous devons passer la fonction tune, l’espace de recherche, le budget de temps, le nombre d’échantillons, le nom de la métrique, le mode et le niveau de détail à la fonction flaml.tune.run. Nous devons également démarrer une exécution MLflow imbriquée pour suivre les résultats de l’essai.
Le flaml.tune.run function
retourne un objet d’analyse qui contient la meilleure configuration et la meilleure valeur de métrique.
# 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,
)
Une fois la version d’évaluation terminée, nous pouvons afficher la meilleure configuration et la meilleure valeur de métrique à partir de l’objet d’analyse.
# 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"])
Comparer les résultats
Après avoir trouvé les meilleurs hyperparamètres avec FLAML, nous devons évaluer la quantité qu’ils améliorent les performances du modèle. Pour ce faire, nous utilisons la fonction d'entraînement pour créer un nouveau modèle avec les meilleurs hyperparamètres sur l'ensemble de données d'entraînement complet. Nous utilisons ensuite le jeu de données de test pour calculer le score R2 pour le nouveau modèle et le modèle de référence.
# 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)
Enregistrer le modèle final
Une fois que nous avons terminé notre essai d’hyperparamètre, nous pouvons maintenant enregistrer le modèle final paramétré en tant que modèle ML dans Fabric.
# 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.")