Partilhar via


Executar ajuste de hiperparâmetro na malha (visualização)

O ajuste de hiperparâmetros é o processo de encontrar os valores ideais para os parâmetros de um modelo de aprendizado de máquina que afetam seu desempenho. Pode ser desafiador e demorado, especialmente ao lidar com modelos complexos e grandes conjuntos de dados. Neste artigo, mostraremos como executar o ajuste de hiperparâmetros no Fabric.

Neste tutorial, usaremos o conjunto de dados de habitação da Califórnia, que contém informações sobre o valor médio da casa e outros recursos para diferentes blocos censitários na Califórnia. Assim que os dados estiverem preparados, treinaremos um modelo SynapseML LightGBM para prever o valor da casa com base nos recursos. Em seguida, usaremos FLAML, uma biblioteca AutoML rápida e leve, para encontrar os melhores hiperparâmetros para o modelo LightGBM. Finalmente, vamos comparar os resultados do modelo ajustado com o modelo de linha de base que usa os parâmetros padrão.

Importante

Este recurso está em pré-visualização.

Pré-requisitos

  • Obtenha uma assinatura do Microsoft Fabric. Ou inscreva-se para uma avaliação gratuita do Microsoft Fabric.

  • Entre no Microsoft Fabric.

  • Use o seletor de experiência no lado esquerdo da sua página inicial para alternar para a experiência Synapse Data Science.

    Captura de tela do menu do seletor de experiência, mostrando onde selecionar Ciência de Dados.

  • Crie um novo ambiente de malha ou verifique se você está executando no Fabric Runtime 1.2 (Spark 3.4 (ou superior) e Delta 2.4)
  • Crie um novo bloco de notas.
  • Ligue o seu bloco de notas a uma casa no lago. No lado esquerdo do seu bloco de notas, selecione Adicionar para adicionar uma lakehouse existente ou criar uma nova.

Preparar conjuntos de dados de treinamento e teste

Nesta seção, preparamos os conjuntos de dados de treinamento e teste para o modelo LightGBM. Usamos o conjunto de dados de habitação da Califórnia da Sklearn. Criamos um dataframe do Spark a partir dos dados e usamos um VectorAssembler para combinar os recursos em uma única coluna vetorial.

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)

Em seguida, dividimos aleatoriamente os dados em três subconjuntos: treinamento, validação e teste, com 85%, 12,75% e 2,25% dos dados, respectivamente. Usamos os conjuntos de treinamento e validação para ajuste de hiperparâmetros e o conjunto de testes para avaliação de modelos.

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)

Configurar a experiência de ML

Configurar MLflow

Antes de realizarmos o ajuste de hiperparâmetros, precisamos definir uma função de trem que possa ter diferentes valores de hiperparâmetros e treinar um modelo LightGBM nos dados de treinamento. Também precisamos avaliar o desempenho do modelo nos dados de validação usando a pontuação R2, que mede o quão bem o modelo se ajusta aos dados.

Para fazer isso, primeiro importamos os módulos necessários e configuramos o experimento MLflow. O MLflow é uma plataforma open source para gerir o ciclo de vida completo de machine learning. Ele nos ajuda a rastrear e comparar os resultados de diferentes modelos e hiperparâmetros.

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

Definir nível de registo

Aqui, configuramos o nível de log para suprimir a saída desnecessária da biblioteca de Synapse.ml, mantendo os logs mais limpos.

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

Modelo de linha de base do trem

Em seguida, definimos a função train que usa quatro hiperparâmetros como entradas: alpha, learningRate, numLeaves e numIterations. Estes são os hiperparâmetros que queremos ajustar mais tarde usando FLAML.

A função train também usa dois dataframes como entradas: train_data e val_data, que são os conjuntos de dados de treinamento e validação, respectivamente. A função train retorna duas saídas: o modelo treinado e a pontuação R2 nos dados de validação.

# 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

Finalmente, usamos a função train para treinar um modelo de linha de base com os valores padrão dos hiperparâmetros. Também avaliamos o modelo de linha de base nos dados do teste e imprimimos a pontuação 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)

Execute o ajuste de hiperparâmetros com FLAML

FLAML é uma biblioteca AutoML rápida e leve que pode encontrar automaticamente os melhores hiperparâmetros para um determinado modelo e conjunto de dados. Utiliza uma estratégia de pesquisa de baixo custo que se adapta ao feedback da métrica de avaliação. Nesta seção, usaremos FLAML para ajustar os hiperparâmetros do modelo LightGBM que definimos na seção anterior.

Definir tune function

Para usar FLAML, precisamos definir uma função tune que usa um dicionário de configuração como entrada e retorna um dicionário com a métrica de avaliação como a chave e o valor da métrica como o valor.

O dicionário config contém os hiperparâmetros que queremos ajustar e seus valores. A função tune usará a função train que definimos anteriormente para treinar e avaliar o modelo com a configuração dada.

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

Definir search space

Em seguida, precisamos definir o espaço de pesquisa para os hiperparâmetros que queremos ajustar. O espaço de pesquisa é um dicionário que mapeia os nomes dos hiperparâmetros para os intervalos de valores que queremos explorar. FLAML fornece algumas funções convenientes para definir diferentes tipos de intervalos, tais como uniforme, loguniform, e randint.

Neste caso, queremos ajustar os seguintes quatro hiperparâmetros: alpha, learningRate, numLeaves e 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),
}

Definir hyperparameter trial

Finalmente, precisamos definir um ensaio de hiperparâmetros que usará FLAML para otimizar os hiperparâmetros. Precisamos passar a função tune, o espaço de pesquisa, o orçamento de tempo, o número de amostras, o nome da métrica, o modo e o nível de verbosidade para a função flaml.tune.run. Também precisamos iniciar uma execução aninhada do MLflow para acompanhar os resultados do ensaio.

O flaml.tune.run function retornará um objeto de análise que contém a melhor configuração e o melhor valor métrico.

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

Após a conclusão do teste, podemos visualizar a melhor configuração e o melhor valor métrico do objeto de análise.

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

Comparar resultados

Depois de encontrar os melhores hiperparâmetros com FLAML, precisamos avaliar o quanto eles melhoram o desempenho do modelo. Para fazer isso, usamos a função train para criar um novo modelo com os melhores hiperparâmetros no conjunto de dados de treinamento completo. Em seguida, usamos o conjunto de dados de teste para calcular a pontuação R2 para o novo modelo e o modelo de linha de base.

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

Guardar modelo final

Depois de concluir nossa avaliação de hiperparâmetros, agora podemos salvar o modelo final ajustado como um modelo de ML no 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.")