Del via


Justering af hyperparameter

Hyperparameter-tuning er processen med at finde de optimale værdier for de parametre, som ikke læres af maskinlæringsmodellen under træningen, men som brugeren sætter før træningsprocessen begynder. Disse parametre kaldes ofte hyperparametre, og eksempler omfatter læringsfrekvensen, antallet af skjulte lag i et neuralt netværk, regulariseringsstyrken og batchstørrelsen.

Ydeevnen af en model til maskinel indlæring kan være meget følsom over for valget af hyperparametre, og det optimale sæt hyperparametre kan variere meget afhængigt af det specifikke problem og datasættet. Justering af hyperparametre er derfor et vigtigt trin i pipelinen til maskinel indlæring, da det kan have en betydelig indvirkning på modellens nøjagtighed og ydeevnen for generalisering.

I Fabric kan data scientists bruge FLAML, et letvægts Python-bibliotek til effektiv automatisering af maskinlæring og AI-operationer til deres hyperparameter-tuningbehov. I Fabric-notesbøger kan brugerne kalde flaml.tune for økonomisk justering af hyperparametre.

Justerer arbejdsproces

Der er tre vigtige trin til at bruge flaml.tune til at afslutte en grundlæggende justeringsopgave:

  1. Angiv justeringsmålet med hensyn til hyperparametrene.
  2. Angiv et søgeområde for hyperparametrene.
  3. Specificér tuning-begrænsninger, herunder begrænsninger på ressourcebudgettet til tuning, begrænsninger på konfigurationerne og/eller begrænsninger på en (eller flere) bestemte metrikker.

Mål for justering

Det første trin er at angive din mål for justering. Det gør du ved først at angive din evalueringsprocedure med hensyn til hyperparametrene i en brugerdefineret funktion evaluation_function. Funktionen kræver en hyperparameterkonfiguration som input. Den kan blot returnere en metrikværdi i en skalar eller returnere en ordbog med metriske navn og metrikværdipar.

I eksemplet nedenfor kan vi definere en evalueringsfunktion med hensyn til to hyperparametre kaldet x og 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"]}

Søgeplads

Dernæst specificerer vi søgerummet for hyperparametre. I søgerummet skal du angive gyldige værdier for dine hyperparametre og hvordan disse værdier udvælges (for eksempel fra en uniform fordeling eller en log-uniform fordeling). I det følgende eksempel kan vi give søgerummet for hyperparametrene x og y. De gyldige værdier for begge er heltal fra [1, 100.000]. Disse hyperparametre udtages ens i de angivne områder.

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

Med FLAML kan brugerne tilpasse domænet for en bestemt hyperparameter. Dette giver brugerne mulighed for at angive en type og gyldigt område, at prøve parametre fra. FLAML understøtter følgende hyperparametertyper: float, integer og categorical. Du kan se følgende eksempel for almindeligt anvendte domæner:

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"]),
}

Du kan få mere at vide om, hvordan du tilpasser domæner i dit søgeområde, ved at gå til FLAML-dokumentationen om tilpasning af søgeområder.

Justeringsbegrænsninger

Det sidste trin er at angive begrænsninger for justeringsopgaven. En bemærkelsesværdig egenskab ved flaml.tune er, at den kan fuldføre tuning-processen inden for en nødvendig ressourcebegrænsning. For at gøre dette kan en bruger angive ressourcebegrænsninger i form af vægklokkeslæt (i sekunder) ved hjælp af argumentet time_budget_s eller med hensyn til antallet af forsøg ved hjælp af argumentet 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, ...)

Hvis du vil vide mere om konfigurationsbegrænsninger for tilføjelser, kan du gå til FLAML-dokumentationen for at få mere at vide om avancerede indstillinger for justering.

Sætte det sammen

Når vi har defineret vores justeringskriterier, kan vi udføre prøveversionen af justering. For at følge resultaterne af vores forsøg kan vi bruge MLFlow autologging til at indfange metrikker og parametre for hver af disse kørsler. Denne kode fanger hele hyperparameter-tuning-forsøget og fremhæver hver af de hyperparameterkombinationer, som FLAML udforskede.

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
    )

Seddel

Når MLflow-autologning er aktiveret, bør målinger, parametre og modeller automatisk logges, mens MLFlow kører. Dette varierer dog afhængigt af strukturen. Målinger og parametre for specifikke modeller bliver måske ikke logget. For eksempel logges der ingen metrikker for XGBoost-, LightGBM-, Spark- og SynapseML-modellerne. Du kan få mere at vide om, hvilke målepunkter og parametre der registreres fra hver struktur, ved hjælp af dokumentationen til automatisk logning af MLFlow.

Parallel justering med Apache Spark

Funktionaliteten flaml.tune understøtter justering af både Apache Spark og enkeltnode-elever. Derudover kan du, når du tuner enkelt-node lærende (for eksempel Scikit-Learn lærende), også parallelisere tuningen for at fremskynde din tuningproces ved at sætte use_spark = True. For Spark-klynger starter FLAML som standard én prøveversion pr. eksekvering. Du kan også tilpasse antallet af samtidige forsøg ved hjælp af argumentet 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

Hvis du vil vide mere om, hvordan du paralleliserer dine justeringsspor, kan du gå til FLAML-dokumentationen for parallelle Spark-job.

Visualiser resultater

Modulet flaml.visualization indeholder hjælpefunktioner til afbildning af optimeringsprocessen ved hjælp af Plotly. Ved at bruge Plotly kan brugere interaktivt udforske resultaterne af deres AutoML-eksperiment. Hvis du vil bruge disse afbildningsfunktioner, skal du angive dit optimerede flaml.AutoML objekt eller flaml.tune.tune.ExperimentAnalysis objekt som input.

Du kan bruge følgende funktioner i din notesbog:

  • plot_optimization_history: Afbildningsoptimeringshistorik for alle forsøg i eksperimentet.
  • plot_feature_importance: Afbild prioritet for hver funktion i datasættet.
  • plot_parallel_coordinate: Afbild de højdimensionelle parameterrelationer i eksperimentet.
  • plot_contour: Afbild parameterrelationen som konturafbildning i eksperimentet.
  • plot_edf: Afbild den objektive værdi EDF (empirisk fordelingsfunktion) for eksperimentet.
  • plot_timeline: Afbild eksperimentets tidslinje.
  • plot_slice: Afbild parameterrelationen som et udsnit i en undersøgelse.
  • plot_param_importance: Afbild eksperimentets hyperparameter vigtighed.