Esercitazione: Eseguire il training di un modello di rilevamento oggetti (anteprima) con AutoML e Python (v1)

SI APPLICA A:Python SDK azureml v1

Importante

Le funzionalità presentate in questo articolo sono disponibili in anteprima. Devono essere considerate funzionalità di anteprima sperimentali che potrebbero cambiare in qualsiasi momento.

Questa esercitazione descrive come eseguire il training di un modello di rilevamento oggetti con ML automatizzato di Azure Machine Learning e Azure Machine Learning Python SDK. Questo modello di rilevamento oggetti identifica se l'immagine contiene oggetti, ad esempio una lattina, una scatola, una bottiglia di latte o una bottiglia d'acqua.

ML automatizzato accetta le impostazioni di configurazione e i dati di training ed esegue automaticamente l'iterazione delle combinazioni di diversi metodi di normalizzazione/standardizzazione di funzionalità, dei modelli e delle impostazioni degli iperparametri allo scopo di ottenere il modello ottimale.

In questa esercitazione verrà usato Python SDK per la scrittura del codice e verranno illustrate le attività seguenti:

  • Scaricare e trasformare i dati
  • Eseguire il training di un modello di rilevamento oggetti di Machine Learning automatizzato
  • Specificare i valori degli iperparametri per il modello
  • Eseguire uno sweeping di iperparametri
  • Distribuire il modello
  • Visualizzare i rilevamenti

Prerequisiti

  • Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare. Provare la versione gratuita o a pagamento di Azure Machine Learning.

  • Per questa funzionalità sono supportati Python 3.7 o 3.8

  • Completare l'Avvio rapido: Iniziare a usare Azure Machine Learning se non si ha già un'area di lavoro di Azure Machine Learning.

  • Scaricare e decomprimere il file di dati *odFridgeObjects.zip. Il set di dati viene annotato in formato Pascal VOC, in cui ogni immagine corrisponde a un file XML. Ogni file XML contiene informazioni sul percorso in cui si trova il file di immagine corrispondente, oltre a informazioni sui rettangoli di selezione e sulle etichette degli oggetti. Per usare questi dati, è prima necessario convertirli nel formato JSONL richiesto, come illustrato nella sezione Convertire i dati scaricati in JSONL del notebook.

Questa esercitazione è disponibile anche nel repository azureml-examples in GitHub se si vuole eseguirlo nell'ambiente locale. Per ottenere i pacchetti richiesti:

Configurazione della destinazione di calcolo

È prima necessario configurare una destinazione di calcolo da usare per il training del modello di ML automatizzato. I modelli di ML automatizzato per le attività correlate alle immagini richiedono SKU GPU.

Per questa esercitazione si usa la serie NCsv3 (con GPU V100) perché questo tipo di destinazione di calcolo sfrutta più GPU per velocizzare il training. È inoltre possibile configurare più nodi per sfruttare il parallelismo durante l'ottimizzazione degli iperparametri per il modello.

Il codice seguente consente di creare un ambiente di calcolo GPU di dimensioni Standard_NC24s_v3 con quattro nodi collegati all'area di lavoro ws.

Avviso

Verificare che la sottoscrizione disponga di una quota sufficiente per la destinazione di calcolo da usare.

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)

Configurazione dell'esperimento

Creare quindi un elemento Experiment nell'area di lavoro per tenere traccia delle esecuzioni di training del modello.


from azureml.core import Experiment

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

Visualizzare i dati di input

Dopo aver preparato i dati di immagine di input in formato JSONL (JSON Lines), è possibile visualizzare i rettangoli di selezione della verità di base per un'immagine. A tale scopo, assicurarsi che sia installato matplotlib.

%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 le funzioni helper precedenti, per qualsiasi immagine specifica, è possibile eseguire il codice seguente per visualizzare i rettangoli di selezione.

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

plot_ground_truth_boxes_jsonl(image_file, jsonl_file)

Caricare i dati e creare il set di dati

Per usare i dati per il training, caricarli nell'area di lavoro tramite un archivio dati. L'archivio dati fornisce un meccanismo che consente di caricare o scaricare i dati e interagirvi dalle destinazioni di calcolo remote.

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

Dopo il caricamento nell'archivio dati, è possibile creare un set di dati di Azure Machine Learning dai dati. I set di dati inseriscono i dati in un oggetto utilizzabile per il training.

Il codice seguente consente di creare un set di dati per il training. Poiché non viene specificato alcun set di dati di convalida, per impostazione predefinita per la convalida viene usato il 20% dei dati di training.

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)

Visualizzare il set di dati

È anche possibile visualizzare i rettangoli di selezione della verità di base per un'immagine da questo set di dati.

Caricare il set di dati in un 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)

Per qualsiasi immagine specifica è possibile eseguire il codice seguente per visualizzare i rettangoli di selezione.

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

Configurare l'esperimento di rilevamento oggetti

Per configurare le esecuzioni automatizzate di ML automatizzato per attività correlate alle immagini, usare l'oggetto AutoMLImageConfig. In AutoMLImageConfig è possibile specificare gli algoritmi del modello con il parametro model_name e configurare le impostazioni per eseguire uno sweeping degli iperparametri su uno spazio parametri definito per trovare il modello ottimale.

In questo esempio si userà AutoMLImageConfig per eseguire il training di un modello di rilevamento oggetti con yolov5 e fasterrcnn_resnet50_fpn, entrambi sottoposti a training preliminare in COCO, un rilevamento di oggetti su larga scala, segmentazione e set di dati di didascalia che contiene oltre migliaia di immagini etichettate con più di 80 categorie di etichette.

Sweeping degli iperparametri per le attività correlate alle immagini

È possibile eseguire uno sweeping di iperparametri su uno spazio parametri definito per trovare il modello ottimale.

Il codice seguente consente di definire lo spazio dei parametri in preparazione per lo sweeping degli iperparametri per ogni algoritmo definito, ossia yolov5 e fasterrcnn_resnet50_fpn. Nello spazio parametri specificare l'intervallo di valori per learning_rate, optimizer, lr_scheduler e così via da cui AutoML potrà scegliere quando proverà a generare un modello con la metrica primaria ottimale. Se non si specificano i valori degli iperparametri, per ogni algoritmo verranno usati i valori predefiniti.

Per le impostazioni di ottimizzazione, usare il campionamento casuale per selezionare campioni da questo spazio parametri importando le classi GridParameterSampling, RandomParameterSampling e BayesianParameterSampling. In questo modo viene indicato a ML automatizzato di provare un totale di 20 iterazioni con questi diversi campioni, eseguendo quattro iterazioni alla volta nella destinazione di calcolo, configurata usando quattro nodi. Più parametri sono presenti nello spazio, maggiore è il numero di iterazioni necessarie per trovare modelli ottimali.

Vengono usati anche i criteri di terminazione anticipata di Bandit. Questi criteri consentono di terminare le configurazioni ritenute insufficienti, ovvero quelle che non rientrano nel 20% del margine di flessibilità delle configurazioni migliori e questo consente di risparmiare in modo significativo sulle risorse di calcolo.

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

Dopo aver definito le impostazioni dello spazio parametri e di ottimizzazione, è possibile passarle nell'oggetto AutoMLImageConfig e quindi inviare l'esperimento per eseguire il training di un modello di immagini con il set di dati di training.

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)

Quando si esegue uno sweeping di iperparametri, può essere utile visualizzare le diverse configurazioni provate con l'interfaccia utente di HyperDrive. È possibile passare a questa interfaccia utente dalla scheda delle esecuzioni figlio dell'interfaccia utente di automl_image_run principale a partire dall'alto, ovvero l'esecuzione padre di HyperDrive. È quindi possibile passare alla scheda delle esecuzioni figlio di tale processo. In alternativa, come illustrato di seguito è possibile visualizzare direttamente l'esecuzione padre di HyperDrive e passare alla relativa scheda delle esecuzioni figlio:

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

Registrare il modello migliore

Al termine dell'esecuzione, è possibile registrare il modello creato dall'esecuzione migliore.

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

Distribuire il modello come servizio Web

Dopo aver eseguito il training del modello, è possibile distribuirlo in Azure. È possibile distribuire il modello sottoposto a training come servizio Web in Istanze di Azure Container o nel servizio Azure Kubernetes. Istanze di Azure Container è ideale per testare le distribuzioni, mentre il servizio Azure Kubernetes è più adatto per l'uso in ambiente di produzione su larga scala.

In questa esercitazione il modello viene distribuito come servizio Web nel servizio Azure Kubernetes.

  1. Creare un cluster di elaborazione del servizio Azure Kubernetes. In questo esempio per il cluster di distribuzione viene usato uno SKU di macchina virtuale GPU

    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. Definire la configurazione dell'inferenza che descrive come configurare il servizio Web contenente il modello. È possibile usare lo script di assegnazione dei punteggi e l'ambiente dall'esecuzione del training nella configurazione dell'inferenza.

    Nota

    Per modificare le impostazioni del modello, aprire lo script di assegnazione dei punteggi scaricato e modificare la variabile model_settings prima di distribuire il modello.

    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. È quindi possibile distribuire il modello come servizio Web del servizio Azure Kubernetes.

    
    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)
    

Testare il servizio Web

È possibile testare il servizio Web distribuito per prevedere le nuove immagini. Per questa esercitazione, passare un'immagine casuale del set di dati all'URI di assegnazione dei punteggi.

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)

Visualizzare i rilevamenti

Dopo aver ottenuto un punteggio per un'immagine di test, è possibile visualizzare i rettangoli di selezione per questa immagine. A tale scopo, assicurarsi di avere installato matplotlib.

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

Pulire le risorse

Se si intende eseguire altre esercitazioni su Azure Machine Learning, non completare questa sezione.

Se non si prevede di usare le risorse create, eliminarle per evitare addebiti.

  1. Nel portale di Azure fare clic su Gruppi di risorse all'estrema sinistra.
  2. Nell'elenco selezionare il gruppo di risorse creato.
  3. Selezionare Elimina gruppo di risorse.
  4. Immettere il nome del gruppo di risorse. Quindi seleziona Elimina.

È anche possibile mantenere il gruppo di risorse ma eliminare una singola area di lavoro. Visualizzare le proprietà dell'area di lavoro e selezionare Elimina.

Passaggi successivi

In questa esercitazione sulla modalità automatizzata di apprendimento automatico sono state eseguite queste attività:

  • Configurare un'area di lavoro e preparare i dati per un esperimento.
  • Training di un modello di rilevamento oggetti automatizzato
  • Specifica dei valori degli iperparametri per il modello
  • Esecuzione di uno sweeping di iperparametri
  • Distribuzione del modello
  • Visualizzazione dei rilevamenti

Nota

L'uso del set di dati degli oggetti fridge è concesso su licenza MIT.