Skapa och köra maskininlärningspipelines med hjälp av komponenter med Azure Machine Learning SDK v2

GÄLLER FÖR: Python SDK azure-ai-ml v2 (aktuell)

I den här artikeln lär du dig hur du skapar en Azure Machine Learning-pipeline med Python SDK v2 för att slutföra en bildklassificeringsuppgift som innehåller tre steg: förbereda data, träna en bildklassificeringsmodell och poängsätta modellen. Maskininlärningspipelines optimerar arbetsflödet med hastighet, portabilitet och återanvändning, så att du kan fokusera på maskininlärning i stället för infrastruktur och automatisering.

Exemplet tränar ett litet Keras convolutional neuralt nätverk för att klassificera bilder i Fashion MNIST-datauppsättningen. Pipelinen ser ut som följande.

Skärmbild som visar pipelinediagram över Keras-exemplet för bildklassificering.

I den här artikeln utför du följande uppgifter:

  • Förbereda indata för pipelinejobbet
  • Skapa tre komponenter för att förbereda data, träna och poängsätta
  • Skapa en pipeline från komponenterna
  • Få åtkomst till arbetsytan med beräkning
  • Skicka pipelinejobbet
  • Granska utdata från komponenterna och det tränade neurala nätverket
  • (Valfritt) Registrera komponenten för ytterligare återanvändning och delning på arbetsytan

Om du inte har någon Azure-prenumeration skapar du ett kostnadsfritt konto innan du börjar. Prova den kostnadsfria eller betalda versionen av Azure Machine Learning idag.

Förutsättningar

  • Azure Machine Learning-arbetsyta – om du inte har någon slutför du självstudien Skapa resurser.

  • En Python-miljö där du har installerat Azure Machine Learning Python SDK v2 – installationsanvisningar – kontrollerar avsnittet komma igång. Den här miljön är till för att definiera och kontrollera dina Azure Machine Learning-resurser och är skild från den miljö som används vid körning för träning.

  • Lagringsplats för klonexempel

    Om du vill köra träningsexemplen klonar du först exempellagringsplatsen och ändrar till sdk katalogen:

    git clone --depth 1 https://github.com/Azure/azureml-examples
    cd azureml-examples/sdk
    

Starta en interaktiv Python-session

Den här artikeln använder Python SDK för Azure Machine Learning för att skapa och styra en Azure Machine Learning-pipeline. Artikeln förutsätter att du kommer att köra kodfragmenten interaktivt i antingen en Python REPL-miljö eller en Jupyter Notebook.

Den här artikeln baseras på notebook-filen image_classification_keras_minist_convnet.ipynb som finns i sdk/python/jobs/pipelines/2e_image_classification_keras_minist_convnet katalogen på azure Machine Learning Examples-lagringsplatsen .

Importera obligatoriska bibliotek

Importera alla Bibliotek som krävs för Azure Machine Learning som du behöver för den här artikeln:

# 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

Förbereda indata för pipelinejobbet

Du måste förbereda indata för den här bildklassificeringspipelinen.

Fashion-MNIST är en datamängd med modebilder uppdelade i 10 klasser. Varje bild är en 28x28 gråskalebild och det finns 60 000 tränings- och 10 000 testbilder. Som ett problem med bildklassificering är Fashion-MNIST svårare än den klassiska MNIST-handskrivna sifferdatabasen. Den distribueras i samma komprimerade binära form som den ursprungliga handskrivna sifferdatabasen.

Importera alla Bibliotek som krävs för Azure Machine Learning som du behöver.

Genom att definiera en Inputskapar du en referens till datakällans plats. Data finns kvar på den befintliga platsen, så ingen extra lagringskostnad tillkommer.

Skapa komponenter för att skapa pipeline

Bildklassificeringsuppgiften kan delas upp i tre steg: förbereda data, träna modell och poängmodell.

Azure Machine Learning-komponenten är en fristående kod som utför ett steg i en maskininlärningspipeline. I den här artikeln skapar du tre komponenter för bildklassificeringsuppgiften:

  • Förbereda data för träning och testning
  • Träna ett neuralt nätverk för bildklassificering med hjälp av träningsdata
  • Poängsätta modellen med hjälp av testdata

För varje komponent måste du förbereda följande:

  1. Förbereda Python-skriptet som innehåller körningslogik

  2. Definiera komponentens gränssnitt

  3. Lägg till andra metadata för komponenten, inklusive körningsmiljö, kommando för att köra komponenten och så vidare.

I nästa avsnitt visas skapa komponenter på två olika sätt: de två första komponenterna med Python-funktionen och den tredje komponenten med YAML-definition.

Skapa komponenten för förberedelse av data

Den första komponenten i den här pipelinen konverterar komprimerade datafiler fashion_ds till två csv-filer, en för träning och den andra för bedömning. Du använder Python-funktionen för att definiera den här komponenten.

Om du följer exemplet i lagringsplatsen för Azure Machine Learning-exempel är källfilerna redan tillgängliga i prep/ mappen. Den här mappen innehåller två filer för att konstruera komponenten: prep_component.py, som definierar komponenten och conda.yaml, som definierar körningsmiljön för komponenten.

Definiera komponent med python-funktionen

Genom att använda command_component() funktionen som dekoratör kan du enkelt definiera komponentens gränssnitt, metadata och kod som ska köras från en Python-funktion. Varje dekorerad Python-funktion omvandlas till en enda statisk specifikation (YAML) som pipelinetjänsten kan bearbeta.

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

Koden ovan definierar en komponent med visningsnamn Prep Data med hjälp av @command_component dekoratör:

  • name är komponentens unika identifierare.

  • version är den aktuella versionen av komponenten. En komponent kan ha flera versioner.

  • display_name är ett eget visningsnamn för komponenten i användargränssnittet, vilket inte är unikt.

  • description beskriver vanligtvis vilken uppgift komponenten kan utföra.

  • environment anger körningsmiljön för den här komponenten. Miljön för den här komponenten anger en docker-avbildning och refererar till conda.yaml filen.

    Filen conda.yaml innehåller alla paket som används för komponenten, till exempel följande:

    name: imagekeras_prep_conda_env
    channels:
      - defaults
    dependencies:
      - python=3.7.11
      - pip=20.0
      - pip:
        - mldesigner==0.1.0b4
    
  • Funktionen prepare_data_component definierar en indata för input_data och två utdata för training_data och test_data. input_data är indatasökvägen. training_data och test_data är utdatasökvägar för träningsdata och testdata.

  • Den här komponenten konverterar data från input_data till en csv för träningsdata till training_data och en csv-testdata till test_data.

Så här ser en komponent ut i studiogränssnittet.

  • En komponent är ett block i ett pipelinediagram.
  • , input_datatraining_data och test_data är portar för komponenten, som ansluter till andra komponenter för dataströmning.

Skärmbild av komponenten Prep Data i användargränssnittet och koden.

Nu har du förberett alla källfiler för komponenten Prep Data .

Skapa komponenten train-model

I det här avsnittet skapar du en komponent för att träna bildklassificeringsmodellen i Python-funktionen som komponenten Prep Data .

Skillnaden är att eftersom träningslogik är mer komplicerad kan du placera den ursprungliga träningskoden i en separat Python-fil.

Källfilerna för den här komponenten finns under train/ mappen i lagringsplatsen för Azure Machine Learning-exempel. Den här mappen innehåller tre filer för att konstruera komponenten:

  • train.py: innehåller den faktiska logiken för att träna modellen.
  • train_component.py: definierar komponentens gränssnitt och importerar funktionen i train.py.
  • conda.yaml: definierar körningsmiljön för komponenten.

Hämta ett skript som innehåller körningslogik

Filen train.py innehåller en vanlig Python-funktion som utför träningsmodelllogik för att träna ett Keras neuralt nätverk för bildklassificering. Information om hur du visar koden finns i filen train.py på GitHub.

Definiera komponent med python-funktionen

När du har definierat träningsfunktionen kan du använda @command_component i Azure Machine Learning SDK v2 för att omsluta funktionen som en komponent som kan användas i Azure Machine Learning-pipelines.

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)

Koden ovan definierar en komponent med visningsnamn Train Image Classification Keras med hjälp av @command_component:

  • Funktionen keras_train_component definierar en indata input_data där träningsdata kommer från, en indata epochs som anger epoker under träningen och en utdata output_model där utdata för modellfilen matas ut. Standardvärdet epochs för är 10. Körningslogik för den här komponenten kommer från train() funktionen ovan train.py .

Komponenten train-model har en något mer komplex konfiguration än komponenten prep-data. Är conda.yaml som följande:

name: imagekeras_train_conda_env
channels:
  - defaults
dependencies:
  - python=3.7.11
  - 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

Nu har du förberett alla källfiler för komponenten Train Image Classification Keras .

Skapa komponenten score-model

I det här avsnittet, förutom de tidigare komponenterna, skapar du en komponent för att poängsätta den tränade modellen via Yaml-specifikationen och skriptet.

Om du följer exemplet i lagringsplatsen för Azure Machine Learning-exempel är källfilerna redan tillgängliga i score/ mappen. Den här mappen innehåller tre filer för att konstruera komponenten:

  • score.py: innehåller komponentens källkod.
  • score.yaml: definierar gränssnittet och annan information om komponenten.
  • conda.yaml: definierar körningsmiljön för komponenten.

Hämta ett skript som innehåller körningslogik

Filen score.py innehåller en vanlig Python-funktion som utför träningsmodelllogik.

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)

Koden i score.py tar tre kommandoradsargument: input_data, input_model och output_result. Programmet bedömer indatamodellen med hjälp av indata och matar sedan ut bedömningsresultatet.

Definiera komponent via Yaml

I det här avsnittet lär du dig att skapa en komponentspecifikation i ett giltigt YAML-komponentspecifikationsformat. Den här filen anger följande information:

  • Metadata: namn, display_name, version, typ och så vidare.
  • Gränssnitt: indata och utdata
  • Kommando, kod och miljö: Kommandot, koden och miljön som används för att köra komponenten
$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 är komponentens unika identifierare. Dess visningsnamn är Score Image Classification Keras.
  • Den här komponenten har två indata och en utdata.
  • Källkodssökvägen för den definieras i code avsnittet och när komponenten körs i molnet laddas alla filer från den sökvägen upp som ögonblicksbild av den här komponenten.
  • Avsnittet command anger vilket kommando som ska köras när den här komponenten körs.
  • Avsnittet environment innehåller en docker-avbildning och en conda yaml-fil. Källfilen finns på exempellagringsplatsen.

Nu har du alla källfiler för komponenten score-model.

Läsa in komponenter för att skapa pipeline

För komponenten prep-data och train-model som definieras av Python-funktionen kan du importera komponenterna precis som vanliga Python-funktioner.

I följande kod importerar prepare_data_component() och keras_train_component() fungerar du från prep_component.py filen under prep mapp respektive train_component fil under train mapp.

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

För poängkomponent som definierats av yaml kan du använda load_component() funktionen för att läsa in.

# load component function from yaml
keras_score_component = load_component(source="./score/score.yaml")

Skapa din pipeline

Nu när du har skapat och läst in alla komponenter och indata för att skapa pipelinen. Du kan skapa dem i en pipeline:

Kommentar

Om du vill använda serverlös beräkning lägger du till from azure.ai.ml.entities import ResourceConfiguration längst upp. Ersätt sedan:

  • default_compute=cpu_compute_target, Med default_compute="serverless",
  • train_node.compute = gpu_compute_target Med train_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)

Pipelinen har en standardberäkning cpu_compute_target, vilket innebär att om du inte anger beräkning för en specifik nod körs den noden på standardberäkningen.

Pipelinen har indata pipeline_input_datapå pipelinenivå . Du kan tilldela värde till pipelineindata när du skickar ett pipelinejobb.

Pipelinen innehåller tre noder, prepare_data_node, train_node och score_node.

  • I input_dataprepare_data_node används värdet pipeline_input_dataför .

  • Av input_datatrain_node är från utdata från training_data prepare_data_node.

  • Score_node input_data kommer från utdata från test_data prepare_data_node och input_model är från output_model train_node.

  • Eftersom train_node kommer att träna en CNN-modell kan du ange dess beräkning som gpu_compute_target, vilket kan förbättra träningsprestandan.

Skicka ditt pipelinejobb

Nu när du har konstruerat pipelinen kan du skicka till din arbetsyta. Om du vill skicka ett jobb måste du först ansluta till en arbetsyta.

Få åtkomst till din arbetsyta

Konfigurera autentiseringsuppgifter

Vi använder DefaultAzureCredential för att få åtkomst till arbetsytan. DefaultAzureCredential ska kunna hantera de flesta autentiseringsscenarier i Azure SDK.

Referens för fler tillgängliga autentiseringsuppgifter om det inte fungerar för dig: konfigurera autentiseringsexempel, referensdokument för azure-identitet.

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

Hämta ett handtag till en arbetsyta med beräkning

Skapa ett MLClient objekt för att hantera Azure Machine Learning-tjänster. Om du använder serverlös beräkning behöver du inte skapa dessa beräkningar.

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

Viktigt!

Det här kodfragmentet förväntar sig att json-filen för arbetsytekonfiguration sparas i den aktuella katalogen eller dess överordnade. Mer information om hur du skapar en arbetsyta finns i Skapa arbetsyteresurser. Mer information om hur du sparar konfigurationen i filen finns i Skapa en konfigurationsfil för arbetsytan.

Skicka pipelinejobb till arbetsytan

Nu när du har fått ett handtag till din arbetsyta kan du skicka ditt pipelinejobb.

pipeline_job = ml_client.jobs.create_or_update(
    pipeline_job, experiment_name="pipeline_samples"
)
pipeline_job

Koden ovan skickar det här pipelinejobbet för bildklassificering för att experimentera med namnet pipeline_samples. Experimentet skapas automatiskt om det inte finns. Använder pipeline_input_datafashion_ds.

Anropet till pipeline_jobgenererar utdata som liknar:

Anropet till submit slutförs Experiment snabbt och genererar utdata som liknar:

Experiment Namn Type Status Informationssida
pipeline_samples sharp_pipe_4gvqx6h1fb Rörledning Förbereda Länk till Azure Machine Learning-studio.

Du kan övervaka pipelinekörningen genom att öppna länken eller blockera tills den har slutförts genom att köra:

# wait until the job completes
ml_client.jobs.stream(pipeline_job.name)

Viktigt!

Den första pipelinekörningen tar ungefär 15 minuter. Alla beroenden måste laddas ned, en Docker-avbildning skapas och Python-miljön etableras och skapas. Det tar betydligt mindre tid att köra pipelinen igen eftersom resurserna återanvänds i stället för att skapas. Den totala körningstiden för pipelinen beror dock på arbetsbelastningen för dina skript och de processer som körs i varje pipelinesteg.

Checka ut ut och felsöka din pipeline i användargränssnittet

Du kan öppna Link to Azure Machine Learning studio, som är jobbinformationssidan för din pipeline. Du ser pipelinediagrammet som följer.

Skärmbild av informationssidan för pipelinejobbet.

Du kan kontrollera loggarna och utdata för varje komponent genom att högerklicka på komponenten eller välja komponenten för att öppna dess informationsfönster. Mer information om hur du felsöker pipelinen i användargränssnittet finns i Så här använder du felsöka pipelinefel.

(Valfritt) Registrera komponenter till arbetsytan

I föregående avsnitt har du skapat en pipeline med tre komponenter till E2E för att slutföra en bildklassificeringsuppgift. Du kan också registrera komponenter till din arbetsyta så att de kan delas och återutfärdas på arbetsytan. Följande är ett exempel för att registrera prep-data-komponenten.

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)

Med kan ml_client.components.get()du hämta en registrerad komponent efter namn och version. Med kan ml_client.components.create_or_update()du registrera en komponent som tidigare lästs in från Python-funktionen eller yaml.

Nästa steg