Självstudie: Skapa en Azure Machine Learning-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 lär du dig hur du skapar en Azure Machine Learning-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 Machine Learning idag.
Förutsättningar
- Slutför Skapa resurser för att komma igång om du inte redan har en Azure Machine Learning-arbetsyta.
- En Python-miljö där du har installerat både paketen
azureml-core
ochazureml-pipeline
. 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.
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
, conda
och så vidare).
Starta en interaktiv Python-session
I den här självstudien används Python SDK för Azure Machine Learning för att skapa och styra en Azure Machine Learning-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 ipython-sdk/tutorial/using-pipelines
katalogen på Azure Machine Learning Examples-lagringsplatsen . Källkoden för själva stegen finns i underkatalogenkeras-mnist-fashion
.
Importtyper
Importera alla Azure Machine Learning-typer 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 Machine Learning 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 Machine Learning-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 på lagringsplatsen Azure Machine Learning-exempel ä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.py
namnet .
# 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 tillcompute_target
- Bland de uppladdade källfilerna körs filen
prepare.py
- Datauppsättningarna
fashion_ds
ochprepared_fashion_ds
monteras påcompute_target
och visas som kataloger - Sökvägen till
fashion_ds
filerna blir det första argumentet tillprepare.py
. Iprepare.py
tilldelas det här argumentet tillmounted_input_path
- Sökvägen till
prepared_fashion_ds
blir det andra argumentet tillprepare.py
. Iprepare.py
tilldelas det här argumentet tillmounted_output_path
- Eftersom
allow_reuse
ärTrue
, kommer den inte att köras igen förrän dess källfiler eller indata ändras - Detta
PythonScriptStep
kommer att namngesprepare step
Modularitet och återanvändning är viktiga fördelar med pipelines. Azure Machine Learning 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 Machine Learning 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 tilloutputs/model/model.h5
En del av koden är dock specifik för Azure Machine Learning. 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 Machine Learning spårar dessa problem åt dig. Du behöver bara skicka in matrisen steps
för och Azure Machine Learning tar hand om att beräkna 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 Machine Learning-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.
På din arbetsyta väljer du Beräkning.
I listan väljer du namnet på beräkningsinstansen.
Välj Stoppa.
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:
- I Azure Portal går du till den vänstra menyn och väljer Resursgrupper.
- I listan över resursgrupper väljer du den resursgrupp som du skapade.
- Välj Ta bort resursgrupp.
- 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 Machine Learning-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örPythonScriptStep
stegen i en helhet - Det
Model
som du registrerade efter att ha varit nöjd med träningsprocessen
- Som
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 Machine Learning-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 Machine Learning? och Vad är Azure Machine Learning-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 OutputFileDatasetConfig
som skapades av .
Fler exempel på hur du skapar pipelines med hjälp av SDK:t för maskininlärning finns i exempellagringsplatsen.