Dela via


Självstudie: Skapa en Azure Mašinsko učenje-pipeline för bildklassificering

GÄLLER FÖR: Python SDK azureml v1

Kommentar

En självstudiekurs som använder SDK v2 för att skapa en pipeline finns i Självstudie: Använda ML-pipelines för ml-arbetsflöden i produktion med Python SDK v2 i en Jupyter Notebook.

I den här självstudien får du lära dig hur du skapar en Azure-Mašinsko učenje pipeline för att förbereda data och träna en maskininlärningsmodell. 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.

I den här självstudien slutför du följande uppgifter:

  • Konfigurera arbetsyta
  • Skapa ett experiment för att lagra ditt arbete
  • Etablera en ComputeTarget för att utföra arbetet
  • Skapa en datauppsättning där komprimerade data ska lagras
  • Skapa ett pipelinesteg för att förbereda data för träning
  • Definiera en körningsmiljö där träning ska utföras
  • Skapa ett pipelinesteg för att definiera det neurala nätverket och utföra träningen
  • Skapa en pipeline från pipelinestegen
  • Kör pipelinen i experimentet
  • Granska utdata från stegen och det tränade neurala nätverket
  • Registrera modellen för vidare användning

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 Mašinsko učenje i dag.

Förutsättningar

  • Slutför Skapa resurser för att komma igång om du inte redan har en Azure-Mašinsko učenje arbetsyta.
  • En Python-miljö där du har installerat både paketen azureml-core och azureml-pipeline . Den här miljön är till för att definiera och kontrollera dina Azure-Mašinsko učenje resurser och är skild från miljön som används vid körning för träning.

Viktigt!

För närvarande är den senaste Python-versionen kompatibel med azureml-pipeline Python 3.8. Om du har problem med att azureml-pipeline installera paketet kontrollerar du att det python --version är en kompatibel version. Mer information finns i dokumentationen för din virtuella Python-miljöhanterare (venv, condaoch så vidare).

Starta en interaktiv Python-session

I den här självstudien används Python SDK för Azure Mašinsko učenje för att skapa och styra en Azure Mašinsko učenje-pipeline. Självstudien förutsätter att du kommer att köra kodfragmenten interaktivt i antingen en Python REPL-miljö eller en Jupyter-notebook-fil.

  • Den här självstudien baseras på notebook-filen image-classification.ipynb som finns i python-sdk/tutorial/using-pipelines katalogen på Azure Mašinsko učenje Examples-lagringsplatsen. Källkoden för själva stegen finns i underkatalogen keras-mnist-fashion .

Importtyper

Importera alla Typer av Azure Mašinsko učenje som du behöver för den här självstudien:

import os
import azureml.core
from azureml.core import (
    Workspace,
    Experiment,
    Dataset,
    Datastore,
    ComputeTarget,
    Environment,
    ScriptRunConfig
)
from azureml.data import OutputFileDatasetConfig
from azureml.core.compute import AmlCompute
from azureml.core.compute_target import ComputeTargetException
from azureml.pipeline.steps import PythonScriptStep
from azureml.pipeline.core import Pipeline

# check core SDK version number
print("Azure Machine Learning SDK Version: ", azureml.core.VERSION)

Azure Mašinsko učenje SDK-versionen bör vara 1.37 eller senare. Om det inte är det uppgraderar du med pip install --upgrade azureml-core.

Konfigurera arbetsyta

Skapa ett arbetsyteobjekt från den befintliga Azure Mašinsko učenje-arbetsytan.

workspace = Workspace.from_config()

Viktigt!

Det här kodfragmentet förväntar sig att konfigurationen av arbetsytan 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.

Skapa infrastrukturen för din pipeline

Skapa ett Experiment objekt som innehåller resultatet av dina pipelinekörningar:

exp = Experiment(workspace=workspace, name="keras-mnist-fashion")

Skapa en ComputeTarget som representerar den datorresurs som pipelinen ska köras på. Det enkla neurala nätverk som används i den här självstudien tränar på bara några minuter även på en CPU-baserad dator. Om du vill använda en GPU för träning anger du use_gpu till True. Etableringen av ett beräkningsmål tar vanligtvis cirka fem minuter.

use_gpu = False

# choose a name for your cluster
cluster_name = "gpu-cluster" if use_gpu else "cpu-cluster"

found = False
# Check if this compute target already exists in the workspace.
cts = workspace.compute_targets
if cluster_name in cts and cts[cluster_name].type == "AmlCompute":
    found = True
    print("Found existing compute target.")
    compute_target = cts[cluster_name]
if not found:
    print("Creating a new compute target...")
    compute_config = AmlCompute.provisioning_configuration(
        vm_size= "STANDARD_NC6" if use_gpu else "STANDARD_D2_V2"
        # vm_priority = 'lowpriority', # optional
        max_nodes=4,
    )

    # Create the cluster.
    compute_target = ComputeTarget.create(workspace, cluster_name, compute_config)

    # Can poll for a minimum number of nodes and for a specific timeout.
    # If no min_node_count is provided, it will use the scale settings for the cluster.
    compute_target.wait_for_completion(
        show_output=True, min_node_count=None, timeout_in_minutes=10
    )
# For a more detailed view of current AmlCompute status, use get_status().print(compute_target.get_status().serialize())

Kommentar

GPU-tillgänglighet beror på kvoten för din Azure-prenumeration och på Azure-kapacitet. Se Hantera och öka kvoter för resurser med Azure Machine Learning.

Skapa en datauppsättning för Azure-lagrade data

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 .

Om du vill skapa en Dataset som refererar till webbaserade data kör du:

data_urls = ["https://data4mldemo6150520719.blob.core.windows.net/demo/mnist-fashion"]
fashion_ds = Dataset.File.from_files(data_urls)

# list the files referenced by fashion_ds
print(fashion_ds.to_path())

Den här koden slutförs snabbt. Underliggande data finns kvar i Azure Storage-resursen som anges i matrisen data_urls .

Skapa pipelinesteget för förberedelse av data

Det första steget i den här pipelinen konverterar komprimerade datafiler fashion_ds till en datauppsättning på din egen arbetsyta som består av CSV-filer som är redo att användas i träning. När de har registrerat sig på arbetsytan kan dina medarbetare komma åt dessa data för sin egen analys, utbildning och så vidare

datastore = workspace.get_default_datastore()
prepared_fashion_ds = OutputFileDatasetConfig(
    destination=(datastore, "outputdataset/{run-id}")
).register_on_complete(name="prepared_fashion_ds")

Koden ovan anger en datauppsättning som baseras på utdata från ett pipelinesteg. De underliggande bearbetade filerna placeras i arbetsytans standarddatalagers bloblagring på den sökväg som anges i destination. Datauppsättningen registreras på arbetsytan med namnet prepared_fashion_ds.

Skapa pipelinestegets källa

Koden som du har kört hittills har skapat och kontrollerat Azure-resurser. Nu är det dags att skriva kod som gör det första steget i domänen.

Om du följer exemplet i lagringsplatsen Azure Mašinsko učenje Examples är källfilen redan tillgänglig som keras-mnist-fashion/prepare.py.

Om du arbetar från grunden skapar du en underkatalog med namnet keras-mnist-fashion/. Skapa en ny fil, lägg till följande kod i den och ge filen prepare.pynamnet .

# prepare.py
# Converts MNIST-formatted files at the passed-in input path to a passed-in output path
import os
import sys

# Conversion routine for MNIST binary format
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()

# The MNIST-formatted source
mounted_input_path = sys.argv[1]
# The output directory at which the outputs will be written
mounted_output_path = sys.argv[2]

# Create the output directory
os.makedirs(mounted_output_path, exist_ok=True)

# Convert the training data
convert(
    os.path.join(mounted_input_path, "mnist-fashion/train-images-idx3-ubyte"),
    os.path.join(mounted_input_path, "mnist-fashion/train-labels-idx1-ubyte"),
    os.path.join(mounted_output_path, "mnist_train.csv"),
    60000,
)

# Convert the test data
convert(
    os.path.join(mounted_input_path, "mnist-fashion/t10k-images-idx3-ubyte"),
    os.path.join(mounted_input_path, "mnist-fashion/t10k-labels-idx1-ubyte"),
    os.path.join(mounted_output_path, "mnist_test.csv"),
    10000,
)

Koden i prepare.py tar två kommandoradsargument: den första tilldelas till mounted_input_path och den andra till mounted_output_path. Om den underkatalogen inte finns skapar anropet till os.makedirs den. Sedan konverterar programmet tränings- och testdata och matar ut kommaavgränsade filer till mounted_output_path.

Ange pipelinesteget

Tillbaka i Python-miljön som du använder för att ange pipelinen kör du den här koden för att skapa en PythonScriptStep för din förberedelsekod:

script_folder = "./keras-mnist-fashion"

prep_step = PythonScriptStep(
    name="prepare step",
    script_name="prepare.py",
    # On the compute target, mount fashion_ds dataset as input, prepared_fashion_ds as output
    arguments=[fashion_ds.as_named_input("fashion_ds").as_mount(), prepared_fashion_ds],
    source_directory=script_folder,
    compute_target=compute_target,
    allow_reuse=True,
)

Anropet till PythonScriptStep anger att när pipelinesteget körs:

  • Alla filer i script_folder katalogen laddas upp till compute_target
  • Bland de uppladdade källfilerna körs filen prepare.py
  • Datauppsättningarna fashion_ds och prepared_fashion_ds monteras på compute_target och visas som kataloger
  • Sökvägen till fashion_ds filerna blir det första argumentet till prepare.py. I prepare.pytilldelas det här argumentet till mounted_input_path
  • Sökvägen till prepared_fashion_ds blir det andra argumentet till prepare.py. I prepare.pytilldelas det här argumentet till mounted_output_path
  • Eftersom allow_reuse är True, kommer den inte att köras igen förrän dess källfiler eller indata ändras
  • Detta PythonScriptStep kommer att namnges prepare step

Modularitet och återanvändning är viktiga fördelar med pipelines. Azure Mašinsko učenje kan automatiskt fastställa källkods- eller datauppsättningsändringar. Utdata från ett steg som inte påverkas återanvänds utan att du kör stegen igen om allow_reuse är True. Om ett steg förlitar sig på en datakälla utanför Azure Mašinsko učenje som kan ändras (till exempel en URL som innehåller försäljningsdata) anger du allow_reuse till False och pipelinesteget körs varje gång pipelinen körs.

Skapa träningssteget

När data har konverterats från det komprimerade formatet till CSV-filer kan de användas för att träna ett convolutional neuralt nätverk.

Skapa träningsstegets källa

Med större pipelines är det en bra idé att placera varje stegs källkod i en separat katalog (src/prepare/, src/train/och så vidare) men för den här självstudien är det bara att använda eller skapa filen train.py i samma keras-mnist-fashion/ källkatalog.

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.utils import to_categorical
from keras.callbacks import Callback

import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from azureml.core import Run

# dataset object from the run
run = Run.get_context()
dataset = run.input_datasets["prepared_fashion_ds"]

# split dataset into train and test set
(train_dataset, test_dataset) = dataset.random_split(percentage=0.8, seed=111)

# load dataset into pandas dataframe
data_train = train_dataset.to_pandas_dataframe()
data_test = test_dataset.to_pandas_dataframe()

img_rows, img_cols = 28, 28
input_shape = (img_rows, img_cols, 1)

X = np.array(data_train.iloc[:, 1:])
y = to_categorical(np.array(data_train.iloc[:, 0]))

# here we split validation data to optimiza classifier during training
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=13)

# test data
X_test = np.array(data_test.iloc[:, 1:])
y_test = to_categorical(np.array(data_test.iloc[:, 0]))


X_train = (
    X_train.reshape(X_train.shape[0], img_rows, img_cols, 1).astype("float32") / 255
)
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1).astype("float32") / 255
X_val = X_val.reshape(X_val.shape[0], img_rows, img_cols, 1).astype("float32") / 255

batch_size = 256
num_classes = 10
epochs = 10

# construct neuron network
model = Sequential()
model.add(
    Conv2D(
        32,
        kernel_size=(3, 3),
        activation="relu",
        kernel_initializer="he_normal",
        input_shape=input_shape,
    )
)
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), activation="relu"))
model.add(Dropout(0.4))
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(num_classes, activation="softmax"))

model.compile(
    loss=keras.losses.categorical_crossentropy,
    optimizer=keras.optimizers.Adam(),
    metrics=["accuracy"],
)

# start an Azure ML run
run = Run.get_context()


class LogRunMetrics(Callback):
    # callback at the end of every epoch
    def on_epoch_end(self, epoch, log):
        # log a value repeated which creates a list
        run.log("Loss", log["loss"])
        run.log("Accuracy", log["accuracy"])


history = model.fit(
    X_train,
    y_train,
    batch_size=batch_size,
    epochs=epochs,
    verbose=1,
    validation_data=(X_val, y_val),
    callbacks=[LogRunMetrics()],
)

score = model.evaluate(X_test, y_test, verbose=0)

# log a single value
run.log("Final test loss", score[0])
print("Test loss:", score[0])

run.log("Final test accuracy", score[1])
print("Test accuracy:", score[1])

plt.figure(figsize=(6, 3))
plt.title("Fashion MNIST with Keras ({} epochs)".format(epochs), fontsize=14)
plt.plot(history.history["accuracy"], "b-", label="Accuracy", lw=4, alpha=0.5)
plt.plot(history.history["loss"], "r--", label="Loss", lw=4, alpha=0.5)
plt.legend(fontsize=12)
plt.grid(True)

# log an image
run.log_image("Loss v.s. Accuracy", plot=plt)

# create a ./outputs/model folder in the compute target
# files saved in the "./outputs" folder are automatically uploaded into run history
os.makedirs("./outputs/model", exist_ok=True)

# serialize NN architecture to JSON
model_json = model.to_json()
# save model JSON
with open("./outputs/model/model.json", "w") as f:
    f.write(model_json)
# save model weights
model.save_weights("./outputs/model/model.h5")
print("model saved in ./outputs/model folder")

Merparten av den här koden bör vara bekant för ML-utvecklare:

  • Data partitioneras i tränings- och valideringsuppsättningar för träning och en separat testunderuppsättning för slutlig bedömning
  • Indataformen är 28x28x1 (endast 1 eftersom indata är gråskala), det kommer att finnas 256 indata i en batch och det finns 10 klasser
  • Antalet utbildningsepoker blir 10
  • Modellen har tre konvolutional lager, med max pooling och dropout, följt av ett tätt lager och softmax huvud
  • Modellen är monterad för 10 epoker och utvärderas sedan
  • Modellarkitekturen skrivs till outputs/model/model.json och vikterna till outputs/model/model.h5

En del av koden är dock specifik för Azure Mašinsko učenje. run = Run.get_context() hämtar ett Run objekt som innehåller den aktuella tjänstkontexten. Källan train.py använder det här run objektet för att hämta indatauppsättningen via dess namn (ett alternativ till koden i prepare.py som hämtade datamängden via matrisen argv med skriptargument).

Objektet run används också för att logga träningsförloppet i slutet av varje epok och, i slutet av träningen, för att logga grafen över förlust och noggrannhet över tid.

Skapa steget träningspipeline

Träningssteget har en något mer komplex konfiguration än förberedelsesteget. Förberedelsesteget använde endast python-standardbibliotek. Vanligare är att du behöver ändra körningsmiljön där källkoden körs.

Skapa en fil conda_dependencies.yml med följande innehåll:

dependencies:
- python=3.7
- pip:
  - azureml-core
  - azureml-dataset-runtime
  - keras==2.4.3
  - tensorflow==2.4.3
  - numpy
  - scikit-learn
  - pandas
  - matplotlib

Klassen Environment representerar körningsmiljön där en maskininlärningsuppgift körs. Associera specifikationen ovan med träningskoden med:

keras_env = Environment.from_conda_specification(
    name="keras-env", file_path="./conda_dependencies.yml"
)

train_cfg = ScriptRunConfig(
    source_directory=script_folder,
    script="train.py",
    compute_target=compute_target,
    environment=keras_env,
)

När du skapar själva träningssteget används kod som liknar den kod som används för att skapa förberedelsesteget:

train_step = PythonScriptStep(
    name="train step",
    arguments=[
        prepared_fashion_ds.read_delimited_files().as_input(name="prepared_fashion_ds")
    ],
    source_directory=train_cfg.source_directory,
    script_name=train_cfg.script,
    runconfig=train_cfg.run_config,
)

Skapa och köra pipelinen

Nu när du har angett dataindata och utdata och skapat pipelinens steg kan du skapa dem i en pipeline och köra den:

pipeline = Pipeline(workspace, steps=[prep_step, train_step])
run = exp.submit(pipeline)

Objektet Pipeline som du skapar körs i din workspace och består av de förberedelse- och träningssteg som du har angett.

Kommentar

Den här pipelinen har ett enkelt beroendediagram: träningssteget förlitar sig på förberedelsesteget och förberedelsesteget förlitar sig på datauppsättningen fashion_ds . Produktionspipelines har ofta mycket mer komplexa beroenden. Steg kan vara beroende av flera uppströmssteg, en källkodsändring i ett tidigt steg kan få långtgående konsekvenser och så vidare. Azure Mašinsko učenje spårar dessa problem åt dig. Du behöver bara skicka in matrisen steps för och Azure Mašinsko učenje tar hand om beräkningen av körningsdiagrammet.

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

Submitted PipelineRun 5968530a-abcd-1234-9cc1-46168951b5eb
Link to Azure Machine Learning Portal: https://ml.azure.com/runs/abc-xyz...

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

run.wait_for_completion(show_output=True)

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.

När pipelinen är klar kan du hämta de mått som du loggade i träningssteget:

run.find_step_run("train step")[0].get_metrics()

Om du är nöjd med måtten kan du registrera modellen på din arbetsyta:

run.find_step_run("train step")[0].register_model(
    model_name="keras-model",
    model_path="outputs/model/",
    datasets=[("train test data", fashion_ds)],
)

Rensa resurser

Slutför inte det här avsnittet om du planerar att köra andra Azure-Mašinsko učenje självstudier.

Stoppa beräkningsinstansen

Om du använde en beräkningsinstans stoppar du den virtuella datorn när du inte använder den för att minska kostnaderna.

  1. På din arbetsyta väljer du Beräkning.

  2. I listan väljer du namnet på beräkningsinstansen.

  3. Välj Stoppa.

  4. När du är redo att använda servern igen väljer du Start.

Ta bort allt

Om du inte planerar att använda de resurser som du skapade, tar du bort dem så att du inte debiteras:

  1. I Azure-portalen går du till den vänstra menyn och väljer Resursgrupper.
  2. I listan över resursgrupper väljer du den resursgrupp som du skapade.
  3. Välj Ta bort resursgrupp.
  4. Ange resursgruppsnamnet. Välj sedan Ta bort.

Du kan också behålla resursgruppen men ta bort en enstaka arbetsyta. Visa egenskaperna för arbetsytan och välj sedan Ta bort.

Nästa steg

I den här självstudien använde du följande typer:

  • Workspace Representerar din Azure Mašinsko učenje-arbetsyta. Den innehöll:
    • Som Experiment innehåller resultatet av träningskörningar av din pipeline
    • Den Dataset som lazily läste in data som lagras i Fashion-MNIST-dataarkivet
    • Som ComputeTarget representerar de datorer som pipelinestegen körs på
    • Det Environment är den körningsmiljö där pipelinestegen körs
    • Det Pipeline som utgör PythonScriptStep stegen i en helhet
    • Det Model som du registrerade efter att ha varit nöjd med träningsprocessen

Objektet Workspace innehåller referenser till andra resurser (notebook-filer, slutpunkter och så vidare) som inte användes i den här självstudien. Mer information finns i Vad är en Azure Mašinsko učenje-arbetsyta?.

Höjer OutputFileDatasetConfig upp utdata från en körning till en filbaserad datauppsättning. Mer information om datauppsättningar och hur du arbetar med data finns i Så här kommer du åt data.

Mer information om beräkningsmål och miljöer finns i Vad är beräkningsmål i Azure Mašinsko učenje? och Vad är Azure Mašinsko učenje miljöer?

Associerar ScriptRunConfig en ComputeTarget och Environment med Python-källfiler. A PythonScriptStep tar det ScriptRunConfig och definierar dess indata och utdata, som i den här pipelinen var fildatauppsättningen OutputFileDatasetConfigsom skapades av .

Fler exempel på hur du skapar pipelines med hjälp av SDK:t för maskininlärning finns i exempellagringsplatsen.