Dela via


Utföra hyperparameterjustering i Infrastrukturresurser (förhandsversion)

Hyperparameterjustering är processen att hitta de optimala värdena för parametrarna för en maskininlärningsmodell som påverkar dess prestanda. Det kan vara utmanande och tidskrävande, särskilt när du hanterar komplexa modeller och stora datamängder. I den här artikeln visar vi hur du utför hyperparameterjustering i Infrastrukturresurser.

I den här självstudien använder vi datauppsättningen För bostäder i Kalifornien, som innehåller information om medianvärdet för hus och andra funktioner för olika folkräkningsblock i Kalifornien. När data har förberetts tränar vi en SynapseML LightGBM-modell för att förutsäga husvärdet baserat på funktionerna. Sedan använder vi FLAML, ett snabbt och enkelt AutoML-bibliotek, för att hitta de bästa hyperparametrar för LightGBM-modellen. Slutligen jämför vi resultatet av den finjusterade modellen med baslinjemodellen som använder standardparametrarna.

Viktigt!

Den här funktionen är i förhandsversion.

Förutsättningar

  • Skapa en ny Infrastrukturmiljö eller se till att du körs på Fabric Runtime 1.2 (Spark 3.4 (eller senare) och Delta 2.4)
  • Skapa en ny notebook-fil.
  • Bifoga anteckningsboken till ett sjöhus. Till vänster i anteckningsboken väljer du Lägg till för att lägga till ett befintligt lakehouse eller skapa ett nytt.

Förbereda tränings- och testdatauppsättningar

I det här avsnittet förbereder vi tränings- och testdatauppsättningarna för LightGBM-modellen. Vi använder kaliforniens bostadsdatauppsättning från Sklearn. Vi skapar en Spark-dataram från data och använder en VectorAssembler för att kombinera funktionerna i en enda vektorkolumn.

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)

Sedan delar vi upp data slumpmässigt i tre delmängder: träning, validering och test, med 85 %, 12,75 % respektive 2,25 % av data. Vi använder tränings- och valideringsuppsättningarna för justering av hyperparametrar och testuppsättningen för modellutvärdering.

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)

Konfigurera ML-experimentet

Konfigurera MLflow

Innan vi utför hyperparameterjustering måste vi definiera en träningsfunktion som kan ta olika värden för hyperparametrar och träna en LightGBM-modell på träningsdata. Vi måste också utvärdera modellens prestanda på valideringsdata med R2-poängen, som mäter hur väl modellen passar data.

För att göra detta importerar vi först de moduler som behövs och konfigurerar MLflow-experimentet. MLflow är en plattform med öppen källkod för hantering av maskininlärningslivscykeln från början till slut. Det hjälper oss att spåra och jämföra resultaten från olika modeller och hyperparametrar.

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

Ange loggningsnivå

Här konfigurerar vi loggningsnivån för att förhindra onödiga utdata från Synapse.ml-biblioteket och hålla loggarna renare.

import logging
 
logging.getLogger('synapse.ml').setLevel(logging.ERROR)

Träna baslinjemodell

Därefter definierar vi träningsfunktionen som tar fyra hyperparametrar som indata: alfa, learningRate, numLeaves och numIterations. Det här är de hyperparametrar som vi vill justera senare med FLAML.

Träningsfunktionen tar också två dataramar som indata: train_data och val_data, som är tränings- respektive valideringsdatauppsättningarna. Funktionen train returnerar två utdata: den tränade modellen och R2-poängen för valideringsdata.

# 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

Slutligen använder vi träningsfunktionen för att träna en baslinjemodell med standardvärdena för hyperparametrar. Vi utvärderar även baslinjemodellen på testdata och skriver ut R2-poängen.

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

Utföra hyperparameterjustering med FLAML

FLAML är ett snabbt och enkelt AutoML-bibliotek som automatiskt kan hitta de bästa hyperparametrar för en viss modell och datauppsättning. Den använder en strategi för lågkostnadssökning som anpassar sig till feedbacken från utvärderingsmåttet. I det här avsnittet använder vi FLAML för att finjustera hyperparametrar för LightGBM-modellen som vi definierade i föregående avsnitt.

Definiera tune-funktion

För att använda FLAML måste vi definiera en justeringsfunktion som tar en konfigurationsordlista som indata och returnerar en ordlista med utvärderingsmåttet som nyckel och måttvärdet som värde.

Konfigurationsordlistan innehåller de hyperparametrar som vi vill justera och deras värden. Tune-funktionen använder den träningsfunktion som vi definierade tidigare för att träna och utvärdera modellen med den angivna konfigurationen.

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

Definiera sökutrymme

Därefter måste vi definiera sökutrymmet för de hyperparametrar som vi vill finjustera. Sökutrymmet är en ordlista som mappar hyperparameternamnen till de värden som vi vill utforska. FLAML tillhandahåller några praktiska funktioner för att definiera olika typer av intervall, till exempel uniform, loguniform och randint.

I det här fallet vill vi justera följande fyra hyperparametrar: alfa, learningRate, numLeaves och 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),
}

Definiera utvärderingsversion av hyperparameter

Slutligen måste vi definiera en utvärderingsversion av hyperparametern som använder FLAML för att optimera hyperparametrar. Vi måste skicka tune-funktionen, sökutrymmet, tidsbudgeten, antalet exempel, måttnamnet, läget och verbositetsnivån till funktionen flaml.tune.run. Vi måste också starta en kapslad MLflow-körning för att spåra resultatet av utvärderingsversionen.

flaml.tune.run function Returnerar ett analysobjekt som innehåller den bästa konfigurationen och det bästa måttvärdet.

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

När utvärderingsversionen är klar kan vi visa den bästa konfigurationen och det bästa måttvärdet från analysobjektet.

# 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"])

Jämför resultat

När vi har hittat de bästa hyperparametrarna med FLAML måste vi utvärdera hur mycket de förbättrar modellens prestanda. För att göra detta använder vi träningsfunktionen för att skapa en ny modell med de bästa hyperparametrar på den fullständiga träningsdatauppsättningen. Sedan använder vi testdatauppsättningen för att beräkna R2-poängen för både den nya modellen och baslinjemodellen.

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

Spara den slutliga modellen

När vi har slutfört utvärderingsversionen av hyperparametern kan vi nu spara den slutgiltiga, finjusterade modellen som en ML-modell i Infrastrukturresurser.

# 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.")