Cómo realizar el ajuste de hiperparámetros en la canalización (v2)
SE APLICA A:Extensión ML de la CLI de Azure v2 (actual)SDK de Python azure-ai-ml v2 (actual)
En este artículo, aprenderá a realizar el ajuste de hiperparámetros en la canalización de Azure Machine Learning.
Requisito previo
- Comprenda qué es el ajuste de hiperparámetros y cómo realizar el ajuste de hiperparámetros en Azure Machine Learning usando SweepJob.
- Descripción de lo que es una canalización de Azure Machine Learning
- Cree un componente de comando que tome hiperparámetros como entrada.
Cómo realizar el ajuste de hiperparámetros en la canalización de Azure Machine Learning
Esta sección explica cómo hacer el ajuste de hiperparámetros en la canalización de Azure Machine Learning mediante la CLI v2 y el SDK de Python. Ambos enfoques comparten el mismo requisito previo: ya tienen un componente de comando creado y el componente de comando toma hiperparámetros como entradas. Si aún no tiene un componente de comando. Siga los vínculos siguientes para crear primero un componente de comando.
CLI v2
El ejemplo que se usa en este artículo se puede encontrar en el repositorio azureml-example. Vaya a [azureml-examples/cli/jobs/pipelines-with-components/pipeline_with_hyperparameter_sweep para comprobar el ejemplo.
Supongamos que ya tiene un componente de comando definido en train.yaml
. Un archivo YAML de trabajo de canalización de dos pasos (entrenamiento y predicción) es similar al siguiente.
$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
sweep_step
es el paso para el ajuste de hiperparámetros. Su tipo debe ser sweep
. Y trial
hace referencia al componente de comando definido en train.yaml
. En el campo search space
podemos ver que se agregan tres hisparámetros (c_value
, kernel
y coef
) al espacio de búsqueda. Después de enviar este trabajo de canalización, Azure Machine Learning ejecutará el componente de prueba varias veces para barrir hiperparámetros en función del espacio de búsqueda y finalizar la directiva que definió en sweep_step
. Compruebe el esquema YAML del trabajo de barrido para obtener el esquema completo del trabajo de barrido.
A continuación se muestra la definición del componente de prueba (archivo train.yml).
$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.0/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}}
Los hiperparámetros agregados al espacio de búsqueda en pipeline.yml deben ser entradas para el componente de prueba. El código fuente del componente de prueba se encuentra en la carpeta ./train-src
. En este ejemplo, es un archivo único train.py
. Este es el código que se ejecutará en cada prueba del trabajo de barrido. Asegúrese de que ha registrado las métricas en el código fuente del componente de prueba con exactamente el mismo nombre que el valor primary_metric
en el archivo pipeline.yml. En este ejemplo, usamos mlflow.autolog()
, que es la manera recomendada de realizar un seguimiento de los experimentos de ML. Obtenga más información sobre mlflow aquí
El fragmento de código que se puede ver a continuación es el código fuente del componente de prueba.
# 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)
SDK de Python
El ejemplo del SDK de Python se puede encontrar en el repositorio azureml-example. Vaya a azureml-examples/sdk/jobs/pipelines/1c_pipeline_with_hyperparameter_sweep para comprobar el ejemplo.
En Azure Machine Learning SDK de Python v2, puede habilitar el ajuste de hiperparámetros para cualquier componente de comando mediante una llamada al método .sweep()
.
En el fragmento de código siguiente se muestra cómo habilitar el barrido para train_model
.
train_component_func = load_component(source="./train.yml")
score_component_func = load_component(source="./predict.yml")
# define a pipeline
@pipeline()
def pipeline_with_hyperparameter_sweep():
"""Tune hyperparameters using sample components."""
train_model = train_component_func(
data=Input(
type="uri_file",
path="wasbs://datasets@azuremlexamples.blob.core.windows.net/iris.csv",
),
c_value=Uniform(min_value=0.5, max_value=0.9),
kernel=Choice(["rbf", "linear", "poly"]),
coef0=Uniform(min_value=0.1, max_value=1),
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,
)
sweep_step = train_model.sweep(
primary_metric="training_f1_score",
goal="minimize",
sampling_algorithm="random",
compute="cpu-cluster",
)
sweep_step.set_limits(max_total_trials=20, max_concurrent_trials=10, timeout=7200)
score_data = score_component_func(
model=sweep_step.outputs.model_output, test_data=sweep_step.outputs.test_data
)
pipeline_job = pipeline_with_hyperparameter_sweep()
# set pipeline level compute
pipeline_job.settings.default_compute = "cpu-cluster"
En primer lugar, cargamos train_component_func
definidas en el archivo train.yml
. Al crear train_model
, agregamos c_value
kernel
y coef0
al espacio de búsqueda (línea 15-17). La línea 30-35 define la métrica principal, el algoritmo de muestra, etc.
Comprobación del trabajo de canalización con el paso de barrido en Studio
Después de enviar un trabajo de canalización, el SDK o el widget de la CLI le proporcionarán un vínculo de dirección URL web a la interfaz de usuario de Studio. El vínculo le guiará a la vista de gráfico de canalización de forma predeterminada.
Para comprobar los detalles del paso de barrido, haga doble clic en el paso de barrido y vaya a la pestaña de trabajo secundario en el panel de la derecha.
Esto le vinculará a la página de trabajo de barrido, como se muestra en la captura de pantalla siguiente. Vaya a la pestaña del trabajo secundario, aquí puede ver las métricas de todos los trabajos secundarios y la lista de todos los trabajos secundarios.
Si se ha producido un error en los trabajos secundarios, seleccione el nombre de ese trabajo secundario para especificar la página de detalles de ese trabajo secundario específico (consulte la siguiente captura de pantalla). La información de depuración útil se encuentra en Salidas y registros.
Cuadernos de ejemplo
- Canalización de compilación con nodo de barrido
- Ejecución del barrido de hiperparámetros en un trabajo de comando