Tutorial: treinar um modelo de detecção de objetos (versão prévia) com o AutoML e o Python (v1)

APLICA-SE ASDK do Python azureml v1

Importante

Os recursos apresentados neste artigo estão em versão prévia. Eles devem ser considerados versão prévia de recursos experimentais que podem mudar a qualquer momento.

Neste tutorial, você aprenderá a treinar um modelo de detecção de objetos usando o ML automatizado do Azure Machine Learning com o SDK do Python do Azure Machine Learning. Este modelo de detecção de objetos identifica se a imagem contém objetos, como uma lata, uma caixa de papelão, uma garrafa de leite ou uma garrafa de água.

O ML automatizado aceita dados de treinamento e configurações e itera automaticamente por meio de combinações de diferentes métodos de normalização/padronização de características, modelos e configurações de hiperparâmetro, para chegar ao melhor modelo.

Você escreverá código usando o SDK do Python neste tutorial e aprenderá as seguintes tarefas:

  • Baixar e transformar dados
  • Treinar um modelo de detecção de objetos com machine learning automatizado
  • Especificar valores de hiperparâmetro para seu modelo
  • Executar uma varredura de hiperparâmetro
  • Implantar o seu modelo
  • Visualizar as detecções

Pré-requisitos

  • Caso não tenha uma assinatura do Azure, crie uma conta gratuita antes de começar. Experimente hoje mesmo a versão gratuita ou paga do Azure Machine Learning.

  • O Python 3.7 ou 3.8 é compatível com esse recurso

  • Conclua o Guia de início rápido: introdução ao Azure Machine Learning se você ainda não tiver um Workspace do Azure Machine Learning.

  • Baixe e descompacte o arquivo de dados *odFridgeObjects.zip. O conjunto de dados é anotado no formato Pascal VOC, em que cada imagem corresponde a um arquivo xml. Cada arquivo xml contém informações sobre onde o arquivo de imagem correspondente está localizado e também contém informações sobre as caixas delimitadoras e os rótulos de objeto. Para usar esses dados, primeiro você precisa convertê-los no formato JSONL necessário, conforme visto na seção Converter os dados baixados em JSONL do notebook.

Este tutorial também está disponível no repositório azureml-examples no GitHub, caso você deseje executá-lo em seu ambiente local. Para obter os pacotes necessários,

Configuração do destino de computação

Primeiro, você precisa configurar um destino de computação para usar para o treinamento do modelo de ML automatizado. Modelos de ML automatizado para tarefas de imagem exigem SKUs de GPU.

Este tutorial usa a série NCsv3 (com GPUs V100), pois esse tipo de destino de computação aproveita várias GPUs para acelerar o treinamento. Além disso, você pode configurar vários nós para aproveitar o paralelismo ao ajustar hiperparâmetros para o seu modelo.

O código a seguir cria uma computação de GPU de tamanho _NC24s_v3 Standard com quatro nós anexados ao workspace, ws.

Aviso

Verifique se sua assinatura tem cota suficiente para o destino de computação que você deseja usar.

from azureml.core.compute import AmlCompute, ComputeTarget

cluster_name = "gpu-nc24sv3"

try:
    compute_target = ComputeTarget(workspace=ws, name=cluster_name)
    print('Found existing compute target.')
except KeyError:
    print('Creating a new compute target...')
    compute_config = AmlCompute.provisioning_configuration(vm_size='Standard_NC24s_v3',
                                                           idle_seconds_before_scaledown=1800,
                                                           min_nodes=0,
                                                           max_nodes=4)

    compute_target = ComputeTarget.create(ws, cluster_name, compute_config)

#If no min_node_count is provided, the scale settings are used for the cluster.
compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)

Instalação do experimento

Em seguida, crie um Experiment em seu workspace para acompanhar as execuções de treinamento do modelo.


from azureml.core import Experiment

experiment_name = 'automl-image-object-detection'
experiment = Experiment(ws, name=experiment_name)

Visualizar dados de entrada

Depois que os dados de imagem de entrada estiverem preparados no formato JSONL (Linhas JSON), você poderá visualizar as caixas delimitadoras de verdade de uma imagem. Para isso, confirme se você tem a matplotlib instalada.

%pip install --upgrade matplotlib

%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.patches as patches
from PIL import Image as pil_image
import numpy as np
import json
import os

def plot_ground_truth_boxes(image_file, ground_truth_boxes):
    # Display the image
    plt.figure()
    img_np = mpimg.imread(image_file)
    img = pil_image.fromarray(img_np.astype("uint8"), "RGB")
    img_w, img_h = img.size

    fig,ax = plt.subplots(figsize=(12, 16))
    ax.imshow(img_np)
    ax.axis("off")

    label_to_color_mapping = {}

    for gt in ground_truth_boxes:
        label = gt["label"]

        xmin, ymin, xmax, ymax =  gt["topX"], gt["topY"], gt["bottomX"], gt["bottomY"]
        topleft_x, topleft_y = img_w * xmin, img_h * ymin
        width, height = img_w * (xmax - xmin), img_h * (ymax - ymin)

        if label in label_to_color_mapping:
            color = label_to_color_mapping[label]
        else:
            # Generate a random color. If you want to use a specific color, you can use something like "red".
            color = np.random.rand(3)
            label_to_color_mapping[label] = color

        # Display bounding box
        rect = patches.Rectangle((topleft_x, topleft_y), width, height,
                                 linewidth=2, edgecolor=color, facecolor="none")
        ax.add_patch(rect)

        # Display label
        ax.text(topleft_x, topleft_y - 10, label, color=color, fontsize=20)

    plt.show()

def plot_ground_truth_boxes_jsonl(image_file, jsonl_file):
    image_base_name = os.path.basename(image_file)
    ground_truth_data_found = False
    with open(jsonl_file) as fp:
        for line in fp.readlines():
            line_json = json.loads(line)
            filename = line_json["image_url"]
            if image_base_name in filename:
                ground_truth_data_found = True
                plot_ground_truth_boxes(image_file, line_json["label"])
                break
    if not ground_truth_data_found:
        print("Unable to find ground truth information for image: {}".format(image_file))

def plot_ground_truth_boxes_dataset(image_file, dataset_pd):
    image_base_name = os.path.basename(image_file)
    image_pd = dataset_pd[dataset_pd['portable_path'].str.contains(image_base_name)]
    if not image_pd.empty:
        ground_truth_boxes = image_pd.iloc[0]["label"]
        plot_ground_truth_boxes(image_file, ground_truth_boxes)
    else:
        print("Unable to find ground truth information for image: {}".format(image_file))

Usando as funções auxiliares acima, para qualquer imagem específica, execute o código a seguir para exibir as caixas delimitadoras.

image_file = "./odFridgeObjects/images/31.jpg"
jsonl_file = "./odFridgeObjects/train_annotations.jsonl"

plot_ground_truth_boxes_jsonl(image_file, jsonl_file)

Carregar dados e criar conjunto de dados

Para usar os dados para treinamento, carregue-os no seu workspace por meio de um armazenamento de dados. O armazenamento de dados oferece um mecanismo para carregar ou baixar dados e interagir com eles em seus destinos de computação remotos.

ds = ws.get_default_datastore()
ds.upload(src_dir='./odFridgeObjects', target_path='odFridgeObjects')

Depois de carregar no armazenamento de dados, crie um conjunto de dados do Azure Machine Learning com os dados. Os conjuntos de dados empacotam seus dados em um objeto consumível para treinamento.

O código a seguir cria um conjunto de dados para o treinamento. Como nenhum conjunto de dados de validação foi especificado, 20% dos seus dados de treinamento são usados para validação por padrão.

from azureml.core import Dataset
from azureml.data import DataType

training_dataset_name = 'odFridgeObjectsTrainingDataset'
if training_dataset_name in ws.datasets:
    training_dataset = ws.datasets.get(training_dataset_name)
    print('Found the training dataset', training_dataset_name)
else:
    # create training dataset
        # create training dataset
    training_dataset = Dataset.Tabular.from_json_lines_files(
        path=ds.path('odFridgeObjects/train_annotations.jsonl'),
        set_column_types={"image_url": DataType.to_stream(ds.workspace)},
    )
    training_dataset = training_dataset.register(workspace=ws, name=training_dataset_name)

print("Training dataset name: " + training_dataset.name)

Visualizar conjunto de dados

Você também pode visualizar as caixas delimitadoras de verdade de uma imagem desse conjunto de dados.

Carregue o conjunto de dados em um dataframe Pandas.

import azureml.dataprep as dprep

from azureml.dataprep.api.functions import get_portable_path

# Get pandas dataframe from the dataset
dflow = training_dataset._dataflow.add_column(get_portable_path(dprep.col("image_url")),
                                              "portable_path", "image_url")
dataset_pd = dflow.to_pandas_dataframe(extended_types=True)

Para qualquer imagem específica, você pode executar o código a seguir para exibir as caixas delimitadoras.

image_file = "./odFridgeObjects/images/31.jpg"
plot_ground_truth_boxes_dataset(image_file, dataset_pd)

Configurar o experimento de detecção de objetos

Para configurar execuções do ML automatizado para tarefas relacionadas a imagens, use o objeto AutoMLImageConfig. No AutoMLImageConfig, você pode especificar os algoritmos do modelo com o parâmetro model_name e definir as configurações para executar uma varredura de hiperparâmetro em um espaço de parâmetro definido para localizar o modelo ideal.

Neste exemplo, usamos o AutoMLImageConfig para treinar um modelo de detecção de objetos com o yolov5 e o fasterrcnn_resnet50_fpn, ambos pré-treinados no COCO, um conjunto de dados de detecção de objetos, segmentação e legendagem em grande escala que contém milhares de imagens rotuladas com mais de 80 categorias de rótulo.

Varredura de hiperparâmetro para tarefas de imagem

Você pode executar uma varredura de hiperparâmetro em um espaço de parâmetro definido para localizar o modelo ideal.

O código a seguir define o espaço de parâmetro em preparação para a varredura de hiperparâmetro para cada algoritmo definido, yolov5 e fasterrcnn_resnet50_fpn. No espaço de parâmetro, especifique o intervalo de valores para learning_rate, optimizer, lr_scheduler etc., para que AutoML escolha enquanto tenta gerar um modelo com a métrica primária ideal. Se os valores de hiperparâmetro não forem especificados, valores padrão serão usados para cada algoritmo.

Para as configurações de ajuste, use amostragem aleatória para escolher amostras desse espaço de parâmetro importando as classes GridParameterSampling, RandomParameterSampling e BayesianParameterSampling. Isso informa ao ML automatizado para experimentar um total de 20 iterações com essas diferentes amostras, executando quatro iterações de cada vez no destino de computação, que foi configurado usando quatro nós. Quanto mais parâmetros o espaço tiver, mais iterações você precisará para encontrar os modelos ideais.

A política de encerramento antecipado Bandit também é usada. Esta política encerra as configurações de baixo desempenho, ou seja, as configurações que não estejam dentro da margem de 20% da configuração de melhor desempenho, o que poupa significativamente os recursos de computação.

from azureml.train.hyperdrive import RandomParameterSampling
from azureml.train.hyperdrive import BanditPolicy, HyperDriveConfig
from azureml.train.hyperdrive import choice, uniform

parameter_space = {
    'model': choice(
        {
            'model_name': choice('yolov5'),
            'learning_rate': uniform(0.0001, 0.01),
            #'model_size': choice('small', 'medium'), # model-specific
            'img_size': choice(640, 704, 768), # model-specific
        },
        {
            'model_name': choice('fasterrcnn_resnet50_fpn'),
            'learning_rate': uniform(0.0001, 0.001),
            #'warmup_cosine_lr_warmup_epochs': choice(0, 3),
            'optimizer': choice('sgd', 'adam', 'adamw'),
            'min_size': choice(600, 800), # model-specific
        }
    )
}

tuning_settings = {
    'iterations': 20,
    'max_concurrent_iterations': 4,
    'hyperparameter_sampling': RandomParameterSampling(parameter_space),
    'policy': BanditPolicy(evaluation_interval=2, slack_factor=0.2, delay_evaluation=6)
}

Depois que o espaço de parâmetro e as configurações de ajuste são definidas, você pode passá-las para o objeto AutoMLImageConfig e, depois, enviar o experimento para treinar um modelo de imagem usando o conjunto de dados de treinamento.

from azureml.train.automl import AutoMLImageConfig
automl_image_config = AutoMLImageConfig(task='image-object-detection',
                                        compute_target=compute_target,
                                        training_data=training_dataset,
                                        validation_data=validation_dataset,
                                        primary_metric='mean_average_precision',
                                        **tuning_settings)

automl_image_run = experiment.submit(automl_image_config)
automl_image_run.wait_for_completion(wait_post_processing=True)

Ao fazer uma varredura de hiperparâmetro, pode ser útil visualizar as diferentes configurações que foram experimentadas usando a interface do usuário do HyperDrive. Navegue até essa interface do usuário acessando a guia "Execuções filho" na interface do usuário da automl_image_run principal acima, que é a execução pai do HyperDrive. Em seguida, você pode acessar a guia "Execuções filho" dessa execução. Como alternativa, veja abaixo diretamente a execução pai do HyperDrive e navegue até a respectiva guia "Execuções filho":

from azureml.core import Run
hyperdrive_run = Run(experiment=experiment, run_id=automl_image_run.id + '_HD')
hyperdrive_run

Registrar o melhor modelo

Quando a execução for concluída, podemos registrar o modelo que foi criado com base na melhor execução.

best_child_run = automl_image_run.get_best_child()
model_name = best_child_run.properties['model_name']
model = best_child_run.register_model(model_name = model_name, model_path='outputs/model.pt')

Implantar o modelo como um serviço Web

Com o modelo treinado, você pode implantá-lo no Azure. Implante o modelo treinado como um serviço Web em ACIs (Instâncias de Contêiner do Azure) ou no AKS (Serviço de Kubernetes do Azure). As ACIs são a opção perfeita para testar as implantações, enquanto o AKS é mais adequado para uso de produção em grande escala.

Neste tutorial, implantamos o modelo como um serviço Web no AKS.

  1. Crie um cluster de computação do AKS. Neste exemplo, um SKU de máquina virtual de GPU é usado para o cluster de implantação

    from azureml.core.compute import ComputeTarget, AksCompute
    from azureml.exceptions import ComputeTargetException
    
    # Choose a name for your cluster
    aks_name = "cluster-aks-gpu"
    
    # Check to see if the cluster already exists
    try:
        aks_target = ComputeTarget(workspace=ws, name=aks_name)
        print('Found existing compute target')
    except ComputeTargetException:
        print('Creating a new compute target...')
        # Provision AKS cluster with GPU machine
        prov_config = AksCompute.provisioning_configuration(vm_size="STANDARD_NC6",
                                                            location="eastus2")
        # Create the cluster
        aks_target = ComputeTarget.create(workspace=ws,
                                          name=aks_name,
                                          provisioning_configuration=prov_config)
        aks_target.wait_for_completion(show_output=True)
    
  2. Defina a configuração de inferência que descreve como configurar o serviço Web que contém seu modelo. Você pode usar o script de pontuação e o ambiente da execução de treinamento em sua configuração de inferência.

    Observação

    Para alterar as configurações do modelo, abra o script de pontuação baixado e modifique a variável model_settings antes de implantar o modelo.

    from azureml.core.model import InferenceConfig
    
    best_child_run.download_file('outputs/scoring_file_v_1_0_0.py', output_file_path='score.py')
    environment = best_child_run.get_environment()
    inference_config = InferenceConfig(entry_script='score.py', environment=environment)
    
  3. Em seguida, você pode implantar o modelo como um serviço Web do AKS.

    
    from azureml.core.webservice import AksWebservice
    from azureml.core.webservice import Webservice
    from azureml.core.model import Model
    from azureml.core.environment import Environment
    
    aks_config = AksWebservice.deploy_configuration(autoscale_enabled=True,
                                                    cpu_cores=1,
                                                    memory_gb=50,
                                                    enable_app_insights=True)
    
    aks_service = Model.deploy(ws,
                               models=[model],
                               inference_config=inference_config,
                               deployment_config=aks_config,
                               deployment_target=aks_target,
                               name='automl-image-test',
                               overwrite=True)
    aks_service.wait_for_deployment(show_output=True)
    print(aks_service.state)
    

Testar o serviço Web

Teste o serviço Web implantado para prever novas imagens. Para este tutorial, passe uma imagem aleatória do conjunto de dados e passe-a para o URI de pontuação.

import requests

# URL for the web service
scoring_uri = aks_service.scoring_uri

# If the service is authenticated, set the key or token
key, _ = aks_service.get_keys()

sample_image = './test_image.jpg'

# Load image data
data = open(sample_image, 'rb').read()

# Set the content type
headers = {'Content-Type': 'application/octet-stream'}

# If authentication is enabled, set the authorization header
headers['Authorization'] = f'Bearer {key}'

# Make the request and display the response
resp = requests.post(scoring_uri, data, headers=headers)
print(resp.text)

Visualizar as detecções

Agora que você fez a pontuação de imagem de teste, visualize as caixas delimitadoras desta imagem. Para fazer isso, confirme se você tem a matplotlib instalada.

%pip install --upgrade matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.patches as patches
from PIL import Image
import numpy as np
import json

IMAGE_SIZE = (18,12)
plt.figure(figsize=IMAGE_SIZE)
img_np=mpimg.imread(sample_image)
img = Image.fromarray(img_np.astype('uint8'),'RGB')
x, y = img.size

fig,ax = plt.subplots(1, figsize=(15,15))
# Display the image
ax.imshow(img_np)

# draw box and label for each detection
detections = json.loads(resp.text)
for detect in detections['boxes']:
    label = detect['label']
    box = detect['box']
    conf_score = detect['score']
    if conf_score > 0.6:
        ymin, xmin, ymax, xmax =  box['topY'],box['topX'], box['bottomY'],box['bottomX']
        topleft_x, topleft_y = x * xmin, y * ymin
        width, height = x * (xmax - xmin), y * (ymax - ymin)
        print('{}: [{}, {}, {}, {}], {}'.format(detect['label'], round(topleft_x, 3),
                                                round(topleft_y, 3), round(width, 3),
                                                round(height, 3), round(conf_score, 3)))

        color = np.random.rand(3) #'red'
        rect = patches.Rectangle((topleft_x, topleft_y), width, height,
                                 linewidth=3, edgecolor=color,facecolor='none')

        ax.add_patch(rect)
        plt.text(topleft_x, topleft_y - 10, label, color=color, fontsize=20)

plt.show()

Limpar os recursos

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

Se você não pretende usar os recursos criados, exclua-os para não gerar encargos.

  1. No portal do Azure, selecione Grupos de recursos no canto esquerdo.
  2. Selecione o grupo de recursos criado na lista.
  3. Selecione Excluir 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 workspace. Exiba as propriedades do workspace e, em seguida, selecione Excluir.

Próximas etapas

Neste tutorial de aprendizado de máquina automatizado, você executou as seguintes tarefas:

  • Configurou um workspace e preparou os dados para um experimento.
  • Treinou um modelo automatizado de detecção de objetos
  • Especificou valores de hiperparâmetro para seu modelo
  • Realizou uma varredura de hiperparâmetro
  • Implantou seu modelo
  • Visualizou detecções

Observação

O uso do conjunto de dados de objetos de geladeira está disponível por licença nos termos da licença MIT.