Condividi tramite


Come eseguire l'ottimizzazione degli iperparametri nelle pipeline

SI APPLICA A:Estensione ml dell'interfaccia della riga di comando di Azure v2 (corrente)Python SDK azure-ai-ml v2 (corrente)

Questo articolo illustra come automatizzare l'ottimizzazione degli iperparametri nelle pipeline di Azure Machine Learning usando l'interfaccia della riga di comando di Azure Machine Learning v2 o Azure Machine Learning SDK per Python v2.

Gli iperparametri sono parametri regolabili che consentono di controllare il processo di training del modello. L'ottimizzazione degli iperparametri è il processo di ricerca della configurazione degli iperparametri che comporta prestazioni ottimali. Azure Machine Learning consente di automatizzare l'ottimizzazione degli iperparametri e di eseguire esperimenti in parallelo per affinare gli iperparametri in modo efficiente.

Prerequisiti

Creare ed eseguire una pipeline di ottimizzazione degli iperparametri

Creare un componente di comando con input degli iperparametri

La pipeline di Azure Machine Learning deve avere un componente di comando con input degli iperparametri. Il file di train.yml seguente dei progetti di esempio definisce un componente trial con input degli iperparametri c_value, kernel e coef ed esegue il codice sorgente che si trova nella cartella ./train-src.

$schema: https://azuremlschemas.azureedge.net/latest/commandComponent.schema.json
type: command

name: train_model
display_name: train_model
version: 1

inputs: 
  data:
    type: uri_folder
  c_value:
    type: number
    default: 1.0
  kernel:
    type: string
    default: rbf
  degree:
    type: integer
    default: 3
  gamma:
    type: string
    default: scale
  coef0: 
    type: number
    default: 0
  shrinking:
    type: boolean
    default: false
  probability:
    type: boolean
    default: false
  tol:
    type: number
    default: 1e-3
  cache_size:
    type: number
    default: 1024
  verbose:
    type: boolean
    default: false
  max_iter:
    type: integer
    default: -1
  decision_function_shape:
    type: string
    default: ovr
  break_ties:
    type: boolean
    default: false
  random_state:
    type: integer
    default: 42

outputs:
  model_output:
    type: mlflow_model
  test_data:
    type: uri_folder
  
code: ./train-src

environment: azureml://registries/azureml/environments/sklearn-1.5/labels/latest

command: >-
  python train.py 
  --data ${{inputs.data}}
  --C ${{inputs.c_value}}
  --kernel ${{inputs.kernel}}
  --degree ${{inputs.degree}}
  --gamma ${{inputs.gamma}}
  --coef0 ${{inputs.coef0}}
  --shrinking ${{inputs.shrinking}}
  --probability ${{inputs.probability}}
  --tol ${{inputs.tol}}
  --cache_size ${{inputs.cache_size}}
  --verbose ${{inputs.verbose}}
  --max_iter ${{inputs.max_iter}}
  --decision_function_shape ${{inputs.decision_function_shape}}
  --break_ties ${{inputs.break_ties}}
  --random_state ${{inputs.random_state}}
  --model_output ${{outputs.model_output}}
  --test_data ${{outputs.test_data}}

Creare il codice sorgente del componente di valutazione

Il codice sorgente per questo esempio è un singolo file train.py. Questo codice viene eseguito in ogni prova del processo sweep.

# imports
import os
import mlflow
import argparse

import pandas as pd
from pathlib import Path

from sklearn.svm import SVC
from sklearn.model_selection import train_test_split

# define functions
def main(args):
    # enable auto logging
    mlflow.autolog()

    # setup parameters
    params = {
        "C": args.C,
        "kernel": args.kernel,
        "degree": args.degree,
        "gamma": args.gamma,
        "coef0": args.coef0,
        "shrinking": args.shrinking,
        "probability": args.probability,
        "tol": args.tol,
        "cache_size": args.cache_size,
        "class_weight": args.class_weight,
        "verbose": args.verbose,
        "max_iter": args.max_iter,
        "decision_function_shape": args.decision_function_shape,
        "break_ties": args.break_ties,
        "random_state": args.random_state,
    }

    # read in data
    df = pd.read_csv(args.data)

    # process data
    X_train, X_test, y_train, y_test = process_data(df, args.random_state)

    # train model
    model = train_model(params, X_train, X_test, y_train, y_test)
    # Output the model and test data
    # write to local folder first, then copy to output folder

    mlflow.sklearn.save_model(model, "model")

    from distutils.dir_util import copy_tree

    # copy subdirectory example
    from_directory = "model"
    to_directory = args.model_output

    copy_tree(from_directory, to_directory)

    X_test.to_csv(Path(args.test_data) / "X_test.csv", index=False)
    y_test.to_csv(Path(args.test_data) / "y_test.csv", index=False)


def process_data(df, random_state):
    # split dataframe into X and y
    X = df.drop(["species"], axis=1)
    y = df["species"]

    # train/test split
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=random_state
    )

    # return split data
    return X_train, X_test, y_train, y_test


def train_model(params, X_train, X_test, y_train, y_test):
    # train model
    model = SVC(**params)
    model = model.fit(X_train, y_train)

    # return model
    return model


def parse_args():
    # setup arg parser
    parser = argparse.ArgumentParser()

    # add arguments
    parser.add_argument("--data", type=str)
    parser.add_argument("--C", type=float, default=1.0)
    parser.add_argument("--kernel", type=str, default="rbf")
    parser.add_argument("--degree", type=int, default=3)
    parser.add_argument("--gamma", type=str, default="scale")
    parser.add_argument("--coef0", type=float, default=0)
    parser.add_argument("--shrinking", type=bool, default=False)
    parser.add_argument("--probability", type=bool, default=False)
    parser.add_argument("--tol", type=float, default=1e-3)
    parser.add_argument("--cache_size", type=float, default=1024)
    parser.add_argument("--class_weight", type=dict, default=None)
    parser.add_argument("--verbose", type=bool, default=False)
    parser.add_argument("--max_iter", type=int, default=-1)
    parser.add_argument("--decision_function_shape", type=str, default="ovr")
    parser.add_argument("--break_ties", type=bool, default=False)
    parser.add_argument("--random_state", type=int, default=42)
    parser.add_argument("--model_output", type=str, help="Path of output model")
    parser.add_argument("--test_data", type=str, help="Path of output model")

    # parse args
    args = parser.parse_args()

    # return args
    return args


# run script
if __name__ == "__main__":
    # parse args
    args = parse_args()

    # run main function
    main(args)

Nota

Assicurarsi di registrare le metriche nel codice sorgente del componente di valutazione con esattamente lo stesso nome del valore primary_metric nel file della pipeline. Questo esempio usa mlflow.autolog(), che è il modo consigliato per tenere traccia degli esperimenti di Machine Learning. Per altre informazioni su MLflow, vedere Tenere traccia degli esperimenti e dei modelli di Machine Learning con MLflow.

Creare una pipeline con un passaggio di sweep degli iperparametri

Dato che il componente di comando definito in train.yml, il codice seguente crea un file di definizione della pipeline in due passaggi train e predict. In sweep_step, il tipo di passaggio richiesto è sweep, e gli input degli iperparametri c_value, kernel e coef per il componente trial vengono aggiunti al search_space.

Nell'esempio seguente viene evidenziata l'ottimizzazione degli iperparametri sweep_step.

$schema: https://azuremlschemas.azureedge.net/latest/pipelineJob.schema.json
type: pipeline
display_name: pipeline_with_hyperparameter_sweep
description: Tune hyperparameters using TF component
settings:
    default_compute: azureml:cpu-cluster
jobs:
  sweep_step:
    type: sweep
    inputs:
      data: 
        type: uri_file
        path: wasbs://datasets@azuremlexamples.blob.core.windows.net/iris.csv
      degree: 3
      gamma: "scale"
      shrinking: False
      probability: False
      tol: 0.001
      cache_size: 1024
      verbose: False
      max_iter: -1
      decision_function_shape: "ovr"
      break_ties: False
      random_state: 42
    outputs:
      model_output:
      test_data:
    sampling_algorithm: random
    trial: ./train.yml
    search_space:
      c_value:
        type: uniform
        min_value: 0.5
        max_value: 0.9
      kernel:
        type: choice
        values: ["rbf", "linear", "poly"]
      coef0:
        type: uniform
        min_value: 0.1
        max_value: 1
    objective:
      goal: minimize
      primary_metric: training_f1_score
    limits:
      max_total_trials: 5
      max_concurrent_trials: 3
      timeout: 7200

  predict_step:
    type: command
    inputs:
      model: ${{parent.jobs.sweep_step.outputs.model_output}}
      test_data: ${{parent.jobs.sweep_step.outputs.test_data}}
    outputs:
      predict_result:
    component: ./predict.yml

Per lo schema completo del processo sweep, vedere Schema YAML del processo sweep dell'interfaccia della riga di comando (v2).

Inviare il processo della pipeline di ottimizzazione degli iperparametri

Dopo aver inviato questo processo della pipeline, Azure Machine Learning esegue il componente trial più volte per eseguire lo sweep sugli iperparametri, in base allo spazio di ricerca e ai limiti definiti nel sweep_step.

Visualizzare i risultati di ottimizzazione degli iperparametri in Studio

Dopo aver inviato un processo della pipeline, il widget dell'SDK o dell'interfaccia della riga di comando fornisce un collegamento URL Web al grafico della pipeline nell'interfaccia utente di Azure Machine Learning Studio.

Per visualizzare i risultati dell'ottimizzazione degli iperparametri, fare doppio clic sul passaggio sweep nel grafico della pipeline, selezionare la scheda Processi figlio nel pannello dei dettagli e quindi selezionare il processo figlio.

Screenshot della pipeline con il processo figlio e il nodo train_model evidenziato.

Nella pagina del processo figlio selezionare la scheda Versioni di valutazione per visualizzare e confrontare le metriche per tutte le esecuzioni figlio. Selezionare una delle esecuzioni figlio per visualizzare i dettagli per l'esecuzione.

Screenshot della pagina del processo figlio con la scheda Versioni di valutazione.

Se un'esecuzione figlio non è riuscita, è possibile selezionare la scheda Output e log nella pagina di esecuzione figlio per visualizzare informazioni di debug utili.

Screenshot della scheda output e log di un'esecuzione figlio.