Tutorial: Treinar um modelo de deteção de objeto (visualização) com AutoML e Python (v1)

APLICA-SE A: Python SDK azureml v1

Importante

Os recursos apresentados neste artigo estão em visualização. Eles devem ser considerados recursos experimentais de visualização que podem mudar a qualquer momento.

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

O ML automatizado aceita dados de treinamento e definições de configuração e itera automaticamente por meio de combinações de diferentes métodos de normalização/padronização de recursos, modelos e configurações de hiperparâmetros 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 automatizado de deteção de objetos de aprendizado de máquina
  • Especificar valores de hiperparâmetros para o seu modelo
  • Executar uma varredura de hiperparâmetros
  • Implementar o modelo
  • Visualizar deteções

Pré-requisitos

  • 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.

  • Python 3.7 ou 3.8 são suportados para este recurso

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

  • Transfira e descomprima o *ficheiro de dados odFridgeObjects.zip. O conjunto de dados é anotado no formato Pascal VOC, onde cada imagem corresponde a um arquivo xml. Cada arquivo xml contém informações sobre onde seu 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 para o formato JSONL necessário, como 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 se você desejar executá-lo em seu próprio 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 em seu treinamento automatizado de modelo de ML. Modelos de ML automatizados 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 seu modelo.

O código a seguir cria um cálculo de GPU de tamanho Standard _NC24s_v3 com quatro nós anexados ao espaço de trabalho, 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)

Configuração da experiência

Em seguida, crie um Experiment em seu espaço de trabalho para acompanhar suas execuções de treinamento de modelo.


from azureml.core import Experiment

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

Visualizar dados de entrada

Depois de preparar os dados da imagem de entrada no formato JSONL (JSON Lines), você pode visualizar as caixas delimitadoras da verdade do solo para uma imagem. Para fazer isso, certifique-se de ter matplotlib instalado.

%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, você pode executar 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 para seu espaço de trabalho por meio de um armazenamento de dados. O armazenamento de dados fornece um mecanismo para você carregar ou baixar dados e interagir com eles a partir de seus destinos de computação remotos.

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

Depois de carregado para o armazenamento de dados, você pode criar um conjunto de dados do Azure Machine Learning a partir dos 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 treinamento. Como nenhum conjunto de dados de validação é especificado, por padrão, 20% dos dados de treinamento são usados para validaçã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 do solo para 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, 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 seu experimento de deteção de objetos

Para configurar execuções automatizadas de ML para tarefas relacionadas à imagem, use o AutoMLImageConfig objeto. No , AutoMLImageConfigvocê pode especificar os algoritmos do modelo com o model_name parâmetro e definir as configurações para executar uma varredura de hiperparâmetros em um espaço de parâmetro definido para encontrar o modelo ideal.

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

Varredura de hiperparâmetros para tarefas de imagem

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

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

Para as configurações de ajuste, use amostragem aleatória para selecionar amostras desse espaço de parâmetro importando as GridParameterSampling, RandomParameterSampling classes and BayesianParameterSampling . Fazendo isso, diz ao ML automatizado para tentar um total de 20 iterações com essas amostras diferentes, executando quatro iterações de cada vez em nosso 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 modelos ideais.

A política de rescisão antecipada do Bandit também é usada. Esta política encerra configurações de baixo desempenho; ou seja, as configurações que não estão dentro de 20% de folga da configuração de melhor desempenho, o que economiza significativamente 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 estiverem definidos, você poderá passá-los para seu AutoMLImageConfig objeto e, em seguida, enviar o experimento para treinar um modelo de imagem usando seu 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âmetros, pode ser útil visualizar as diferentes configurações que foram tentadas usando a interface do usuário do HyperDrive. Você pode navegar até essa interface do usuário indo para a guia 'Execuções filho' na interface do usuário do automl_image_run principal acima, que é a execução pai do HyperDrive. Então você pode ir para a guia 'Criança corre' deste. Como alternativa, aqui abaixo você pode ver diretamente a execução pai do HyperDrive e navegar até a guia 'Execuções filhas':

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

Registar o melhor modelo

Uma vez concluída a execução, podemos registrar o modelo que foi criado a partir da 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 modelo como um serviço Web

Depois de ter seu modelo treinado, você pode implantá-lo no Azure. Você pode implantar seu modelo treinado como um serviço Web em Instâncias de Contêiner do Azure (ACI) ou no Serviço Kubernetes do Azure (AKS). O ACI é a opção perfeita para testar implantações, enquanto o AKS é mais adequado para uso de produção em alta escala.

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

  1. Crie um cluster de computação AKS. Neste exemplo, uma SKU de máquina virtual de GPU é usada 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.

    Nota

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

Você pode testar 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 deteções

Agora que você marcou uma imagem de teste, você pode visualizar as caixas delimitadoras para essa imagem. Para fazer isso, certifique-se de ter matplotlib instalado.

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

Clean up resources (Limpar recursos)

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

Se não planeia utilizar os recursos que criou, elimine-os para não incorrer em quaisquer encargos.

  1. No portal do Azure, selecione Grupos de recursos na extremidade esquerda.
  2. Na lista, selecione o grupo de recursos que criou.
  3. Selecione Eliminar grupo de recursos.
  4. Insira o nome do grupo de recursos. Em seguida, selecione Eliminar.

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 de aprendizado de máquina automatizado, você executou as seguintes tarefas:

  • Configurou um espaço de trabalho e preparou dados para um experimento.
  • Treinou um modelo automatizado de deteção de objetos
  • Valores de hiperparâmetros especificados para seu modelo
  • Realizada uma varredura de hiperparâmetros
  • Implantou seu modelo
  • Deteções visualizadas

Nota

O uso do conjunto de dados de objetos de geladeira está disponível através da licença sob a Licença MIT.