В настоящее время существует множество различных решений для обслуживания моделей машинного обучения в производственных средах в связи с ростом популярности MLOps.
Одним из наиболее популярных решений является TensorFlow Serving, разработанный командой TensorFlow для развертывания и обслуживания своих моделей в производственных средах. В ответ на это развитие был создан TorchServe, чтобы дать пользователям PyTorch возможность легко развертывать свои модели.
TorchServe — это гибкий и простой в использовании инструмент для обслуживания моделей PyTorch. Это платформа с открытым исходным кодом, которая позволяет легко и эффективно развертывать обученные модели PyTorch в любом масштабе без необходимости писать собственный код. TorchServe обеспечивает легкое обслуживание с низкой задержкой, поэтому вы можете развертывать свои модели для высокопроизводительного вывода. TorchServe является экспериментальным и может еще претерпеть некоторые изменения, но в любом случае он предлагает некоторые интересные функции.
Основные возможности:
Мультимодельное обслуживание
Управление версиями модели для A/B-тестирования
Метрики для мониторинга
Конечные точки RESTful для интеграции приложений
Поддерживает любую среду машинного обучения, включая Amazon SageMaker, Kubernetes, Amazon EKS и Amazon EC2.
TorchServe можно использовать для многих типов вывода в производственных условиях.
Предоставляет простой в использовании интерфейс командной строки.
Об остальных инструментах можно почитать здесь: Best Tools to Do ML Model Serving
В данной статье мы рассмотрим процесс обучения и развертывания сверточной модели с переносом обучения с использованием ResNet в качестве backbone. Эта модель классифицирует изображения, полученные из части известного датасета, названного Cat_Dog_data
🔨 Requirements
Прежде всего, убедитесь, что у вас установлена Java JDK версии 11, так как для развертывания модели TorchServe использует Java для экспонирования своих API.
sudo apt install --no-install-recommends -y openjdk-11-jre-headless
Затем можно продолжить с установкой необходимых пакетов Python для PyTorch и TorchServe (пример для CPU)
pip install torch==1.7.0 torchvision==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
pip install torchserve==0.2.0 torch-model-archiver==0.2.0
📂 Dataset
Для обучения модели классификации изображений мы используем датасет Cat_Dog_data содержащий 2 класса. Это большой набор изображений кошек и собак, являющийся частью уже закрытого конкурса Kaggle и представляет собой подмножество так называемого набора данных Asirra.
![Source code: tfds.image_classification.CatsVsDogs Source code: tfds.image_classification.CatsVsDogs](https://habrastorage.org/getpro/habr/upload_files/05e/c99/10e/05ec9910ec258f5cd408d56b5d35d6f8.png)
🤖 Modelling
Мы продолжим подход к трансферному обучению, используя ResNet в качестве основы с предварительно обученным набором весов, обученным на ImageNet, поскольку это современный уровень, когда речь идет о проблемах классификации изображений.
В этом случае, поскольку мы хотим обслуживать модель PyTorch, мы будем использовать реализацию ResNet в PyTorch и, более конкретно, ResNet50, 50 означает количество содержащихся в ней слоев. Поскольку мы собираемся использовать трансферное обучение на основе предварительно обученной модели, мы загрузим модель ResNet50 и заморозим ее веса, используя следующий фрагмент кода:
model = models.resnet50(pretrained=True)
Note: Полный код доступен в здесь в Google Colab в формате tutorial: cats_n_dogs_classifier.ipynb
После загрузки нам нужно обновить слой fc, который означает «fully connected», и это последний уровень модели, поверх которого будут рассчитываться веса для оптимизации сети для нашего набора данных. В данном конкретном случае мы включили следующий последовательный слой, предварительно заморозив параметры (градиенты для них не будут вычисляться и обновляться во время обучения):
classifier = nn.Sequential(nn.Linear(2048, 512),
nn.ReLU(),
nn.Dropout(p=0.2),
nn.Linear(512, 2),
nn.LogSoftmax(dim=1))
model.fc = classifier
После обучения модели вам просто нужно сохранить модель путем state_dict в файл .pth torch.save(model.state_dict(), PATH), содержащий предварительно обученный набор весов.
После того, как state_dict создан на основе предварительно обученной модели, вам необходимо убедиться, что его можно загрузить правильно. Но прежде чем проверять это, необходимо определить архитектуру модели как класс Python, чтобы в эту архитектуру загружался предварительно обученный набор весов, а это означает, что ключи между моделью и весами должны совпадать.
Поскольку мы использовали трансферное обучение на основе предварительно обученной модели и только что изменили последний полностью связный слой (fc), нам необходимо изменить исходный класс ResNet50. Вы можете найти исходный класс для этой модели по здесь torchvision/models/segmentation, а для остальных предварительно обученных моделей PyTorch — torchvision/models.
Класс для нашей модели для можно найти здесь: model_resnet50.py
Здесь мы создаем новый класс с именем ImageClassifier, который наследуется от базового класса ResNet, определенного в этом файле. Затем нам нужно инициализировать этот класс с нашей архитектурой, которая в данном случае такая же, как у ResNet50, а затем мы изменяем количество классов, которые для нашего случая это 2, как мы упоминали ранее. Наконец, чтобы обеспечить соответствие state_dict классу модели, нам нужно переопределить уровень self.fc, который является последним уровнем сети. Поскольку мы используем этот последовательный слой при обучении модели, окончательные веса были оптимизированы для нашего набора данных по этому слою, поэтому, просто переопределив его, мы получим архитектуру модели с нашими изменениями.
Затем, чтобы проверить, что модель может быть загружена в класс ImageClassifier, вам нужно просто определить класс и загрузить веса, используя следующий фрагмент кода:
load_path = 'models/cats_n_dogs_resnet50.pth'
model = ImageClassifier()
model.load_state_dict(torch.load(load_path))
model.eval()
Чей ожидаемый результат должен быть “<All keys matched successfully>”.
🚀 Deployment
1. Создайте файл MAR.
Прежде всего вам нужно будет создать файл MAR, который представляет собой «готовый к использованию» архив модели, созданной с помощью torch-model-archiver. Итак, для этого вам нужно будет использовать следующую команду:
torch-model-archiver --model-name cats_n_dogs_resnet50
--version 1.0
--model-file model_resnet50.py
--serialized-file model/cats_n_dogs_resnet50.pth
--handler handler.py
--extra-files index_to_name.json
Таким образом, используемые флаги torch-model-archiver означают:
— model-name: имя, которое будет иметь сгенерированный файл MAR, готовый к использованию.
— version: это необязательно, хотя рекомендуется включать версии моделей, чтобы обеспечить их правильное отслеживание.
— model-file: файл, в котором определена архитектура модели.
— serialized-file: dumped state_dictвесов обученной модели.
— handler: файл Python, который определяет предварительную обработку данных, вывод и постобработку.
— extra-files: поскольку это проблема классификации, вы можете включить словарь json, содержащий отношения между идентификаторами (цель модели) и метками или также дополнительными файлами, необходимыми файлу модели для более чистого форматирования выходных данных.
Note. Вы можете определить собственные обработчики, но это не обязательно, поскольку уже существуют обработчики по умолчанию для каждой возможной проблемы, определенные TorchServe и доступные через простую строку. Текущее возможное обработчики по умолчанию: «image_classifier», «image_segmenter», «object_detector» и «text_classifier». Дополнительную информацию можно найти в разделе TorchServe Default Handlers..
После создания вам нужно будет поместить файл MAR в каталог развертывания/хранилища моделей :
mv cats_n_dogs_resnet50.mar deployment/model-store
Дополнительную информацию о Torch-Model-Archiver можно найти на Torch Model Archiver for TorchServe.
2. Развертывание TorchServe
Как только вы создадите «готовую к использованию» модель MAR, вам останется только обслуживать ее. Процесс обслуживания предварительно обученной модели PyTorch в виде файла MAR начинается с развертывания API REST TorchServe. Этими API являются Inference API, Management API и Metrics API, которые по умолчанию развернуты на локальном хосте в портах 8080, 8081 и 8082 соответственно. При развертывании TorchServe вы также можете указать каталог, в котором хранятся файлы MAR, чтобы они развертывались в API при запуске. Команда для развертывания TorchServe с текущей моделью MAR, хранящейся в папке deployment/model-store/:
torchserve --start \
--ncs \
--ts-config deployment/config.properties \
--model-store deployment/model-store \
--models cats_n_dogs=cats_n_dogs_resnet50.mar
Флаги torchserve означают:
— start: запустить службу TorchServe (развернуть API).
— ncs: отключить функцию snapshot (необязательно).
— ts-config: включить файл конфигурации, который тоже не является обязательным.
— model-store: каталог, в котором хранятся файлы MAR.
— models: это имя(я) модели(й), которая будет обслуживаться при запуске, включая псевдоним, который будет конечной точкой API этой конкретной модели, и имя файла этой модели в формате endpoint=model_name.mar.
Note: альтернативой может быть сначала развертывание TorchServe (без указания моделей), а затем регистрация модели (или моделей) с помощью Management API и масштабирование количества рабочих процессов (при необходимости).
torchserve --start \
--ncs \
--ts-config deployment/config.properties \
--model-store deployment/model-store
curl -X POST "http://localhost:8081/models?initial_workers=1&synchronous=true&url=cats_n_dogs_resnet50.mar"
curl -X PUT "http://localhost:8081/models/foodnet?min_worker=3"
Дополнительную информацию о CLI torchserve можно найти на странице TorchServe CLI.
3. Проверьте статус
Чтобы проверить доступность развернутого API TorchServe, вы можете просто отправить HTTP-запрос GET к API-интерфейсу Inference, развернутому по умолчанию в порту 8080, но вам следует проверить файл config.properties, в котором указан «inference_address», включая порт.
curl http://localhost:8080/ping
Note: если статус запроса на проверку работоспособности был «Unhealthy», вам следует проверить журналы либо с консоли, откуда вы запустили развертывание TorchServe, либо из каталога logs/, который создается автоматически при развертывании TorchServe в том же каталоге, где вы развернули его.
4. Остановите TorchServe
torchserve --stop
Тогда в следующий раз, когда вы развернете TorchServe, это займет меньше времени, чем в первый раз, если модели, которые будут использоваться на сервере, уже зарегистрированы/загружены, поскольку TorchServe сохраняет их в кэше в каталоге /tmp, поэтому ему не нужно будет загружать их снова, если ни название, ни версия не менялись. С другой стороны, если вы зарегистрируете новую модель, TorchServe придется ее загрузить, и это может занять немного больше времени в зависимости от характеристик вашей машины.
🐋 Docker
Чтобы воспроизвести развертывание TorchServe в образе Ubuntu Docker:
docker build -t ubuntu-torchserve:latest deployment/
docker run --rm --name torchserve_docker \
-p8080:8080 -p8081:8081 -p8082:8082 \
ubuntu-torchserve:latest \
torchserve --model-store <path_to_model_store> --models cats_n_dogs=cats_n_dogs_resnet50.mar
Для получения дополнительной информации о Docker можно ознакомиться с объяснениями TorchServe, по адресу pytorch/serve/docker, поскольку там также объясняется, как использовать их образ Docker (вместо чистого образа Ubuntu), а также некоторые советы относительно производственного развертывания модели, использующие TorchServe.
🧙♂️ Использование
Выполнив все описанные выше шаги, можно отправить образец запроса к развернутой модели, чтобы увидеть ее производительность и сделать выводы. В этом случае, поскольку проблема, с которой мы столкнулись, представляет собой проблему классификации изображений, мы будем использовать пример ниже, а затем отправим его в виде файла в теле HTTP-запроса:
wget https://github.com/yliasolom/cats_n_dogs/blob/main/cat_sample.jpeg
curl -X POST http://localhost:8080/predictions/cats_n_dogs -T cat_sample.jpeg
Note: выходные данные исходного вывода — это словарь с идентификатором каждого класса, а не имена классов. В этом случае, поскольку мы включили index_to_name.json в качестве дополнительного файла при создании MAR, TorchServe автоматически присваивает идентификаторы классу. имена, чтобы предсказание было более ясным.
📕 Вывод
TorchServe — это мощная платформа, разработанная PyTorch для простого, но последовательного обслуживания своих моделей, ее использование рекомендуется при обслуживании моделей машинного обучения в производственных средах, поскольку он полностью интегрирован с PyTorch.
В течение жизненного цикла MLOps при запуске моделей в производство вам не нужно будет создавать полный API с конкретной целью предоставить конечную точку для использования ваших моделей, поскольку это уже делается автоматически с помощью TorchServe.
В дополнение к API вывода. который может быть наиболее распространенным, вы также сможете получить доступ к API метрик и API управления, которые позволяют вам собирать как метрики системного уровня, так и пользовательские через регулярные промежутки времени, а также управлять своим сервером, а также моделями, которые вы используете. экспонирование и ресурсы сервера, назначенные каждой модели соответственно.
Это делает TorchServe по-настоящему согласованной средой обслуживания моделей, так что цикл, начиная с сохранения обученной модели, его обслуживание можно выполнить за несколько простых шагов, что делает MLOps для PyTorch проще, чем когда-либо.
🌟 Я очень ценю все последующие комментарии!🌟