Учебник. Обучение модели обнаружения объектов (предварительная версия) с помощью AutoML и Python (версия 1)

ОБЛАСТЬ ПРИМЕНЕНИЯ:Пакет SDK для Python для ML Azure версии 1

Важно!

Функции, описанные в этой статье, доступны в режиме предварительной версии. Их следует считать экспериментальными, и она могут быть изменены в любое время.

В этом учебнике описывается обучение модели обнаружения объектов с помощью автоматизированного машинного обучения в службе "Машинное обучение Azure" с использованием пакета SDK Python для Машинного обучения Azure. Эта модель обнаружения объектов определяет, содержит ли изображение объекты, такие как жестяная банка, картонная коробка, бутылка с молоком или бутылка с водой.

В ходе автоматизированного машинного обучения добавляются данные для обучения и настраиваются параметры, а также выполняется автоматическая итерация с использованием комбинаций разных методов нормализации или стандартизации признаков, моделей и настроек гиперпараметров для получения оптимальной модели.

Работая с этим учебником, вы напишите код с помощью пакета SDK для Python и изучите следующие задачи:

  • Скачивание и преобразование данных.
  • Обучение модели обнаружения объектов автоматизированного машинного обучения.
  • Определение значений гиперпараметров для модели.
  • Выполнение очистки гиперпараметров.
  • Развертывание модели
  • Визуализация обнаружений.

Предварительные требования

  • Если у вас еще нет подписки Azure, создайте бесплатную учетную запись, прежде чем начинать работу. Опробуйте бесплатную или платную версию Машинного обучения Azure.

  • Эта функция поддерживает Python 3.7 или 3.8.

  • Выполните инструкции из краткого руководства по началу работы с Машинным обучением Azure, если у вас еще нет рабочей области службы "Машинное обучение Azure".

  • Скачайте и распакуйте файл данных *odFridgeObjects.zip. Набор данных объявляется в формате Pascal VOC, в котором каждое изображение соответствует XML-файлу. Каждый XML-файл содержит сведения о том, где находится соответствующий файл изображения, а также содержит сведения об ограничивающих прямоугольниках и метках объектов. Чтобы использовать эти данные, сначала необходимо преобразовать их в требуемый формат JSONL, как показано в разделе Преобразование скачанных данных в JSONL записной книжки.

Это руководство также доступно в репозитории azureml-examples на GitHub, если вы хотите запустить его в собственной локальной среде. Чтобы получить нужные пакеты, сделайте следующее:

Настройка целевых объектов вычисления

Сначала необходимо настроить целевой объект вычислений, который будет использоваться для обучения модели автоматизированного машинного обучения. Для моделей автоматизированного машинного обучения требуются номера SKU GPU для выполнения задач с изображениями.

В этом учебнике используется серия NCsv3 (с графическими процессорами V100), так как этот тип целевого объекта вычислений использует несколько графических процессоров для ускорения обучения. Кроме того, можно настроить несколько узлов, чтобы воспользоваться преимуществами параллелизма при настройке гиперпараметров модели.

Приведенный ниже код создает вычисление GPU с размером Standard _NC24s_v3 с четырьмя узлами, присоединенными к рабочей области, ws.

Предупреждение

Убедитесь, что ваша подписка имеет достаточную квоту для целевого объекта вычислений, который вы хотите использовать.

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)

Настройка эксперимента

Затем создайте Experiment в рабочей области, чтобы отследить запуски обучения модели.


from azureml.core import Experiment

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

Визуализация входных данных

После подготовки данных изображения ввода в формате JSON (строки JSON) для изображения можно визуализировать фактические ограничивающие прямоугольники. Для этого установите 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))

Используя указанные выше вспомогательные функции, для любого изображения можно выполнить следующий код, чтобы отобразить ограничивающие прямоугольники.

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

plot_ground_truth_boxes_jsonl(image_file, jsonl_file)

Загрузка данных и создание набора данных

Чтобы использовать данные для обучения, загрузите их в рабочую область через хранилище данных. Хранилище данных предоставляет механизм для загрузки или скачивания данных и взаимодействия с ними из удаленных целевых объектов вычислений.

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

После загрузки в хранилище данных можно создать набор данных Машинного обучения Azure на основе данных. Наборы данных упаковывают данные в потребляемый объект для обучения.

Следующий код создает набор данных для обучения. Так как проверочный набор данных не указан, для проверки по умолчанию используется 20 % обучающих данных.

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)

Визуализация набора данных

Вы также можете визуализировать фактические ограничивающие прямоугольники для изображения из этого набора данных.

Загрузите набор данных в кадр данных 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)

Для любого указанного изображения можно выполнить следующий код, чтобы отобразить ограничивающие прямоугольники.

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

Настройка эксперимента по обнаружению объектов

Чтобы настроить запуски автоматизированного машинного обучения для задач, связанных с изображениями, используйте объект AutoMLImageConfig. В AutoMLImageConfig вы можете указать алгоритмы модели с помощью параметра model_name и настроить параметры для выполнения очистки гиперпараметров в определенном их пространстве, чтобы найти оптимальную модель.

В этом примере мы используем AutoMLImageConfig для обучения модели обнаружения объектов с yolov5 и fasterrcnn_resnet50_fpn, оба из которых предварительно обучены в COCO, обнаружении крупномасштабных объектов, сегментации и наборе данных субтитров, которые содержат более тысячи помеченных изображений с более чем 80 категориями меток.

Очистка гиперпараметров для задач с изображениями

Чтобы найти оптимальную модель, можно выполнить очистку гиперпараметра для определенного пространства параметров.

Следующий код определяет пространство параметров в процессе подготовки для очистки гиперпараметров для каждого определенного алгоритма, yolov5 и fasterrcnn_resnet50_fpn. В пространстве параметров укажите диапазон значений для learning_rate, optimizer, lr_scheduler и т. д. для выбора службой AutoML, так как она пытается создать модель с оптимальной первичной метрикой. Если значения параметров не указаны, для каждого алгоритма используются значения по умолчанию.

Для параметров настройки используйте случайную выборку, чтобы выбрать примеры из этого пространства параметров путем импорта классов GridParameterSampling, RandomParameterSampling и BayesianParameterSampling. При этом автоматическому машинному обучению предлагается выполнить всего 20 итераций с этими различными примерами, одновременно выполнив четыре итерации на целевом объекте вычислений, который был настроен с помощью четырех узлов. Чем больше параметров содержит пространство, тем больше итераций необходимо для поиска оптимальных моделей.

Кроме того, используется политика преждевременного завершения Bandit. Эта политика завершает работу конфигураций с низкой производительностью, то есть тех конфигураций, которые не находятся в пределах резерва времени в 20 % от наиболее производительной конфигурации, что значительно экономит вычислительные ресурсы.

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

После определения пространства параметров и параметров настройки их можно передать в объект AutoMLImageConfig, а затем отправить эксперимент, чтобы обучить модель изображений с помощью набора данных для обучения.

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)

При выполнении очистки гиперпараметров полезно визуализировать различные конфигурации, которые выполнялись с помощью пользовательского интерфейса HyperDrive. Вы можете перейти к этому пользовательскому интерфейсу, зайдя на вкладку "Дочерние запуски" в пользовательском интерфейсе основного запуска automl_image_run, который является родительским запуском HyperDrive. Затем можно перейти на вкладку "Дочерние запуски". Кроме того, здесь можно увидеть непосредственно родительский запуск HyperDrive и перейти на вкладку "Дочерние запуски":

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

Регистрация наилучшей модели.

После завершения запуска можно зарегистрировать модель, созданную на основе лучшего запуска.

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

Развертывание модели в качестве веб-службы

Обучив модель, вы можете развернуть ее в Azure. Обученную модель можно развернуть как веб-службу в Экземплярах контейнеров Azure или Службе Azure Kubernetes (AKS). ACI является идеальным вариантом для тестирования развертываний, а AKS лучше подходит для крупномасштабного использования в рабочей среде.

В рамках этого учебника мы развертываем модель в качестве веб-службы в AKS.

  1. Создайте вычислительный кластер AKS. В этом примере для кластера развертывания используется номер SKU виртуальной машины 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. Создайте определение конфигурации вывода, которое описывает настройку веб-службы, содержащей модель. Скрипт оценки и среду можно использовать из обучающего запуска в конфигурации вывода.

    Примечание

    Чтобы изменить параметры модели, откройте скачанный скрипт оценки и измените переменную model_settings перед развертыванием модели.

    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. Затем можно развернуть модель как веб-службу 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)
    

Тестирование веб-службы

Развернутую веб-службу можно протестировать для прогнозирования новых изображений. Для работы с этим учебником передайте случайное изображение из набора данных, а затем передайте его в URI оценки.

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)

Визуализация обнаружений

После оценки тестового изображения можно визуализировать ограничивающие прямоугольники для этого изображения. Для этого убедитесь, что у вас установлена библиотека 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()

Очистка ресурсов

Не выполняйте инструкции из этого раздела, если вы собираетесь изучать другие руководства по Машинному обучению Azure.

Если вы не планируете использовать созданные ресурсы, удалите их, чтобы с вас не взималась плата.

  1. На портале Azure выберите Группы ресурсов в левой части окна.
  2. В списке выберите созданную группу ресурсов.
  3. Выберите Удалить группу ресурсов.
  4. Введите имя группы ресурсов. Теперь щелкните Удалить.

Вы также можете сохранить группу ресурсов, но удалить одну рабочую область. Отобразите свойства рабочей области и нажмите кнопку Удалить.

Дальнейшие действия

Изучив это руководство об автоматическом машинном обучении, вы выполнили следующие задачи.

  • Настройка рабочей области и подготовка данных для эксперимента.
  • Обучение модели автоматизированного обнаружения объектов.
  • Определение значения гиперпараметров для модели.
  • Очистка гиперпараметров.
  • Развертывание модели.
  • Визуализация обнаружений.

Примечание

Использование набора данных объектов "Холодильник" доступно через лицензирование в рамках лицензии MIT.