Partilhar via


Tutorial: Criar um pipeline do Azure Machine Learning para classificação de imagens

APLICA-SE A: Python SDK azureml v1

Nota

Para obter um tutorial que usa o SDK v2 para criar um pipeline, consulte Tutorial: Usar pipelines de ML para fluxos de trabalho de ML de produção com o Python SDK v2 em um Jupyter Notebook.

Neste tutorial, você aprenderá a criar um pipeline do Azure Machine Learning para preparar dados e treinar um modelo de aprendizado de máquina. Os pipelines de aprendizado de máquina otimizam seu fluxo de trabalho com velocidade, portabilidade e reutilização, para que você possa se concentrar no aprendizado de máquina em vez de infraestrutura e automação.

O exemplo treina uma pequena rede neural convolucional Keras para classificar imagens no conjunto de dados Fashion MNIST.

Neste tutorial, vai concluir as seguintes tarefas:

  • Configurar a área de trabalho
  • Crie uma experiência para manter o seu trabalho
  • Provisionar um ComputeTarget para fazer o trabalho
  • Criar um conjunto de dados no qual armazenar dados compactados
  • Criar uma etapa de pipeline para preparar os dados para treinamento
  • Definir um ambiente de tempo de execução no qual executar o treinamento
  • Criar uma etapa de pipeline para definir a rede neural e executar o treinamento
  • Compor um pipeline a partir das etapas do pipeline
  • Execute o pipeline no experimento
  • Revise a saída das etapas e a rede neural treinada
  • Registar o modelo para posterior utilização

Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar. Experimente hoje mesmo a versão gratuita ou paga do Azure Machine Learning .

Pré-requisitos

  • Conclua Crie recursos para começar se ainda não tiver um espaço de trabalho do Azure Machine Learning.
  • Um ambiente Python no qual você instalou os azureml-core pacotes e azureml-pipeline . Esse ambiente serve para definir e controlar seus recursos do Azure Machine Learning e é separado do ambiente usado em tempo de execução para treinamento.

Importante

Atualmente, a versão mais recente do Python compatível com azureml-pipeline é o Python 3.8. Se tiver dificuldade em instalar o azureml-pipeline pacote, certifique-se de que python --version é uma versão compatível. Consulte a documentação do seu gerenciador de ambiente virtual Python (venv, conda, e assim por diante) para obter instruções.

Iniciar uma sessão interativa do Python

Este tutorial usa o SDK do Python para Azure Machine Learning para criar e controlar um pipeline do Azure Machine Learning. O tutorial pressupõe que você executará os trechos de código interativamente em um ambiente Python REPL ou em um bloco de anotações Jupyter.

  • Este tutorial é baseado no image-classification.ipynb bloco de anotações encontrado no python-sdk/tutorial/using-pipelines diretório do repositório de Exemplos do Azure Machine Learning . O código-fonte das etapas em si está no keras-mnist-fashion subdiretório.

Tipos de importação

Importe todos os tipos do Azure Machine Learning necessários para este tutorial:

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)

A versão do SDK do Azure Machine Learning deve ser 1.37 ou superior. Se não estiver, atualize com pip install --upgrade azureml-core.

Configurar a área de trabalho

Crie um objeto de espaço de trabalho a partir do espaço de trabalho existente do Azure Machine Learning.

workspace = Workspace.from_config()

Importante

Este trecho de código espera que a configuração do espaço de trabalho seja salva no diretório atual ou em seu pai. Para obter mais informações sobre como criar um espaço de trabalho, consulte Criar recursos do espaço de trabalho. Para obter mais informações sobre como salvar a configuração no arquivo, consulte Criar um arquivo de configuração do espaço de trabalho.

Crie a infraestrutura para seu pipeline

Crie um Experiment objeto para armazenar os resultados de suas execuções de pipeline:

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

Crie um ComputeTarget que represente o recurso de máquina no qual seu pipeline será executado. A rede neural simples usada neste tutorial treina em apenas alguns minutos, mesmo em uma máquina baseada em CPU. Se desejar usar uma GPU para treinamento, defina use_gpu como True. O provisionamento de um destino de computação geralmente leva cerca de cinco minutos.

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

Nota

A disponibilidade da GPU depende da quota da sua subscrição do Azure e da capacidade do Azure. Veja Gerir e aumentar as quotas dos recursos com o Azure Machine Learning.

Criar um conjunto de dados para os dados armazenados no Azure

Fashion-MNIST é um conjunto de dados de imagens de moda dividido em 10 classes. Cada imagem é uma imagem em tons de cinza 28x28 e há 60.000 imagens de treinamento e 10.000 imagens de teste. Como um problema de classificação de imagem, o Fashion-MNIST é mais difícil do que o clássico banco de dados de dígitos manuscritos MNIST. É distribuído na mesma forma binária compactada que o banco de dados de dígitos manuscrito original.

Para criar um Dataset que faça referência aos dados baseados na Web, execute:

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

Este código é concluído rapidamente. Os dados subjacentes permanecem no recurso de armazenamento do Azure especificado na data_urls matriz.

Criar a etapa do pipeline de preparação de dados

A primeira etapa desse pipeline converterá os arquivos de dados compactados em um conjunto de fashion_ds dados em seu próprio espaço de trabalho, consistindo em arquivos CSV prontos para uso em treinamento. Uma vez cadastrados no espaço de trabalho, seus colaboradores podem acessar esses dados para suas próprias análises, treinamentos e assim por diante

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

O código acima especifica um conjunto de dados baseado na saída de uma etapa de pipeline. Os arquivos processados subjacentes serão colocados no armazenamento de blob padrão do armazenamento de dados do espaço de trabalho no caminho especificado em destination. O conjunto de dados será registrado no espaço de trabalho com o nome prepared_fashion_ds.

Criar a origem da etapa de pipeline

O código que você executou até agora criou e controlou recursos do Azure. Agora é hora de escrever o código que faz o primeiro passo no domínio.

Se você estiver acompanhando o exemplo no repositório Exemplos do Azure Machine Learning, o arquivo de origem já está disponível como keras-mnist-fashion/prepare.py.

Se você estiver trabalhando do zero, crie um subdiretório chamado keras-mnist-fashion/. Crie um novo arquivo, adicione o seguinte código a ele e nomeie o arquivo prepare.py.

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

O código em prepare.py usa dois argumentos de linha de comando: o primeiro é atribuído a e mounted_input_path o segundo a mounted_output_path. Se esse subdiretório não existir, a chamada para os.makedirs criá-lo. Em seguida, o programa converte os dados de treinamento e teste e produz os arquivos separados por vírgulas para o mounted_output_path.

Especificar a etapa do pipeline

De volta ao ambiente Python que você está usando para especificar o pipeline, execute este código para criar um PythonScriptStep para seu código de preparação:

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

A chamada para PythonScriptStep especifica que, quando a etapa do pipeline é executada:

  • Todos os arquivos no script_folder diretório são carregados para o compute_target
  • Entre os arquivos de origem carregados, o arquivo prepare.py será executado
  • Os fashion_ds conjuntos de dados e prepared_fashion_ds serão montados no compute_target e aparecerão como diretórios
  • O caminho para os fashion_ds arquivos será o primeiro argumento para prepare.py. No prepare.py, este argumento é atribuído a mounted_input_path
  • O caminho para o será o prepared_fashion_ds segundo argumento para prepare.py. No prepare.py, este argumento é atribuído a mounted_output_path
  • Porque allow_reuse é True, ele não será executado novamente até que seus arquivos de origem ou entradas mudem
  • Este PythonScriptStep será nomeado prepare step

A modularidade e a reutilização são os principais benefícios dos pipelines. O Azure Machine Learning pode determinar automaticamente o código-fonte ou as alterações do Conjunto de Dados. A saída de uma etapa que não é afetada será reutilizada sem executar as etapas novamente se allow_reuse for True. Se uma etapa depender de uma fonte de dados externa ao Aprendizado de Máquina do Azure que pode ser alterada (por exemplo, uma URL que contém dados de vendas), defina allow_reuse como False e a etapa de pipeline será executada sempre que o pipeline for executado.

Criar a etapa de treinamento

Uma vez que os dados tenham sido convertidos do formato compactado para arquivos CSV, eles podem ser usados para treinar uma rede neural convolucional.

Criar a origem da etapa de treinamento

Com pipelines maiores, é uma boa prática colocar o código-fonte de cada etapa em um diretório separado (src/prepare/, src/train/, e assim por diante), mas para este tutorial, basta usar ou criar o arquivo train.py no mesmo keras-mnist-fashion/ diretório de origem.

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

A maioria desse código deve ser familiar para desenvolvedores de ML:

  • Os dados são particionados em conjuntos de treinamento e validação para treinamento, e um subconjunto de teste separado para pontuação final
  • A forma de entrada é 28x28x1 (apenas 1 porque a entrada é em tons de cinza), haverá 256 entradas em um lote e há 10 classes
  • O número de épocas de formação será de 10
  • O modelo tem três camadas convolucionais, com pool máximo e dropout, seguido por uma camada densa e cabeça softmax
  • O modelo é ajustado para 10 épocas e, em seguida, avaliado
  • A arquitetura do modelo é gravada e outputs/model/model.json os pesos para outputs/model/model.h5

Parte do código, no entanto, é específico do Azure Machine Learning. run = Run.get_context() Recupera um Run objeto, que contém o contexto de serviço atual. A train.py fonte usa esse run objeto para recuperar o conjunto de dados de entrada por meio de seu nome (uma alternativa ao código em prepare.py que recuperou o conjunto de dados por meio da argv matriz de argumentos de script).

O run objeto também é usado para registrar o progresso do treinamento no final de cada época e, no final do treinamento, para registrar o gráfico de perda e precisão ao longo do tempo.

Criar a etapa do pipeline de treinamento

A etapa de treinamento tem uma configuração um pouco mais complexa do que a etapa de preparação. A etapa de preparação usou apenas bibliotecas Python padrão. Mais comumente, você precisará modificar o ambiente de tempo de execução no qual o código-fonte é executado.

Crie um arquivo conda_dependencies.yml com o seguinte conteúdo:

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

A Environment classe representa o ambiente de tempo de execução no qual uma tarefa de aprendizado de máquina é executada. Associe a especificação acima ao código de treinamento com:

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

A criação da etapa de treinamento em si usa um código semelhante ao código usado para criar a etapa de preparação:

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

Criar e executar o pipeline

Agora que você especificou entradas e saídas de dados e criou as etapas do pipeline, pode compô-las em um pipeline e executá-lo:

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

O Pipeline objeto que você cria é executado em seu workspace e é composto pelas etapas de preparação e treinamento que você especificou.

Nota

Esse pipeline tem um gráfico de dependência simples: a etapa de treinamento depende da etapa de preparação e a etapa de preparação depende do fashion_ds conjunto de dados. Os pipelines de produção geralmente terão dependências muito mais complexas. As etapas podem depender de várias etapas upstream, uma alteração no código-fonte em uma etapa inicial pode ter consequências de longo alcance e assim por diante. O Azure Machine Learning rastreia essas preocupações para você. Você só precisa passar na matriz de e o Azure Machine Learning cuida do cálculo do gráfico de steps execução.

A chamada para submit o Experiment é concluída rapidamente e produz resultados semelhantes a:

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

Você pode monitorar a execução do pipeline abrindo o link ou pode bloquear até que ele seja concluído executando:

run.wait_for_completion(show_output=True)

Importante

A primeira execução do pipeline leva cerca de 15 minutos. Todas as dependências devem ser baixadas, uma imagem do Docker é criada e o ambiente Python é provisionado e criado. Executar o pipeline novamente leva significativamente menos tempo porque esses recursos são reutilizados em vez de criados. No entanto, o tempo total de execução do pipeline depende da carga de trabalho dos scripts e dos processos em execução em cada etapa do pipeline.

Quando o pipeline for concluído, você poderá recuperar as métricas registradas na etapa de treinamento:

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

Se estiver satisfeito com as métricas, pode registar o modelo na sua área de trabalho:

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

Clean up resources (Limpar recursos)

Não conclua esta seção se você planeja executar outros tutoriais do Azure Machine Learning.

Pare a instância de computação

Se você usou uma instância de computação, pare a VM quando não estiver usando-a para reduzir custos.

  1. No espaço de trabalho, selecione Computação.

  2. Na lista, selecione o nome da instância de computação.

  3. Selecione Parar.

  4. Quando estiver pronto para usar o servidor novamente, selecione Iniciar.

Excluir tudo

Se você não planeja usar os recursos que criou, exclua-os para não incorrer em nenhum custo:

  1. No portal do Azure, no menu à esquerda, selecione Grupos de recursos.
  2. Na lista de grupos de recursos, selecione o grupo de recursos que você criou.
  3. Selecione Eliminar grupo de recursos.
  4. Insira o nome do grupo de recursos. Em seguida, selecione Excluir.

Você também pode manter o grupo de recursos, mas excluir um único espaço de trabalho. Exiba as propriedades do espaço de trabalho e selecione Excluir.

Próximos passos

Neste tutorial, você usou os seguintes tipos:

  • O Workspace representa seu espaço de trabalho do Azure Machine Learning. Continha:
    • O Experiment que contém os resultados das execuções de treinamento do seu pipeline
    • O Dataset que preguiçosamente carregou os dados mantidos no armazenamento de dados Fashion-MNIST
    • O ComputeTarget que representa a(s) máquina(s) na qual as etapas do pipeline são executadas
    • O Environment que é o ambiente de tempo de execução no qual as etapas do pipeline são executadas
    • O Pipeline que compõe os PythonScriptStep passos em um todo
    • O Model que você se inscreveu depois de estar satisfeito com o processo de treinamento

O Workspace objeto contém referências a outros recursos (blocos de anotações, pontos de extremidade e assim por diante) que não foram usados neste tutorial. Para saber mais, consulte O que é um espaço de trabalho do Azure Machine Learning?.

O OutputFileDatasetConfig promove a saída de uma execução para um conjunto de dados baseado em arquivo. Para obter mais informações sobre conjuntos de dados e como trabalhar com dados, consulte Como acessar dados.

Para obter mais informações sobre destinos e ambientes de computação, consulte O que são destinos de computação no Azure Machine Learning? e O que são ambientes do Azure Machine Learning?

O ScriptRunConfig associa a ComputeTarget e Environment com arquivos de código-fonte Python. A PythonScriptStep pega isso ScriptRunConfig e define suas entradas e saídas, que neste pipeline era o conjunto de dados de arquivo construído pelo OutputFileDatasetConfig.

Para obter mais exemplos de como criar pipelines usando o SDK de aprendizado de máquina, consulte o repositório de exemplo.