Compartir vía


Ajuste de hiperparámetros (versión preliminar)

El ajuste de hiperparámetros es el proceso de búsqueda de los valores óptimos para los parámetros que el modelo de aprendizaje automático no ha aprendido durante el entrenamiento, sino que lo establece el usuario antes de que comience el proceso de entrenamiento. Estos parámetros se conocen normalmente como hiperparámetros y ejemplos incluyen la velocidad de aprendizaje, el número de capas ocultas en una red neuronal, la intensidad de regularización y el tamaño del lote.

El rendimiento de un modelo de aprendizaje automático puede ser altamente sensible a la elección de hiperparámetros y el conjunto óptimo de hiperparámetros puede variar considerablemente en función del problema y el conjunto de datos específicos. Por lo tanto, el ajuste de hiperparámetros es un paso crítico en la canalización de aprendizaje automático, ya que puede tener un impacto significativo en el rendimiento de la precisión y la generalización del modelo.

En Fabric, los científicos de datos pueden aprovechar FLAML, una biblioteca ligera de Python para una automatización eficaz de las operaciones de aprendizaje automático e inteligencia artificial, para sus requisitos de ajuste de hiperparámetros. En los cuadernos de Fabric, los usuarios pueden llamar a flaml.tune para optimizar hiperparámetros de manera económica.

Importante

Esta característica se encuentra en versión preliminar.

Optimización de flujo de trabajo

Hay tres pasos esenciales para usar flaml.tune para finalizar una tarea de optimización básica:

  1. Especifique el objetivo de ajuste con respecto a los hiperparámetros.
  2. Especifique un espacio de búsqueda de los hiperparámetros.
  3. Especifique restricciones de optimización, incluidas las restricciones del presupuesto de recursos para realizar la optimización, las restricciones de las configuraciones o/o las restricciones de una métrica determinada (o varias).

Objetivo de optimización

El primer paso es especificar el objetivo de ajuste. Para ello, primero debe especificar el procedimiento de evaluación con respecto a los hiperparámetros de una función definida por el usuario evaluation_function. La función requiere una configuración de hiperparámetros como entrada. Puede simplemente devolver un valor de métrica en forma escalar o devolver un diccionario con pares de nombre y valor de métrica.

En el ejemplo siguiente, podemos definir una función de evaluación con respecto a 2 hiperparámetros denominados x y y.

import time

def evaluate_config(config: dict):
    """evaluate a hyperparameter configuration"""
    score = (config["x"] - 85000) ** 2 - config["x"] / config["y"]


    faked_evaluation_cost = config["x"] / 100000
    time.sleep(faked_evaluation_cost)
    # we can return a single float as a score on the input config:
    # return score
    # or, we can return a dictionary that maps metric name to metric value:
    return {"score": score, "evaluation_cost": faked_evaluation_cost, "constraint_metric": config["x"] * config["y"]}

Espacio de búsqueda

A continuación, especificaremos el espacio de búsqueda de hiperparámetros. En el espacio de búsqueda, debe especificar valores válidos para sus hiperparámetros y cómo se muestrean estos valores (por ejemplo, a partir de una distribución uniforme o una distribución log-uniforme). En el ejemplo siguiente, podemos proporcionar el espacio de búsqueda para los hiperparámetros x y y. Los valores válidos para ambos son enteros que van desde [1, 100 000]. Estos hiperparámetros se muestrean uniformemente en los intervalos especificados.

from flaml import tune

# construct a search space for the hyperparameters x and y.
config_search_space = {
    "x": tune.lograndint(lower=1, upper=100000),
    "y": tune.randint(lower=1, upper=100000)
}

# provide the search space to tune.run
tune.run(..., config=config_search_space, ...)

Con FLAML, los usuarios pueden personalizar el dominio para un hiperparámetros determinado. Esto permite a los usuarios especificar un tipo y un intervalo válido de para el muestreo de parámetros. FLAML admite los siguientes tipos de hiperparámetros: float, entero y categórico. Puede ver este ejemplo a continuación para dominios usados habitualmente:

config = {
    # Sample a float uniformly between -5.0 and -1.0
    "uniform": tune.uniform(-5, -1),

    # Sample a float uniformly between 3.2 and 5.4,
    # rounding to increments of 0.2
    "quniform": tune.quniform(3.2, 5.4, 0.2),

    # Sample a float uniformly between 0.0001 and 0.01, while
    # sampling in log space
    "loguniform": tune.loguniform(1e-4, 1e-2),

    # Sample a float uniformly between 0.0001 and 0.1, while
    # sampling in log space and rounding to increments of 0.00005
    "qloguniform": tune.qloguniform(1e-4, 1e-1, 5e-5),

    # Sample a random float from a normal distribution with
    # mean=10 and sd=2
    "randn": tune.randn(10, 2),

    # Sample a random float from a normal distribution with
    # mean=10 and sd=2, rounding to increments of 0.2
    "qrandn": tune.qrandn(10, 2, 0.2),

    # Sample a integer uniformly between -9 (inclusive) and 15 (exclusive)
    "randint": tune.randint(-9, 15),

    # Sample a random uniformly between -21 (inclusive) and 12 (inclusive (!))
    # rounding to increments of 3 (includes 12)
    "qrandint": tune.qrandint(-21, 12, 3),

    # Sample a integer uniformly between 1 (inclusive) and 10 (exclusive),
    # while sampling in log space
    "lograndint": tune.lograndint(1, 10),

    # Sample a integer uniformly between 2 (inclusive) and 10 (inclusive (!)),
    # while sampling in log space and rounding to increments of 2
    "qlograndint": tune.qlograndint(2, 10, 2),

    # Sample an option uniformly from the specified choices
    "choice": tune.choice(["a", "b", "c"]),
}

Para obtener más información sobre cómo puede personalizar dominios dentro del espacio de búsqueda, visite la documentación de FLAML sobre la personalización de espacios de búsqueda.

Restricciones de optimización

El último paso es especificar restricciones de la tarea de optimización. Una propiedad notable de flaml.tune es que puede completar el proceso de optimización dentro de una restricción de recursos necesaria. Para ello, un usuario puede proporcionar restricciones de recursos en términos de tiempo de CPU (en segundos) mediante el argumento time_budget_s o en términos del número de pruebas utilizando el argumento num_samples.

# Set a resource constraint of 60 seconds wall-clock time for the tuning.
flaml.tune.run(..., time_budget_s=60, ...)

# Set a resource constraint of 100 trials for the tuning.
flaml.tune.run(..., num_samples=100, ...)

# Use at most 60 seconds and at most 100 trials for the tuning.
flaml.tune.run(..., time_budget_s=60, num_samples=100, ...)

Para obtener más información sobre las restricciones de configuración de adiciones, puede visitar la documentación de FLAML para obtener opciones de ajuste avanzadas.

Ensamblándolo

Una vez que hayamos definido nuestros criterios de optimización, podemos ejecutar la prueba de optimización. Para realizar un seguimiento de los resultados de la prueba, podemos aprovechar el registro automático de MLFlow para capturar las métricas y los parámetros de cada ejecución. Este código capturará toda la prueba de ajuste de hiperparámetros, resaltando cada una de las combinaciones de hiperparámetros exploradas por FLAML.

import mlflow
mlflow.set_experiment("flaml_tune_experiment")
mlflow.autolog(exclusive=False)

with mlflow.start_run(nested=True, run_name="Child Run: "):
    analysis = tune.run(
        evaluate_config,  # the function to evaluate a config
        config=config_search_space,  # the search space defined
        metric="score",
        mode="min",  # the optimization mode, "min" or "max"
        num_samples=-1,  # the maximal number of configs to try, -1 means infinite
        time_budget_s=10,  # the time budget in seconds
    )

Nota

Cuando el registro automático de MLflow está habilitado, las métricas, los parámetros y los modelos se deben registrar automáticamente a medida que se ejecuta MLFlow. Sin embargo, esto varía según el marco. Es posible que no se registren métricas y parámetros para modelos específicos. Por ejemplo, no se registrará ninguna métrica para los modelos XGBoost, LightGBM, Spark y SynapseML. Puede obtener más información sobre qué métricas y parámetros se capturan de cada framework usando la documentación de registro automático de MLFlow .

Ajuste paralelo con Apache Spark

La funcionalidad de flaml.tune admite el ajuste tanto de Apache Spark como de los algoritmos de aprendizaje en un solo nodo. Además, al ajustar el aprendizaje de un solo nodo (por ejemplo, Scikit-Learn aprendizaje), también puede realizar el ajuste en paralelo para acelerar el proceso estableciendo use_spark = True. En el caso de los clústeres de Spark, de forma predeterminada, FLAML iniciará una prueba por ejecutor. También puede personalizar el número de pruebas simultáneas mediante el argumento n_concurrent_trials.


analysis = tune.run(
    evaluate_config,  # the function to evaluate a config
    config=config_search_space,  # the search space defined
    metric="score",
    mode="min",  # the optimization mode, "min" or "max"
    num_samples=-1,  # the maximal number of configs to try, -1 means infinite
    time_budget_s=10,  # the time budget in seconds
    use_spark=True,
)
print(analysis.best_trial.last_result)  # the best trial's result
print(analysis.best_config)  # the best config

Para más información sobre cómo paralelizar los recorridos de optimización, puede visitar la documentación de FLAML para trabajos paralelos de Spark.

Visualización de los resultados

El módulo flaml.visualization proporciona funciones de utilidad para trazar el proceso de optimización mediante Plotly. Al aprovechar Plotly, los usuarios pueden explorar interactivamente sus resultados del experimento de AutoML. Para usar estas funciones de trazado, simplemente proporcione el objeto optimizado flaml.AutoML o flaml.tune.tune.ExperimentAnalysis como entrada.

Puede usar las siguientes funciones en el cuaderno:

  • plot_optimization_history: Trazar la historia de optimización de todas las pruebas del experimento.
  • plot_feature_importance: Importancia del gráfico para cada característica del conjunto de datos.
  • plot_parallel_coordinate: trazar las relaciones de parámetros de alta dimensión en el experimento.
  • plot_contour: Dibujar la relación de parámetros como gráfico de contorno en el experimento.
  • plot_edf: traza el valor objetivo EDF (función de distribución empírica) del experimento.
  • plot_timeline: representar la línea de tiempo del experimento.
  • plot_slice: Trazar la relación de parámetros como gráfico de segmentos en un estudio.
  • plot_param_importance: Representar gráficamente la importancia de los hiperparámetros del experimento.