Введение

Люди говорят, что самое лучшее в Python — это обилие его библиотек с открытым исходным кодом. Позволю себе не согласиться.

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

Прямо сейчас это касается операций машинного обучения (MLOPs). В последние годы это стало настолько важной областью, что сообщество Python блестяще воспользовалось случаем, создав как можно больше инструментов и библиотек для выполнения дисциплин MLOps.

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

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

Возьмем в качестве примера развертывание моделей как API (тема этой статьи). Какой набор инструментов вы бы выбрали для выполнения работы?

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

Как преобразовать модель в адрес HTTPS, чтобы пользователи могли отправлять запросы? Есть так много вариантов, таких как Flask, Django, FastAPI и т. д.

Даже после выбора фреймворка получить его онлайн непросто. Используете ли вы AWS, Heroku, GCP или десятки других, которые фактически утверждают, что предлагают единственный лучший способ сделать это?

Чтобы избавить вас от необходимости отвечать на все эти вопросы, в этой статье я представлю решение, которое должно быть довольно простым и беспроблемным по сравнению с другими альтернативами. Вам нужно будет знать только scikit-learn и xgboost; остальным я научу.

В итоге построим этот API:

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



Получите лучшие и последние статьи по машинному обучению и искусственному интеллекту, выбранные и обобщенные с помощью мощного искусственного интеллекта — альфа-сигнала:



Стек, который мы будем использовать

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

  • Pandas, NumPy — пояснений не требуется.
  • Sklearn и XGBoost — модель обучения. Они выбраны только для иллюстрации, и инструкции будут работать на моделях из любого другого фреймворка.
  • BentoML — упаковка обученной модели в локальный API (подробно будет объяснено позже)
  • bentoctl — инструмент командной строки, позволяющий создавать образы Docker и сохранять их в облачном формате с помощью одной команды.
  • Terraform — еще один CLI-инструмент для управления облачной инфраструктурой. Он заботится о создании ресурсов и функций и размещении в них контейнеров, не посещая полмиллиона страниц.
  • AWS — самая популярная, надежная и гибкая облачная платформа (можно подтвердить через Google Trends).
  • AWS Lambda — запуск кода в бессерверном облаке — высокая масштабируемость и удобство.

Итак, без лишних слов, приступим.

Что такое BentoML и его цель?

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

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

BentoML был создан, чтобы решить эти проблемы и максимально упростить и ускорить развертывание в рабочей среде. В следующих разделах вы увидите, как BentoML упрощает выполнение утомительных операций MLOps. Вот примеры:

  • Сохранение любой модели любого фреймворка в едином формате для облегчения совместной работы.
  • Создайте конечную точку HTTP API с одной функцией Python для более быстрой итерации.
  • Контейнеризируйте все, что нужно модели, с помощью Docker с помощью одной команды CLI.

Прочтите документы здесь, чтобы узнать больше об этом, или продолжите чтение.

Подготовка набора данных и обучение модели

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

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

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

Мы создаем простой набор данных с семью функциями и 10 000 образцов с целью бинарной классификации.

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

Сохранение обученных моделей в формате BentoML

Сохранение обученной модели в формате, совместимом с BentoML, выполняется вызовом специфичной для фреймворка команды save:

Возвращаемый объект является экземпляром класса BentoML Model с меткой, называемой тегом.

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

BentoML поддерживает почти все основные фреймворки машинного обучения:

  • Классика: Sklearn, XGBoost, CatBoost, LightGBM
  • Глубокое обучение: TensorFlow, PyTorch, PyTorch Lightning, Keras, Transformers
  • Другие: ONNX, MLFlow, fast.ai, statsmodels, spaCy, h2o, Gluon и др.

У каждого из фреймворков есть соответствующая команда bentoml.framework.save_model.

Когда модель сохраняется, она помещается в локальный каталог, называемый хранилищем моделей BentoML. Из последнего вывода (параметр path) мы увидели, что хранилище моей модели находится в /home/bexgboost/bentoml/models. Вы можете увидеть список всех своих моделей, вызвав команду bentoml models list в терминале:

Вы также можете увидеть модели из других моих проектов.

Примечание. В документах BentoML и в этой статье имена «модель» и «тег» взаимозаменяемы для обозначения сохраненных моделей в хранилище моделей.

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

Выше мы сохраняем нашу модель XGBoost с дополнительными данными, такими как автор (я), оценки важности функций, которые вы можете получить с помощью booster.get_score и фиктивной метрики.

Делимся моделями

Модели в магазине моделей BentoML можно использовать как отдельные архивы с помощью команды bentoml models export:

Если вы не знаете точную строку версии вашего тега, вы можете использовать суффикс ':latest', чтобы выбрать самую последнюю версию. С помощью приведенной выше команды мы экспортируем классификатор в архив .bentomodel в каталог models. Когда товарищ по команде отправляет вам архив .bentomodel, вы можете использовать команду import, чтобы отправить его в ваш локальный магазин моделей BentoML:

Получение сохраненных моделей

Существует несколько способов загрузки сохраненных моделей из хранилища моделей в вашу среду. Самая простая — это функция load_model. Как и save_model, load_model также зависит от фреймворка:

Функция загрузит модель в том же формате, в котором она была до сохранения, что означает, что вы можете использовать ее собственные методы, такие как predict:

Чтобы загрузить модель как объект BentoML Model, вы можете использовать команду models.get, которая НЕ зависит от платформы:

tag = bentoml.models.get("xgb_custom:latest")

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

Последний и самый важный способ получения моделей — загрузить их как бегунов:

Бегуны — это специальные объекты BentoML, которые оптимизированы для наиболее эффективного использования системных ресурсов на основе их фреймворка. Бегуны — это основные компоненты API, которые мы создадим в следующем разделе.

Теперь мы готовы приступить к созданию API!



Организовать в сценарии

До сих пор мы использовали ноутбуки. Нам нужно переключиться на сценарии Python для создания службы API. Давайте организуем код предыдущих разделов. В файле generate_data.py создайте функцию, которая сохраняет синтетические данные из раздела «Подготовка набора данных»:

Полный скрипт generate_data.py можно найти здесь.

В файле train.py создайте функцию, которая обучает наш классификатор XGBoost и сохраняет его в хранилище моделей BentoML:

Полный скрипт train.py можно найти здесь.

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

Создание скрипта службы API

Теперь пришло время создать локальный API. Для этого нам понадобится всего лишь простой скрипт, который начинается, как показано ниже:

После загрузки нашей модели с models.get в качестве бегуна мы создаем объект с именем svc. Это будет экземпляр объекта BentoML Service. Service — это высокоуровневый класс, абстрактно представляющий наш API.

Мы добавляем одну конечную точку с именем classify в объект службы, создавая функцию с тем же именем:

Давайте разберем приведенный выше фрагмент построчно.

Во-первых, мы импортируем новый класс с именем NumpyNdarray из bentoml.io — модуля ввода/вывода. Для стандартизации ввода и вывода BentoML предлагает несколько классов, таких как NumpyNdarray, таких как Text, File, Image, PandasDataFrame и т. д.

Добавление этих классов к аргументам input и output декоратора svc.api гарантирует, что правильные типы данных передаются в конечную точку нашего API. В нашем случае мы следим за тем, чтобы данные, передаваемые нашей функции classify, всегда были массивом NumPy.

Если бы мы работали с моделями изображений, наш входной класс мог бы быть классом File или Image, а выходной снова был бы NumpyNdarray.

Внутри функции мы используем метод predict.run нашего бегуна, чтобы получить прогноз на входе. Метод вызывает метод predict объекта бустера XGBoost под капотом.

Вот как скрипт выглядит в итоге:

Вот и все! Используя bentoml serve, мы можем создать локальный сервер отладки:

$ bentoml serve service.py:svc --reload

Важно: переменные service.py и svc в приведенной выше команде изменяются в зависимости от имени вашего скрипта и имени объекта службы. Если бы у вас был объект службы с именем api в сценарии с именем api.py, команда была бы bentoml serve api.py:api --reload. Теги --reload гарантируют, что BentoML обнаружит изменения, внесенные в ваш сценарий, без необходимости перезапуска сервера.

Вот пример вывода команды:

GIF показывает, что API работает локально по адресу http://127.0.0.1:3000:.

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

Ура! Наш API работает — он классифицирует данный образец как первый класс.

Создание бенто

Теперь мы упаковываем наш API в Bento.

Bento — это термин, введенный BentoML, который относится к архиву, содержащему все необходимое для работы нашего API — в унифицированном формате. Внутри Bento будут инструкции по сборке образа Docker и зависимости нашей модели API.

Мы начинаем сборку Bento с создания файла bentofile.yaml (имя должно быть таким же) на том же уровне каталога, что и наши скрипты. Это будет выглядеть следующим образом:

Поле include используется для перечисления всех скриптов, необходимых для запуска нашего Bento. В нашем случае мы просто добавляем все скрипты Python. Далее идет поле packages, в котором должны быть перечислены зависимости и их версии.

В больших проектах сложно отслеживать все зависимости и их версии, поэтому вы можете использовать библиотеку pipreqs для создания файла requirements.txt для вашего проекта:

$ pip install pipreqs
$ pipreqs --force .  # --force overrides existing req file

Затем вы можете скопировать зависимости в файл bentofile.yaml.

После того, как у вас будет готов bentofile.yaml, вызываем команду build и указываем путь к нашему bentofile.yaml, который в нашем случае является корнем проекта (.):

$ bentoml build .

В случае успеха вы увидите вывод, как показано ниже:

Вы также можете проверить Bento, запустив bentoml list в CLI:

Как видите, в моей системе три Bentos, два из которых относятся к текущему проекту. Наличие готового Bento означает, что мы готовы развернуть его в Интернете.

Настройка учетных данных AWS

Поскольку мы развертываем наш API как функцию AWS Lambda, мы должны настроить свои учетные данные AWS. Лучший способ сделать это через CLI.

Сначала перейдите в свою консоль AWS IAM и найдите свои учетные данные. Обычно он доступен через кнопку Управление ключами доступа:

Нажмите на нее, и вы попадете сюда:

Создайте новый набор ключей или загрузите существующий. Затем перейдите в свой терминал и выполните следующие команды:

Для Linux или OSX:

Для Windows:

Это настроит ваши учетные данные AWS ТОЛЬКО ДЛЯ ТЕКУЩЕЙ виртуальной среды.

Развертывание Bento на AWS Lambda

Чтобы развернуть наш Bento, мы будем использовать собственный пакет командной строки BentoML под названием bentoctl. Установите его с пакетом boto3 (для зависимостей AWS) и установите оператор aws-lambda. Затем позвоните по номеру bentoctl init:

$ pip install bentoctl boto3
$ bentoctl operator install aws-lambda
$ bentoctl init

Команда задаст вам несколько вопросов. Вам нужно только указать имя для развертывания — xgb_classifier. Остальные можно оставить по умолчанию.

Инструкции по развертыванию взяты здесь на bentoctl docs.

Будут созданы три файла — deployment_config.yaml, bentoctl.tfvars и main.tf. Им понравится ниже:

Теперь мы установим другой инструмент под названием terraform. Terraform упрощает создание облачных ресурсов и управление ими прямо из интерфейса командной строки. Он будет использовать три вышеуказанных файла, в основном файл main.tf, в котором перечислены все детали нашей будущей функции AWS Lambda.

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

$ terraform -h

Если он напечатает список команд, установка прошла успешно.

После этого мы создаем образ Docker, совместимый с AWS Lambda, с помощью команды bentoctl build:

$ bentoctl build -b xgb_classifier:latest -f deployment_config.yaml

Мы добавляем имя и версию нашего Bento и указываем спецификации сборки через файл deployment_config.yaml. Процесс должен выглядеть следующим образом:

Если вы получаете botocore.exceptions.ClientError, учетные данные AWS настроены неправильно. Вернитесь к этому шагу снова.

Если образ создан успешно, вы должны увидеть вывод, подобный приведенному ниже:

Наконец, мы используем Terraform для отправки изображения в функцию AWS Lambda. Используйте следующие команды:

$ terraform init
$ terraform apply -var-file=bentoctl.tfvars -auto-approve

В конце вы увидите следующее сообщение, в котором показан URL-адрес нашего развернутого API Lambda:

Отображение пользовательского интерфейса займет некоторое время, но после этого документы API будут видны при нажатии на ссылку:

При первом запуске ссылка покажет сообщение о внутренней ошибке сервера. Игнорируй это.

Но он сразу будет доступен для отправки запросов и получения прогнозов:

Заключение

Фу! Это было много шагов, учитывая, что я сказал, что статья будет простой в начале. Но, поскольку у нас на руках готовое решение для машинного обучения, оно того стоило.

Развертывание моделей в виде API — один из лучших способов дать пользователям возможность взаимодействовать с вашей моделью. Берите пример с таких известных сервисов, как Dalle-E или GPT-3. Обе модели представляют собой массивные модели, представленные с помощью простого API и размещенные на веб-сайте. Используя методы, описанные в этой статье, вы можете создавать такие же продукты, хотя поначалу они, вероятно, не будут моделями с миллиардом параметров.

Спасибо за чтение!





Еще истории от меня…