Treine os modelos PyTorch em escala com o Azure Machine Learning

APLICA-SE A: SDK do Python azure-ai-ml v2 (atual)

Neste artigo, você aprenderá a treinar, ajustar os hiperparâmetros e implantar um modelo do PyTorch usando o SDK v2 do Python para o Azure Machine Learning.

Você usará scripts de exemplo para classificar imagens de frango e peru para criar uma rede neural de aprendizado profundo (DNN) com base no Tutorial de aprendizado por transferência do PyTorch. O aprendizado de transferência é uma técnica que aplica o conhecimento obtido na resolução de um problema para um problema diferente, mas relacionado. A transferência de aprendizado reduz o processo de treinamento, exigindo menos dados, tempo e recursos computacionais do que o treinamento começando do zero. Para saber mais sobre aprendizado por transferência, consulte Aprendizado profundo vs aprendizado de máquina.

Se você está treinando em um modelo PyTorch de aprendizado profundo do zero ou está usando um modelo existente na nuvem, você pode usar o Azure Machine Learning para escalar horizontalmente execuções de treinamento de open-source usando recursos de computação em nuvem elásticos. Você pode criar, implantar, versionar e monitorar modelos de nível de produção com o Azure Machine Learning.

Pré-requisitos

  • Uma assinatura do Azure. Se você ainda não tem, crie uma conta gratuita.
  • Execute o código nesse artigo usando uma instância de computação do Azure Machine Learning ou em seu próprio Jupyter Notebook.
    • Instância de computação do Azure Machine Learning – não há necessidade de fazer download nem instalação:
      • Conclua o Início Rápido: introdução ao Azure Machine Learning para criar um servidor de notebook dedicado pré-carregado com o SDK e o repositório de exemplo.
      • Na guia Amostras, na seção Notebooks do seu workspace, encontre um notebook amplo e completo navegando para este diretório: SDK v2/sdk/python/jobs/single-step/pytorch/train-hyperparameter-tune-deploy-with-pytorch
    • Seu servidor do Jupyter Notebook:

Você também pode encontrar uma versão completa do notebook Jupyter deste guia na página de exemplos do GitHub.

Antes de executar o código neste artigo para criar um cluster de GPU, você precisará solicitar um aumento de cota para seu workspace.

Configurar o trabalho

Esta seção configura o trabalho para treinamento carregando os pacotes necessários do Python, conectando-se a um workspace, criando um recurso de computação para executar um trabalho de comando e criando um ambiente para executar o trabalho.

Conectar-se ao workspace

Primeiro, será necessário se conectar ao Workspace do Azure Machine Learning. O workspace é o recurso de nível superior para o serviço. Ele fornece um local centralizado para trabalhar com todos os artefatos que você criar ao usar o Azure Machine Learning.

Estamos usando DefaultAzureCredential para obter acesso ao workspace. Esta credencial deve poder lidar com a maioria dos cenários de autenticação do SDK do Azure.

Se DefaultAzureCredential não funcionar para você, consulte o pacote azure.identity ou Configurar autenticação para obter mais credenciais disponíveis.

# Handle to the workspace
from azure.ai.ml import MLClient

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

Se você preferir usar um navegador para entrar e se autenticar, remova a marca de comentário o código a seguir e use-o.

# Handle to the workspace
# from azure.ai.ml import MLClient

# Authentication package
# from azure.identity import InteractiveBrowserCredential
# credential = InteractiveBrowserCredential()

Em seguida, obtenha um identificador para o workspace. Para isso, forneça sua ID de assinatura, o nome do grupo de recursos e o nome do workspace. Para localizar esses parâmetros:

  1. Procure o nome do workspace no canto superior direito da barra de ferramentas do Estúdio do Azure Machine Learning.
  2. Selecione o nome do workspace para exibir o grupo de recursos e a ID da assinatura.
  3. Copie os valores do grupo de recursos e da ID da assinatura no código.
# Get a handle to the workspace
ml_client = MLClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)

O resultado da execução desse script é um identificador do workspace que você pode usar para gerenciar outros recursos e trabalhos.

Observação

A criação do MLClient não conecta o cliente ao workspace. A inicialização do cliente é lenta e aguarda pela primeira vez que precisar fazer uma chamada. Neste artigo, isso ocorre durante a criação da computação.

Criar um recurso de computação para executar o trabalho

O Azure Machine Learning precisa de um recurso de computação para executar um trabalho. Esse recurso pode ser computadores com um ou vários nós com o SO Linux ou Windows ou uma malha de computação específica como o Spark.

No script de exemplo a seguir, provisionamos um cluster de cálculo do Linux. Você pode conferir a página de Preços do Azure Machine Learning para obter a lista completa de tamanhos e preços de VM. Como precisamos ter um cluster de GPU para este exemplo, vamos escolher um modelo STANDARD_NC6 e criar uma computação do Azure Machine Learning.

from azure.ai.ml.entities import AmlCompute

gpu_compute_target = "gpu-cluster"

try:
    # let's see if the compute target already exists
    gpu_cluster = ml_client.compute.get(gpu_compute_target)
    print(
        f"You already have a cluster named {gpu_compute_target}, we'll reuse it as is."
    )

except Exception:
    print("Creating a new gpu compute target...")

    # Let's create the Azure ML compute object with the intended parameters
    gpu_cluster = AmlCompute(
        # Name assigned to the compute cluster
        name="gpu-cluster",
        # Azure ML Compute is the on-demand VM service
        type="amlcompute",
        # VM Family
        size="STANDARD_NC6s_v3",
        # Minimum running nodes when there is no job running
        min_instances=0,
        # Nodes in cluster
        max_instances=4,
        # How many seconds will the node running after the job termination
        idle_time_before_scale_down=180,
        # Dedicated or LowPriority. The latter is cheaper but there is a chance of job termination
        tier="Dedicated",
    )

    # Now, we pass the object to MLClient's create_or_update method
    gpu_cluster = ml_client.begin_create_or_update(gpu_cluster).result()

print(
    f"AMLCompute with name {gpu_cluster.name} is created, the compute size is {gpu_cluster.size}"
)

Criar um ambiente de trabalho

Você precisa ter um ambiente para executar um trabalho do Azure Machine Learning. Um ambiente do Azure Machine Learning encapsula as dependências (como bibliotecas e runtime de software) necessárias para executar o script de treinamento de machine learning no recurso de computação. Esse ambiente é semelhante a um ambiente do Python no computador local.

O Azure Machine Learning permite que você use um ambiente coletado (ou pronto) ou crie um ambiente personalizado usando uma imagem do Docker ou uma configuração do Conda. Neste artigo, você reutiliza o ambiente AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu coletado do Azure Machine Learning. Use a versão mais recente deste ambiente usando a diretiva @latest.

curated_env_name = "AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu@latest"

Configurar e enviar trabalhos de treinamento

Nesta seção, começamos introduzindo os dados para treinamento. Em seguida, abordamos como executar um trabalho de treinamento usando um script de treinamento fornecido. Você aprenderá a criar o trabalho de treinamento configurando o comando para executar o script de treinamento. Em seguida, você enviará o trabalho de treinamento para execução no Azure Machine Learning.

Obter os dados de treinamento

Você pode usar o conjunto de dados neste arquivo compactado. Este conjunto de dados consiste em cerca de 120 imagens de treinamento cada para duas classes (perus e galinhas), com 100 imagens de validação para cada classe. As imagens são um subconjunto do Conjunto de dados do Open images V5. O script de treinamento pytorch_train.py baixa e extrai o conjunto de dados.

Preparar o script de treinamento

Na seção pré-requisitos, fornecemos o script de treinamento pytorch_train.py. Na prática, você deve conseguir usar qualquer script de treinamento personalizado no estado em que se encontra e executá-lo com o Azure Machine Learning sem precisar modificar o código.

O script de treinamento fornecido baixa os dados, treina um modelo e registra o modelo.

Compilar o trabalho de treinamento

Agora que você tem todos os ativos necessários para executar o trabalho, é hora de compilá-lo usando o SDK v2 do Python para o Azure Machine Learning. Para este exemplo, criamos um command.

Um command do Azure Machine Learning é um recurso que especifica todos os detalhes necessários para executar o código de treinamento na nuvem. Esses detalhes incluem as entradas e saídas, o tipo de hardware a ser usado, o software a ser instalado e como executar o código. command contém informações para executar um único comando.

Configurar o comando

O uso geral command será usado para executar o script de treinamento e executar as tarefas desejadas. Crie um objeto command para especificar os detalhes de configuração do trabalho de treinamento.

from azure.ai.ml import command
from azure.ai.ml import Input

job = command(
    inputs=dict(
        num_epochs=30, learning_rate=0.001, momentum=0.9, output_dir="./outputs"
    ),
    compute=gpu_compute_target,
    environment=curated_env_name,
    code="./src/",  # location of source code
    command="python pytorch_train.py --num_epochs ${{inputs.num_epochs}} --output_dir ${{inputs.output_dir}}",
    experiment_name="pytorch-birds",
    display_name="pytorch-birds-image",
)
  • As entradas desse comando incluem o número de épocas, a taxa de aprendizado, o momento e o diretório de saída.
  • Nos valores dos parâmetros:
    1. Forneça o cluster de computação gpu_compute_target = "gpu-cluster" que você criou para executar este comando.
    2. Forneça o ambiente coletado AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu que você inicializou anteriormente.
    3. Se você não estiver usando o notebook concluído na pasta Amostras, especifique o local do arquivo pytorch_train.py.
    4. Configure a ação da linha de comando em si – nesse caso, o comando é python pytorch_train.py. É possível acessar as entradas e saídas no comando por meio da notação ${{ ... }}.
    5. Configure metadados como o nome de exibição e o nome do experimento, nos quais um experimento é um contêiner para todas as iterações feitas em um determinado projeto. Todos os trabalhos enviados com o mesmo nome de experimento serão listados um ao lado do outro no Estúdio do Azure Machine Learning.

Enviar o trabalho

Agora é hora de enviar o trabalho a ser executado no Azure Machine Learning. Desta vez, você usa create_or_update em ml_client.jobs.

ml_client.jobs.create_or_update(job)

Depois de concluído, o trabalho registra um modelo no seu workspace (como resultado do treinamento) e gera um link para exibir o trabalho no Estúdio do Azure Machine Learning.

Aviso

O Azure Machine Learning executa scripts de treinamento copiando o diretório de origem inteiro. Se você tiver dados confidenciais que não quer carregar, use um arquivo .ignore ou não o inclua no diretório de origem.

O que acontece durante o trabalho

Conforme o trabalho é executado, ele passa pelos seguintes estágios:

  • Preparação: uma imagem Docker é criada de acordo com o ambiente definido. A imagem é carregada no registro de contêiner do workspace e armazenada em cache para execuções posteriores. Os logs também são transmitidos para o histórico do trabalho e podem ser exibidos para monitorar o progresso. Mas se um ambiente coletado for especificado, a imagem armazenada em cache desse ambiente coletado é usada.

  • Dimensionamento: o cluster tenta escalar verticalmente se exigir mais nós para a execução, além do que está disponível no momento.

  • Execução: todos os scripts na pasta de scripts src são carregados para o destino de computação, os armazenamentos de dados são montados ou copiados e o script é executado. As saídas do stdout e da pasta ./logs são transmitidas para o histórico do trabalho e podem ser usadas para monitorar o trabalho.

Ajustar hiperparâmetros do modelo

Você treinou o modelo com um conjunto de parâmetros, agora veremos se é possível melhorar ainda mais a precisão do modelo. Você pode ajustar e otimizar os hiperparâmetros do modelo usando as funcionalidades sweep do Azure Machine Learning.

Para ajustar os hiperparâmetros do modelo, defina o espaço de parâmetro a ser pesquisado durante o treinamento. É possível fazer isso substituindo alguns dos parâmetros passados para o trabalho de treinamento por entradas especiais do pacote azure.ml.sweep.

Como o script de treinamento usa um cronograma de taxa de aprendizagem para decair a taxa de aprendizagem a cada várias épocas, você pode ajustar a taxa de aprendizagem inicial e os parâmetros de impulso.

from azure.ai.ml.sweep import Uniform

# we will reuse the command_job created before. we call it as a function so that we can apply inputs
job_for_sweep = job(
    learning_rate=Uniform(min_value=0.0005, max_value=0.005),
    momentum=Uniform(min_value=0.9, max_value=0.99),
)

Em seguida, você pode configurar a varredura no trabalho de comando, usando alguns parâmetros específicos de varredura, como a métrica primária a ser observada e o algoritmo de amostragem a ser usado.

No código a seguir, usamos a amostragem aleatória para tentar diferentes conjuntos de configuração de hiperparâmetros na tentativa de maximizar nossa métrica primária, best_val_acc.

Também definimos uma política de encerramento antecipado, a BanditPolicy, para encerrar antecipadamente execuções com baixo desempenho. O BanditPolicy encerra qualquer execução que não se enquadre no fator de folga de nossa métrica de avaliação principal. Você aplica esta política a cada época (já que relatamos nossa métrica best_val_acc a cada época e evaluation_interval=1). Observe que adiamos a primeira avaliação da política até depois das 10 primeiras épocas (delay_evaluation=10).

from azure.ai.ml.sweep import BanditPolicy

sweep_job = job_for_sweep.sweep(
    compute="gpu-cluster",
    sampling_algorithm="random",
    primary_metric="best_val_acc",
    goal="Maximize",
    max_total_trials=8,
    max_concurrent_trials=4,
    early_termination_policy=BanditPolicy(
        slack_factor=0.15, evaluation_interval=1, delay_evaluation=10
    ),
)

Agora, você pode enviar este trabalho como antes. Desta vez, você está executando um trabalho de varredura que limpa seu trabalho de treinamento.

returned_sweep_job = ml_client.create_or_update(sweep_job)

# stream the output and wait until the job is finished
ml_client.jobs.stream(returned_sweep_job.name)

# refresh the latest status of the job after streaming
returned_sweep_job = ml_client.jobs.get(name=returned_sweep_job.name)

Você pode monitorar o trabalho usando o link de interface do usuário do estúdio que é apresentado durante a execução do trabalho.

Localizar o melhor modelo

Depois que todas as execuções forem concluídas, você poderá encontrar a execução que produziu o modelo com a maior precisão.

from azure.ai.ml.entities import Model

if returned_sweep_job.status == "Completed":

    # First let us get the run which gave us the best result
    best_run = returned_sweep_job.properties["best_child_run_id"]

    # lets get the model from this run
    model = Model(
        # the script stores the model as "outputs"
        path="azureml://jobs/{}/outputs/artifacts/paths/outputs/".format(best_run),
        name="run-model-example",
        description="Model created from run.",
        type="custom_model",
    )

else:
    print(
        "Sweep job status: {}. Please wait until it completes".format(
            returned_sweep_job.status
        )
    )

Implantar o modelo como um ponto de extremidade online

Agora você pode implantar seu modelo como um ponto de extremidade online, ou seja, como um serviço web na nuvem do Azure.

Para implantar um serviço de aprendizado de máquina, geralmente você precisa:

  • Os ativos do modelo que você deseja implantar. Esses ativos incluem o arquivo e os metadados do modelo que você já registrou em seu trabalho de treinamento.
  • Alguns códigos a serem executados como um serviço. O código executa o modelo em uma determinada solicitação de entrada (um script de entrada). Este script de entrada recebe os dados enviados para um serviço Web implantado e os transmite ao modelo. Depois que o modelo processa os dados, o script retorna a resposta do modelo ao cliente. O script é específico para seu modelo e deve compreender os dados que o modelo espera e retorna. Quando você usa um modelo do MLFlow, o Azure Machine Learning cria esse script automaticamente para você.

Para obter mais informações sobre a implantação, confira Implante e pontue um modelo de machine learning com um ponto de extremidade online gerenciado usando o SDK do Python v2.

Criar um ponto de extremidade online

Como uma primeira etapa para implantar seu modelo, você precisa criar um ponto de extremidade online. O nome do ponto de extremidade deve ser exclusivo em toda a região do Azure. Para este artigo, você cria um nome exclusivo usando um UUID (identificador exclusivo universal).

import uuid

# Creating a unique name for the endpoint
online_endpoint_name = "aci-birds-endpoint-" + str(uuid.uuid4())[:8]
from azure.ai.ml.entities import ManagedOnlineEndpoint

# create an online endpoint
endpoint = ManagedOnlineEndpoint(
    name=online_endpoint_name,
    description="Classify turkey/chickens using transfer learning with PyTorch",
    auth_mode="key",
    tags={"data": "birds", "method": "transfer learning", "framework": "pytorch"},
)

endpoint = ml_client.begin_create_or_update(endpoint).result()

print(f"Endpoint {endpoint.name} provisioning state: {endpoint.provisioning_state}")

Após criar o ponto de extremidade, você pode recuperá-lo da seguinte maneira:

endpoint = ml_client.online_endpoints.get(name=online_endpoint_name)

print(
    f'Endpint "{endpoint.name}" with provisioning state "{endpoint.provisioning_state}" is retrieved'
)

Implantar o modelo ao ponto de extremidade

Agora você pode implantar o modelo com o script de entrada. Um ponto de extremidade pode ter várias implantações. Usando as regras, o ponto de extremidade pode direcionar o tráfego para essas implantações.

No código a seguir, você criará uma única implantação que manipula 100% do tráfego de entrada. Especificamos um nome de cor arbitrário aci-blue para a implantação. Você também pode usar qualquer outro nome, como aci-green ou aci-red, para a implantação.

O código para implantar o modelo no ponto de extremidade:

  • Implanta a melhor versão do modelo que você registrou anteriormente.
  • Pontua o modelo usando o arquivo score.py.
  • Usa o ambiente com curadoria (que você especificou anteriormente) para realizar a inferência.
from azure.ai.ml.entities import (
    ManagedOnlineDeployment,
    Model,
    Environment,
    CodeConfiguration,
)

online_deployment_name = "aci-blue"

# create an online deployment.
blue_deployment = ManagedOnlineDeployment(
    name=online_deployment_name,
    endpoint_name=online_endpoint_name,
    model=model,
    environment=curated_env_name,
    code_configuration=CodeConfiguration(code="./score/", scoring_script="score.py"),
    instance_type="Standard_NC6s_v3",
    instance_count=1,
)

blue_deployment = ml_client.begin_create_or_update(blue_deployment).result()

Observação

Essa implantação demora um pouco para ser concluída.

Testar o modelo implantado

Agora que você implantou o modelo no ponto de extremidade, é possível prever a saída do modelo implantado, usando o método invoke no ponto de extremidade.

Para testar o ponto de extremidade, vamos usar uma imagem de exemplo para previsão. Primeiro, vamos exibir a imagem.

# install pillow if PIL cannot imported
%pip install pillow
import json
from PIL import Image
import matplotlib.pyplot as plt

%matplotlib inline
plt.imshow(Image.open("test_img.jpg"))

Crie uma função para formatar e redimensionar a imagem.

# install torch and torchvision if needed
%pip install torch
%pip install torchvision

import torch
from torchvision import transforms


def preprocess(image_file):
    """Preprocess the input image."""
    data_transforms = transforms.Compose(
        [
            transforms.Resize(256),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
        ]
    )

    image = Image.open(image_file)
    image = data_transforms(image).float()
    image = torch.tensor(image)
    image = image.unsqueeze(0)
    return image.numpy()

Formate a imagem e converta-a em um arquivo JSON.

image_data = preprocess("test_img.jpg")
input_data = json.dumps({"data": image_data.tolist()})
with open("request.json", "w") as outfile:
    outfile.write(input_data)

Em seguida, você pode invocar o ponto de extremidade com este JSON e imprimir o resultado.

# test the blue deployment
result = ml_client.online_endpoints.invoke(
    endpoint_name=online_endpoint_name,
    request_file="request.json",
    deployment_name=online_deployment_name,
)

print(result)

Limpar os recursos

Se você não precisar mais do ponto de extremidade, exclua-o para parar de usar o recurso. Verifique se nenhuma outra implantação está usando o ponto de extremidade antes de excluí-lo.

ml_client.online_endpoints.begin_delete(name=online_endpoint_name)

Observação

Essa limpeza demora um pouco para ser concluída.

Próximas etapas

Neste artigo, você treinou e registrou uma rede neural de aprendizado profundo usando PyTorch no Azure Machine Learning. Você também implantou o modelo em um ponto de extremidade online. Consulte estes outros artigos para saber mais sobre Azure Machine Learning.