Пример использования ИИ: Разработка модели классификации изображений с помощью Sagemaker JumpStart

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

Чтобы построить модель классификации изображений, мы должны сначала получить их записи, то есть изображения классов в контексте для работы, а затем начать процесс моделирования, основанный на жизненном цикле, широко изученном в области машинного обучения (ML), который указывает, что есть 4 фундаментальных столпа для разработки решения ML, под которыми мы подразумеваем процедуру инженерии данных, применение алгоритмов искусственного интеллекта, оценку производительности достигнутой модели, заканчивая развертыванием и мониторингом решения.

Каждый из упомянутых этапов подразумевает длительное время разработки, как для достижения наилучшей модели, так и для ее развертывания и использования в организации, если не учитывать инструменты или рабочую среду, подходящую для создания таких решений, которые могут стать чрезмерно адаптированным решением по отношению к коду модели как таковому, немасштабируемым решением с точки зрения развертывания, и, следовательно, не иметь влияния на бизнес. В этой заметке мы рассмотрим построение модели классификации изображений, опираясь на великолепный инструмент предварительно построенных решений, предлагаемый Sagemaker Studio, то есть сервис JumpStart, добавив альтернативное развертывание с помощью кликов, в облаке AWS. Подробно мы рассмотрим следующие моменты:

  • Обзор сервиса JumpStart
  • Разработка решения с использованием алгоритма ResNet 152 из семейства моделей, предлагаемых Pytorch.
  • Развертывание решения с использованием лямбда-функции и приложения с сервисом уведомлений Simple Notification Service (SNS).

JumpStart программы Sagemaker Studio

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

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

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

Практический пример

Разрабатываемый пример относится к контексту классификации строительных материалов, в котором есть 6 типов объектов, то есть у нас есть 6 классов, которые мы должны определить с помощью модели машинного обучения. Для этого случая мы выбрали модель ResNet 152 из фреймворка Pytorch, который принадлежит к одному из многочисленных решений, предлагаемых JumpStart. Этот конкретный алгоритм имеет наилучшие показатели в семействе ResNet, алгоритмов, предложенных Kaiming He et al, 2015 в статье Deep Residual Learning for Image Recognition.
Одной из особенностей этого алгоритма является глубина реализованных слоев, т.е. 152 слоя в глубину.

Данные

Количество информации для каждого класса достаточно, чтобы начать итерацию непосредственно с помощью JumpStart, поскольку класс с наименьшим количеством наблюдений близок к 300, а самый большой имеет около 2 000 записей. Используя код, разработанный в блокноте Jupyter, мы проверяем расширение каждого файла, поскольку он должен быть в формате .jpg, и генерируем набор данных для обучения и для тестирования в пропорции 90/10 соответственно.

Обучение и оценка

После того как данные настроены в S3, мы приступаем к развертыванию службы Sagemaker Studio. Это облегчит использование сервиса JumpStart. Как только интерфейс Studio включен, мы переходим в сервис, содержащий модели, и ищем алгоритм ResNet 152, выбираем его и переходим к заполнению информации, запрашиваемой для обучения на данных из нашего упражнения.

Наконец, в 3 клика мы уже обучаем решение, на что уйдет примерно 20 минут, отслеживая в облаке метрики обучения.

Самая важная часть этого процесса — создание нашего файла .pth, сжатого в файл .tar.gz, который также называется артефактом модели.

Пакетное преобразование

Обычная альтернатива — провести тест, развернув конечную точку и настроив процедуру, которая позволяет выполнить вывод на партии изображений, однако возник вопрос, какова будет стоимость вывода на тысячах изображений, и не обязательно в реальном времени? Поэтому я решил изучить, как выполнить пакетную работу с артефактом, сгенерированным в ходе обучения JumpStart.

Для этого процесса наиболее важным является то, что артефакт модели должен иметь определенную структуру, хранящую файл выводов python, или также известный как entrypoint.py, когда мы разрабатываем модель локально. Структура этого артефакта показана ниже:

/tar.gz
|-- tar
|   |-- label_info.json
|   |-- model.pth
|   `-- code
|        -- _init_.py
|        -- inference.py
|        -- version
|        `-- lib
|        `-- constants
|               -- _init_.py
|               -- constants.py
Вход в полноэкранный режим Выход из полноэкранного режима

Где файл inference.py содержит следующие функции:

import json
import logging
import os
import re

import numpy as np
import torch
from constants import constants
from PIL import Image
from sagemaker_inference import content_types
from sagemaker_inference import encoder
from six import BytesIO


logging.basicConfig(format="%(asctime)s %(message)s", level=logging.INFO)

DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")


class PyTorchIC:
    """Model class that wraps around the Torch model."""

    def __init__(self, model, model_dir):
        """Image classification class that wraps around the Torch model.
        Stores the model inside class and read the labels from a JSON file in the model directory.
        """
        self.model = model
        with open(os.path.join(model_dir, constants.LABELS_INFO)) as f:
            self.labels = json.loads(f.read())[constants.LABELS]

    def forward(self, tensors):
        """Make a forward pass."""
        input_batch = tensors.unsqueeze(0)
        input_batch = input_batch.to(DEVICE)
        with torch.no_grad():
            output = self.model(input_batch)
        return torch.nn.functional.softmax(output[0], dim=0)

    @classmethod
    def tensorize(cls, input_data):
        """Prepare the image, return the tensor."""
        try:
            from torchvision import transforms
        except ImportError:
            raise
        transform = transforms.Compose(
            [
                transforms.Resize(256),
                transforms.CenterCrop(224),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
            ]
        )
        return transform(input_data).to(DEVICE)

    @classmethod
    def decode(cls, input_data, content_type):
        """Decode input with content_type"""
        _ = content_type
        return input_data

    @classmethod
    def encode(cls, predictions, accept):
        """Encode results with accept"""
        return encoder.encode(predictions, accept)

    def __call__(self, input_data, content_type=content_types.JSON, accept=content_types.JSON, **kwargs):
        """Decode the image, tensorize it, make a forward pass and return the encoded prediction."""
        input_data = self.decode(input_data=input_data, content_type=content_type)
        tensors = self.tensorize(input_data)
        predictions = self.forward(tensors)
        predictions = predictions.cpu()
        output = {constants.PROBABILITIES: predictions}
        if accept.endswith(constants.VERBOSE_EXTENSION):
            output[constants.LABELS] = self.labels
            predicted_label_idx = np.argmax(predictions)
            output[constants.PREDICTED_LABEL] = self.labels[predicted_label_idx]
        accept = accept.rstrip(constants.VERBOSE_EXTENSION)
        return self.encode(output, accept=accept)


def model_fn(model_dir):
    """Create our inference task as a delegate to the model.
    This runs only once per one worker.
    """
    for root, dirs, files in os.walk(model_dir):
        for file in files:
            if re.compile(".*\.pth").match(file):
                checkpoint = re.compile(".*\.pth").match(file).group()
    try:
        model = torch.load(checkpoint)
        if torch.cuda.is_available():
            model.to("cuda")
        model.eval()
        return PyTorchIC(model=model, model_dir=model_dir)
    except Exception:
        logging.exception("Failed to load model")
        raise


def transform_fn(task: PyTorchIC, input_data, content_type, accept):
    """Make predictions against the model and return a serialized response.
    The function signature conforms to the SM contract.
    Args:
        task (obj): model loaded by model_fn, in our case is one of the Task.
        input_data (obj): the request data.
        content_type (str): the request content type.
        accept (str): accept header expected by the client.
    Returns:
        obj: the serialized prediction result or a tuple of the form
            (response_data, content_type)
    """
    # input_data = decoder.decode(input_data, content_type)
    if content_type == "application/x-image":
        input_data = Image.open(BytesIO(input_data)).convert("RGB")
        try:
            output = task(input_data=input_data, content_type=content_type, accept=accept)
            return output
        except Exception:
            logging.exception("Failed to do transform")
            raise
    raise ValueError('{{"error": "unsupported content type {}"}}'.format(content_type or "unknown"))
Вход в полноэкранный режим Выход из полноэкранного режима

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

Хотя в метриках видны высокие значения, два класса не показывают хороших результатов с данными за пределами обучающей выборки, класс-1 и класс-4, поэтому мы решили применить увеличение данных для этих классов.

Дополнение данных

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

from PIL import Image
from torchvision import transforms as tr
from torchvision.transforms import Compo

pipeline1 = Compose(
             [tr.RandomRotation(degrees = 90),
              tr.RandomRotation(degrees = 270)
             ])

augmented_image1 = pipeline1(img = im)
augmented_image1.show()
Вход в полноэкранный режим Выход из полноэкранного режима

Пример показан ниже, исходное изображение:

Сгенерированное новое изображение:

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

Использование модели: Уведомление о выводах по электронной почте

Для этого упражнения мы решили использовать лямбда-функцию AWS, которая позволяет вызывать модель при получении изображения в ведро S3.

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

Заключительные слова

В этом посте нам удалось разработать сквозной процесс, в контексте алгоритмов глубокого обучения, применяя 4 фундаментальных столпа моделирования искусственного интеллекта, и построить простое приложение использования этих алгоритмов. Следующей задачей является создание развертывания этой модели через оркестратор AWS ml-ops и тестирование потребления решения в рамках продуктивной архитектуры. Основная ценность данной публикации заключалась в демонстрации того, как сервис JumpStart позволяет получать решения в области искусственного интеллекта, посредством нескольких кликов, обучения с использованием ваших данных и развертывания решения в облаке.

Ссылка

  • Документация JumpStart

  • Страница AWS из JumpStart

  • Модель классификации изображений в блоге с JumpStart

  • Глубокое остаточное обучение для распознавания изображений

Оцените статью
devanswers.ru
Добавить комментарий