Freigeben über


Optimieren von Hyperparametern in Pipelines

GILT FÜR:Azure CLI ML-Erweiterung v2 (aktuell)Python SDK azure-ai-ml v2 (aktuell)

In diesem Artikel erfahren Sie, wie Sie die Hyperparameteroptimierung in Azure Machine Learning-Pipelines mithilfe der Azure Machine Learning CLI v2 oder dem Azure Machine Learning SDK für Python v2 automatisieren.

Hyperparameter sind anpassbare Parameter, mit denen Sie den Modelltrainingsprozess steuern können. Bei der Hyperparameteroptimierung handelt es sich um den Prozess, bei dem nach der Hyperparameterkonfiguration gesucht wird, die eine optimale Leistung liefert. Mit Azure Machine Learning können Sie die Hyperparameteroptimierung automatisieren und Experimente parallel ausführen, um Hyperparameter effizient zu optimieren.

Voraussetzungen

Erstellen und Ausführen einer Pipeline zur Hyperparameteroptimierung

Erstellen einer Befehlskomponente mit Hyperparametereingaben

Die Azure Machine Learning-Pipeline muss über eine Befehlskomponente mit Hyperparametereingaben verfügen. Die folgende Datei train.yml aus den Beispielprojekten definiert eine trial-Komponente mit den Hyperparametereingaben c_value, kernel und coef und führt den Quellcode im Ordner ./train-src aus.

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

Erstellen des Quellcodes der Testkomponente

Der Quellcode für dieses Beispiel ist eine einzelne Datei train.py. Dieser Code wird bei jedem Test des Sweep-Auftrags ausgeführt.

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

Hinweis

Achten Sie darauf, die Metriken im Quellcode der Testkomponente mit exakt demselben Namen wie dem primary_metric-Wert in der Pipelinedatei zu erfassen. In diesem Beispiel wird mlflow.autolog() verwendet. Dabei handelt es sich um die empfohlene Methode zum Nachverfolgen von Machine Learning-Experimenten. Weitere Informationen zu MLflow finden Sie unter Nachverfolgen von Machine Learning-Experimenten und -Modellen mit MLflow.

Erstellen einer Pipeline mit einem Schritt für das Hyperparameter-Sweeping

Der folgende Code erstellt anhand der in train.yml definierten Befehlskomponente eine Pipelinedefinitionsdatei mit den beiden Schritten train und predict. In sweep_step lautet der erforderliche Schritttyp sweep, und die Hyperparametereingaben c_value, kernel und coef für die trial-Komponente werden search_space hinzugefügt.

Im folgenden Beispiel ist die Hyperparameteroptimierung von sweep_step hervorgehoben.

$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

Ein vollständiges Schema für einen Sweep-Auftrag finden Sie unter CLI (v2): YAML-Schema von Sweep-Aufträgen.

Übermitteln des Pipelineauftrags für die Hyperparameteroptimierung

Nachdem Sie diesen Pipelineauftrag übermittelt haben, führt Azure Machine Learning die trial-Komponente mehrmals aus, um da Sweeping für die Hyperparameter auf der Grundlage des Suchbereichs und der Grenzwerte, die Sie in sweep_step definiert haben, durchzuführen.

Anzeigen der Ergebnisse der Hyperparameteroptimierung in Studio

Nachdem Sie einen Pipelineauftrag übermittelt haben, erhalten Sie vom SDK- oder CLI-Widget einen Web-URL-Link zum Pipelinediagramm auf der Benutzeroberfläche von Azure Machine Learning Studio.

Um die Ergebnisse der Hyperparameteroptimierung anzuzeigen, doppelklicken Sie im Pipelinediagramm auf den Sweep-Schritt. Wählen Sie anschließend im Detailbereich die Registerkarte Untergeordnete Aufträge und dann den untergeordneten Auftrag aus.

Screenshot: Pipeline mit untergeordnetem Auftrag und hervorgehobenem Knoten „train_model“

Wählen Sie auf der Seite des untergeordneten Auftrags die Registerkarte Testversionen aus, um Metriken für alle untergeordneten Ausführungen anzuzeigen und zu vergleichen. Wählen Sie eine der untergeordneten Ausführungen aus, um die zugehörigen Details anzuzeigen.

Screenshot der Seite eines untergeordneten Auftrags mit der Registerkarte „Testversionen“

Wenn bei einer untergeordneten Ausführung ein Fehler aufgetreten ist, wählen Sie auf der Seite der untergeordneten Ausführung die Registerkarte Ausgaben und Protokolle aus, um nützliche Debuginformationen anzuzeigen.

Screenshot der Registerkarte „Ausgaben und Protokolle“ einer untergeordneten Ausführung