Creare ed eseguire pipeline di Machine Learning usando componenti con Azure Machine Learning SDK v2
SI APPLICA A: Python SDK azure-ai-ml v2 (corrente)
Questo articolo illustra come creare una pipeline di Azure Machine Learning usando Python SDK v2 per completare un'attività di classificazione delle immagini contenente tre passaggi: preparare i dati, eseguire il training di un modello di classificazione delle immagini e assegnare un punteggio al modello. Le pipeline di Machine Learning ottimizzano il flusso di lavoro offrendo velocità, portabilità e possibilità di riutilizzo per consentire così di concentrarsi su Machine Learning anziché sull'infrastruttura e l'automazione.
L'esempio esegue il training di una piccola rete neurale convoluzionale Keras per classificare le immagini nel set di dati Fashion MNIST. La pipeline ha un aspetto simile al seguente.
In questo articolo vengono completate le attività seguenti:
- Preparare i dati di input per il processo della pipeline
- Creare tre componenti per preparare i dati, eseguire il training e assegnare il punteggio
- Comporre una pipeline dai componenti
- Ottenere l'accesso all'area di lavoro con l'ambiente di calcolo
- Inviare il processo della pipeline
- Esaminare l'output dei componenti e della rete neurale sottoposta a training
- (Facoltativo) Registrare il componente per riutilizzare e condividere ulteriormente all'interno dell'area di lavoro
Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare. Provare la versione gratuita o a pagamento di Azure Machine Learning.
Prerequisiti
Area di lavoro di Azure Machine Learning: se non ne è disponibile una, completare l'esercitazione Creare risorse.
Un ambiente Python in cui è stato installato Azure Machine Learning Python SDK v2 - istruzioni di installazione - Controllare la sezione introduttiva. Questo ambiente viene usato per definire e controllare le risorse di Azure Machine Learning ed è separato dall'ambiente usato in fase di esecuzione per il training.
Clonare il repository di esempi
Per eseguire gli esempi di training, clonare prima di tutto il repository di esempi e passare alla directory
sdk
:git clone --depth 1 https://github.com/Azure/azureml-examples cd azureml-examples/sdk
Avviare una sessione Interattiva di Python
Questo articolo usa Python SDK per Azure Machine Learning per creare e controllare una pipeline di Azure Machine Learning. L'articolo presuppone che i frammenti di codice vengano eseguiti in modo interattivo in un ambiente Python REPL o in un notebook Jupyter.
Questo articolo si basa sul notebook image_classification_keras_minist_convnet.ipynb disponibile nella directory sdk/python/jobs/pipelines/2e_image_classification_keras_minist_convnet
del repository Azure Machine Learning Examples.
Importare le librerie obbligatorie
Importare tutte le librerie necessarie di Azure Machine Learning richieste per questo articolo:
# import required libraries
from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
from azure.ai.ml import MLClient
from azure.ai.ml.dsl import pipeline
from azure.ai.ml import load_component
Preparare i dati di input per il processo della pipeline
È necessario preparare i dati di input per questa pipeline di classificazione delle immagini.
Fashion-MNIST è un set di dati di immagini di moda suddivise in 10 classi. Ogni immagine è un'immagine in scala di grigi 28x28 ed esistono 60.000 immagini per il training e 10.000 immagini per i test. Come problema di classificazione delle immagini, Fashion-MNIST è più difficile rispetto al database classico MNIST con cifre scritte a mano. È distribuito nella stessa forma binaria compressa del database di cifre scritto a mano originale.
Importare tutte le librerie necessarie di Azure Machine Learning necessarie.
Definendo un Input
, si crea un riferimento al percorso dell'origine dati. I dati rimangono nell'attuale posizione, quindi non si incorre in costi aggiuntivi di archiviazione.
Creare componenti per la compilazione della pipeline
L'attività di classificazione delle immagini può essere suddivisa in tre passaggi: preparare i dati, eseguire il training del modello e assegnare un punteggio al modello.
Un componente di Azure Machine Learning è una parte autonoma di codice che esegue un passaggio in una pipeline di Machine Learning. In questo articolo verranno creati tre componenti per l'attività di classificazione delle immagini:
- Preparare i dati per il training e il test
- Eseguire il training di una rete neurale per la classificazione delle immagini usando i dati di training
- Assegnare un punteggio al modello usando i dati di test
Per ogni componente è necessario preparare quanto segue:
Preparare lo script Python contenente la logica di esecuzione
Definire l'interfaccia del componente
Aggiungere altri metadati del componente, incluso l'ambiente di runtime, il comando per eseguire il componente e così via.
La sezione successiva mostrerà due modi diversi per creare i componenti: i primi due componenti tramite la funzione Python e il terzo componente tramite la definizione YAML.
Creare il componente di preparazione dei dati
Il primo componente di questa pipeline convertirà i file di dati compressi di fashion_ds
in due file CSV, uno per il training e l'altro per l'assegnazione dei punteggi. Si userà la funzione Python per definire questo componente.
Se si segue l'esempio nel repository di esempi di Azure Machine Learning, i file di origine sono già disponibili nella cartella prep/
. Questa cartella contiene due file per costruire il componente prep_component.py
, che definisce il componente e conda.yaml
, che definisce l'ambiente di runtime del componente.
Definire un componente usando la funzione Python
Usando la funzione command_component()
come elemento Decorator, è possibile definire facilmente l'interfaccia, i metadati e il codice del componente da eseguire da una funzione Python. Ogni funzione Python decorata verrà trasformata in una singola specifica statica (YAML) che il servizio pipeline può elaborare.
# Converts MNIST-formatted files at the passed-in input path to training data output path and test data output path
import os
from pathlib import Path
from mldesigner import command_component, Input, Output
@command_component(
name="prep_data",
version="1",
display_name="Prep Data",
description="Convert data to CSV file, and split to training and test data",
environment=dict(
conda_file=Path(__file__).parent / "conda.yaml",
image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04",
),
)
def prepare_data_component(
input_data: Input(type="uri_folder"),
training_data: Output(type="uri_folder"),
test_data: Output(type="uri_folder"),
):
convert(
os.path.join(input_data, "train-images-idx3-ubyte"),
os.path.join(input_data, "train-labels-idx1-ubyte"),
os.path.join(training_data, "mnist_train.csv"),
60000,
)
convert(
os.path.join(input_data, "t10k-images-idx3-ubyte"),
os.path.join(input_data, "t10k-labels-idx1-ubyte"),
os.path.join(test_data, "mnist_test.csv"),
10000,
)
def convert(imgf, labelf, outf, n):
f = open(imgf, "rb")
l = open(labelf, "rb")
o = open(outf, "w")
f.read(16)
l.read(8)
images = []
for i in range(n):
image = [ord(l.read(1))]
for j in range(28 * 28):
image.append(ord(f.read(1)))
images.append(image)
for image in images:
o.write(",".join(str(pix) for pix in image) + "\n")
f.close()
o.close()
l.close()
Il codice precedente definisce un componente con nome visualizzato Prep Data
usando l'elemento Decorator @command_component
:
name
è l'identificatore univoco del componente.version
è la versione corrente del componente. Un componente può avere più versioni.display_name
è un nome visualizzato descrittivo del componente nell'interfaccia utente, che non è univoco.description
descrive in genere l'attività che questo componente può completare.environment
specifica l'ambiente di runtime per questo componente. L'ambiente di questo componente specifica un'immagine Docker e fa riferimento al fileconda.yaml
.Il file
conda.yaml
contiene tutti i pacchetti usati per il componente come segue:name: imagekeras_prep_conda_env channels: - defaults dependencies: - python=3.7.11 - pip=20.0 - pip: - mldesigner==0.1.0b4
La funzione
prepare_data_component
definisce un input perinput_data
e due output pertraining_data
etest_data
.input_data
è il percorso dei dati di input.training_data
etest_data
sono percorsi di dati di output per i dati di training e i dati di test.Questo componente converte i dati da
input_data
in un file CSV di dati di training intraining_data
e un file CSV di dati di test intest_data
.
Di seguito è riportato l'aspetto di un componente nell'interfaccia utente dello studio.
- Un componente è un blocco in un grafico della pipeline.
input_data
,training_data
etest_data
sono porte del componente, che si connette ad altri componenti per lo streaming dei dati.
A questo punto sono stati preparati tutti i file di origine per il componente Prep Data
.
Creare il componente train-model
In questa sezione si creerà un componente per il training del modello di classificazione delle immagini nella funzione Python, ad esempio il componente Prep Data
.
La differenza è che poiché la logica di training è più complessa, è possibile inserire il codice di training originale in un file Python separato.
I file di origine di questo componente si trovano nella cartella train/
nel repository di esempi di Azure Machine Learning. Questa cartella contiene tre file per costruire il componente:
train.py
: contiene la logica effettiva per il training del modello.train_component.py
: definisce l'interfaccia del componente e importa la funzione intrain.py
.conda.yaml
: definisce l'ambiente di runtime del componente.
Ottenere uno script contenente la logica di esecuzione
Il file train.py
contiene una normale funzione Python, che esegue la logica del modello di training per eseguire il training di una rete neurale Keras per la classificazione delle immagini. Per visualizzare il codice, vedere il file train.py in GitHub.
Definire un componente usando la funzione Python
Dopo aver definito correttamente la funzione di training, è possibile usare @command_component
in Azure Machine Learning SDK v2 per eseguire il wrapping della funzione come componente, che può essere usato nelle pipeline di Azure Machine Learning.
import os
from pathlib import Path
from mldesigner import command_component, Input, Output
@command_component(
name="train_image_classification_keras",
version="1",
display_name="Train Image Classification Keras",
description="train image classification with keras",
environment=dict(
conda_file=Path(__file__).parent / "conda.yaml",
image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04",
),
)
def keras_train_component(
input_data: Input(type="uri_folder"),
output_model: Output(type="uri_folder"),
epochs=10,
):
# avoid dependency issue, execution logic is in train() func in train.py file
from train import train
train(input_data, output_model, epochs)
Il codice precedente definisce un componente con nome visualizzato Train Image Classification Keras
usando @command_component
:
- La funzione
keras_train_component
definisce uninput_data
di input da cui provengono i dati di training, unepochs
di input che specifica periodi durante il training e unoutput_model
di output in cui restituisce il file del modello. Il valore predefinito diepochs
è 10. La logica di esecuzione di questo componente proviene dalla funzionetrain()
intrain.py
precedente.
Il componente train-model ha una configurazione leggermente più complessa rispetto al componente prep-data. conda.yaml
è simile al seguente:
name: imagekeras_train_conda_env
channels:
- defaults
dependencies:
- python=3.8
- pip=20.2
- pip:
- mldesigner==0.1.0b12
- azureml-mlflow==1.50.0
- tensorflow==2.7.0
- numpy==1.21.4
- scikit-learn==1.0.1
- pandas==1.3.4
- matplotlib==3.2.2
- protobuf==3.20.0
A questo punto sono stati preparati tutti i file di origine per il componente Train Image Classification Keras
.
Creare il componente score-model
In questa sezione, oltre ai componenti precedenti, si creerà un componente per assegnare un punteggio al modello sottoposto a training tramite la specifica e lo script YAML.
Se si segue l'esempio nel repository di esempi di Azure Machine Learning, i file di origine sono già disponibili nella cartella score/
. Questa cartella contiene tre file per costruire il componente:
score.py
: contiene il codice sorgente del componente.score.yaml
: definisce l'interfaccia e altri dettagli del componente.conda.yaml
: definisce l'ambiente di runtime del componente.
Ottenere uno script contenente la logica di esecuzione
Il file score.py
contiene una normale funzione Python, che esegue la logica del modello di training.
from tensorflow import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.utils import to_categorical
from keras.callbacks import Callback
from keras.models import load_model
import argparse
from pathlib import Path
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import mlflow
def get_file(f):
f = Path(f)
if f.is_file():
return f
else:
files = list(f.iterdir())
if len(files) == 1:
return files[0]
else:
raise Exception("********This path contains more than one file*******")
def parse_args():
# setup argparse
parser = argparse.ArgumentParser()
# add arguments
parser.add_argument(
"--input_data", type=str, help="path containing data for scoring"
)
parser.add_argument(
"--input_model", type=str, default="./", help="input path for model"
)
parser.add_argument(
"--output_result", type=str, default="./", help="output path for model"
)
# parse args
args = parser.parse_args()
# return args
return args
def score(input_data, input_model, output_result):
test_file = get_file(input_data)
data_test = pd.read_csv(test_file, header=None)
img_rows, img_cols = 28, 28
input_shape = (img_rows, img_cols, 1)
# Read test data
X_test = np.array(data_test.iloc[:, 1:])
y_test = to_categorical(np.array(data_test.iloc[:, 0]))
X_test = (
X_test.reshape(X_test.shape[0], img_rows, img_cols, 1).astype("float32") / 255
)
# Load model
files = [f for f in os.listdir(input_model) if f.endswith(".h5")]
model = load_model(input_model + "/" + files[0])
# Log metrics of the model
eval = model.evaluate(X_test, y_test, verbose=0)
mlflow.log_metric("Final test loss", eval[0])
print("Test loss:", eval[0])
mlflow.log_metric("Final test accuracy", eval[1])
print("Test accuracy:", eval[1])
# Score model using test data
y_predict = model.predict(X_test)
y_result = np.argmax(y_predict, axis=1)
# Output result
np.savetxt(output_result + "/predict_result.csv", y_result, delimiter=",")
def main(args):
score(args.input_data, args.input_model, args.output_result)
# run script
if __name__ == "__main__":
# parse args
args = parse_args()
# call main function
main(args)
Il codice in score.py accetta tre argomenti della riga di comando: input_data
, input_model
e output_result
. Il programma assegna un punteggio al modello di input usando i dati di input e quindi restituisce il risultato dell'assegnazione dei punteggi.
Definire il componente tramite YAML
In questa sezione si apprenderà come creare una specifica del componente nel formato di specifica del componente YAML valido. Questo file specifica le informazioni seguenti:
- Metadati: nome, display_name, versione, tipo e così via.
- Interfaccia: input e output
- Comando, codice e ambiente: comando, codice e ambiente usati per eseguire il componente
$schema: https://azuremlschemas.azureedge.net/latest/commandComponent.schema.json
type: command
name: score_image_classification_keras
display_name: Score Image Classification Keras
inputs:
input_data:
type: uri_folder
input_model:
type: uri_folder
outputs:
output_result:
type: uri_folder
code: ./
command: python score.py --input_data ${{inputs.input_data}} --input_model ${{inputs.input_model}} --output_result ${{outputs.output_result}}
environment:
conda_file: ./conda.yaml
image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04
name
è l'identificatore univoco del componente. Il nome visualizzato èScore Image Classification Keras
.- Questo componente ha due input e un output.
- Il percorso del codice sorgente è definito nella sezione
code
e quando il componente viene eseguito nel cloud, tutti i file di tale percorso verranno caricati come snapshot di questo componente. - La sezione
command
specifica il comando da eseguire durante l'esecuzione di questo componente. - La sezione
environment
contiene un'immagine Docker e un file YAML conda. Il file di origine si trova nel repository di esempio.
Ora sono disponibili tutti i file di origine per il componente score-model.
Caricare i componenti nella pipeline di compilazione
Per il componente prep-data e il componente train-model definiti dalla funzione Python è possibile importare i componenti esattamente come le normali funzioni Python.
Nel codice seguente si importano rispettivamente le funzioni prepare_data_component()
e keras_train_component()
dal file prep_component.py
nella cartella prep
e dal file train_component
nella cartella train
.
%load_ext autoreload
%autoreload 2
# load component function from component python file
from prep.prep_component import prepare_data_component
from train.train_component import keras_train_component
# print hint of components
help(prepare_data_component)
help(keras_train_component)
Per il componente score definito da YAML, è possibile usare la funzione load_component()
per il caricamento.
# load component function from yaml
keras_score_component = load_component(source="./score/score.yaml")
Creare la pipeline
Sono stati ora creati e caricati tutti i componenti e i dati di input per compilare la pipeline. È possibile comporli in una pipeline:
Nota
Per usare l'elaborazione serverless, aggiungere from azure.ai.ml.entities import ResourceConfiguration
all'inizio.
Sostituire quindi:
default_compute=cpu_compute_target,
condefault_compute="serverless",
train_node.compute = gpu_compute_target
contrain_node.resources = "ResourceConfiguration(instance_type="Standard_NC6s_v3",instance_count=2)
# define a pipeline containing 3 nodes: Prepare data node, train node, and score node
@pipeline(
default_compute=cpu_compute_target,
)
def image_classification_keras_minist_convnet(pipeline_input_data):
"""E2E image classification pipeline with keras using python sdk."""
prepare_data_node = prepare_data_component(input_data=pipeline_input_data)
train_node = keras_train_component(
input_data=prepare_data_node.outputs.training_data
)
train_node.compute = gpu_compute_target
score_node = keras_score_component(
input_data=prepare_data_node.outputs.test_data,
input_model=train_node.outputs.output_model,
)
# create a pipeline
pipeline_job = image_classification_keras_minist_convnet(pipeline_input_data=mnist_ds)
La pipeline ha un ambiente di calcolo predefinito cpu_compute_target
, ovvero se non si specifica l'ambiente di calcolo per un nodo specifico, tale nodo verrà eseguito nell'ambiente di calcolo predefinito.
La pipeline ha un input a livello di pipeline pipeline_input_data
. È possibile assegnare valore all'input della pipeline quando si invia un processo della pipeline.
La pipeline contiene tre nodi, prepare_data_node, train_node e score_node.
input_data
diprepare_data_node
usa il valore dipipeline_input_data
.input_data
ditrain_node
proviene dall'outputtraining_data
di prepare_data_node.input_data
di score_node proviene dall'outputtest_data
di prepare_data_node einput_model
proviene daoutput_model
di train_node.Poiché
train_node
eseguirà il training di un modello CNN, è possibile specificarne l'ambiente di calcolo come gpu_compute_target, che può migliorare le prestazioni di training.
Inviare il processo della pipeline
Dopo aver costruito la pipeline, è possibile eseguire l'invio all'area di lavoro. Per inviare un processo, è necessario innanzitutto connettersi a un'area di lavoro.
Ottenere l'accesso all'area di lavoro
Configurare le credenziali
Si userà DefaultAzureCredential
per ottenere l'accesso all'area di lavoro. DefaultAzureCredential
deve essere in grado di gestire la maggior parte degli scenari di autenticazione di Azure SDK.
Se non funziona, vedere i riferimenti per altre credenziali disponibili: configure credential example, azure-identity reference doc.
try:
credential = DefaultAzureCredential()
# Check if given credential can get token successfully.
credential.get_token("https://management.azure.com/.default")
except Exception as ex:
# Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work
credential = InteractiveBrowserCredential()
Ottenere un handle in un'area di lavoro con ambiente di calcolo
Creare un oggetto MLClient
per gestire i servizi di Azure Machine Learning. Se si usa l'elaborazione serverless, non è necessario creare questi ambienti di calcolo.
# Get a handle to workspace
ml_client = MLClient.from_config(credential=credential)
# Retrieve an already attached Azure Machine Learning Compute.
cpu_compute_target = "cpu-cluster"
print(ml_client.compute.get(cpu_compute_target))
gpu_compute_target = "gpu-cluster"
print(ml_client.compute.get(gpu_compute_target))
Importante
Questo frammento di codice prevede che il file JSON di configurazione dell'area di lavoro venga salvato nella directory corrente o nel relativo elemento padre. Per altre informazioni sulla creazione di un'area di lavoro, vedere Creare risorse dell'area di lavoro. Per altre informazioni sul salvataggio della configurazione in un file, vedere Creare un file di configurazione dell'area di lavoro.
Inviare un processo della pipeline all'area di lavoro
A questo punto si ottiene un handle per l'area di lavoro ed è possibile inviare il processo della pipeline.
pipeline_job = ml_client.jobs.create_or_update(
pipeline_job, experiment_name="pipeline_samples"
)
pipeline_job
Il codice precedente invia questo processo della pipeline di classificazione delle immagini all'esperimento denominato pipeline_samples
. Se non esiste, l'esperimento verrà creato automaticamente. pipeline_input_data
usa fashion_ds
.
La chiamata a pipeline_job
produce un output simile al seguente:
La chiamata a submit
per Experiment
viene completata rapidamente e produce un output simile al seguente:
Esperimento | Nome | Type | Status | Pagina dettagli |
---|---|---|---|---|
pipeline_samples | sharp_pipe_4gvqx6h1fb | pipeline | Preparazione | Collegamento allo studio di Azure Machine Learning. |
È possibile monitorare l'esecuzione della pipeline aprendo il collegamento oppure è possibile bloccarlo fino al completamento eseguendo:
# wait until the job completes
ml_client.jobs.stream(pipeline_job.name)
Importante
La prima esecuzione della pipeline richiede circa 15 minuti. Devono essere scaricate tutte le dipendenze, quindi viene creata un'immagine Docker e viene effettuato il provisioning o la creazione dell'ambiente Python. Una seconda esecuzione della pipeline richiede molto meno tempo, perché queste risorse vengono riutilizzate e non create. Tuttavia, il tempo di esecuzione totale dipende dal carico di lavoro degli script e dai processi in esecuzione in ogni passaggio della pipeline.
Estrarre output ed eseguire il debug della pipeline nell'interfaccia utente
È possibile aprire Link to Azure Machine Learning studio
, ovvero la pagina dei dettagli del processo della pipeline. Il grafico della pipeline sarà simile al seguente.
È possibile controllare i log e gli output di ogni componente facendo clic con il pulsante destro del mouse sul componente oppure selezionare il componente per aprire il relativo riquadro dei dettagli. Per altre informazioni su come eseguire il debug della pipeline nell'interfaccia utente, vedere Come usare la pagina per eseguire il debug degli errori della pipeline.
(Facoltativo) Registrare i componenti nell'area di lavoro
Nella sezione precedente è stata compilata una pipeline usando tre componenti per completare end-to-end un'attività di classificazione delle immagini. È anche possibile registrare i componenti nell'area di lavoro in modo che possano essere condivisi e riutilizzati all'interno dell'area di lavoro. Di seguito è riportato un esempio per registrare il componente prep-data.
try:
# try get back the component
prep = ml_client.components.get(name="prep_data", version="1")
except:
# if not exists, register component using following code
prep = ml_client.components.create_or_update(prepare_data_component)
# list all components registered in workspace
for c in ml_client.components.list():
print(c)
Usando ml_client.components.get()
è possibile ottenere un componente registrato in base al nome e alla versione. Usando ml_client.components.create_or_update()
è possibile registrare un componente caricato in precedenza dalla funzione Python o da YAML.
Passaggi successivi
- Per altri esempi sulla creazione di pipeline tramite Machine Learning SDK, vedere il repository di esempi.
- Per informazioni su come usare l'interfaccia utente dello studio per inviare ed eseguire il debug della pipeline, vedere Come creare pipeline usando il componente nell'interfaccia utente.
- Per informazioni su come usare l'interfaccia della riga di comando di Azure Machine Learning per creare componenti e pipeline, vedere Come creare pipeline usando il componente con l'interfaccia della riga di comando.
- Per informazioni su come distribuire le pipeline nell'ambiente di produzione usando endpoint Batch, vedere Come distribuire pipeline con endpoint Batch.