Улучшение наблюдаемости вашей системы искусственного интеллекта
Одна из лучших вех на пути каждого создателя ИИ — это день, когда модель готова пройти обучение и быть развернутой в рабочей среде. Согласно недавнему опросу, проведенному Algorithmia, большинство организаций уже имеют более 25 моделей в производстве. Это подчеркивает, что предприятия все чаще полагаются на машинное обучение для повышения производительности за пределами лаборатории. Однако фаза после развертывания может быть сложной для вашей модели машинного обучения. Специалисты по обработке и анализу данных могут думать, что после развертывания модели самое сложное позади, но на самом деле проблемы только начинаются. Ошибки данных, неработающие конвейеры и снижение производительности модели обязательно возникнут в один прекрасный день, и когда этот день наступит, мы должны быть готовы к эффективной отладке и устранению этих проблем. Чтобы иметь надежную и надежную систему машинного обучения, абсолютно необходима наблюдаемость.
В этой статье я хотел бы поделиться подходом к тому, как улучшить наблюдаемость вашего приложения машинного обучения за счет эффективного ведения журнала и мониторинга ваших моделей. Для демонстрации мы развернем приложение Flask для распознавания образов на основе известного набора данных Iris. Что касается мониторинга, мы изучим бесплатную начальную версию платформы Observability WhyLabs, чтобы настроить собственную панель мониторинга моделей. С панели управления у нас будет доступ ко всей статистике, показателям и данным о производительности, собранным из каждой части нашего конвейера машинного обучения. Для взаимодействия с платформой мы будем использовать whylogs — библиотеку регистрации данных с открытым исходным кодом, разработанную WhyLabs.
Одним из ключевых случаев использования панели мониторинга является неожиданное изменение качества и/или согласованности наших данных. В связи с этим мы моделируем один из наиболее распространенных сценариев сбоя модели — дрейф признаков, что означает изменение распределения наших входных данных. Затем мы используем панель мониторинга, чтобы увидеть, как такого рода проблемы могут быть обнаружены и отлажены. Хотя дрейф функций может повлиять или не повлиять на производительность вашей модели, наблюдение такого рода изменений в производстве всегда должно быть причиной для дальнейшего изучения и, возможно, переобучения модели.
Таким образом, мы рассмотрим пошаговый путь к:
- Разверните API Flask, интегрированный с WhyLabs
- Протестируйте приложение
- Внедрить Feature Drift и исследовать панель управления моделью
Если это проблема, которая находит отклик у вас, мы сделали полный код для этого руководства доступным здесь, чтобы вы могли использовать его повторно. Вам нужно будет скопировать его на свой компьютер, чтобы следовать этому примеру. Вам также понадобится Docker и, желательно, инструмент управления средой Python, такой как Conda или pipenv. Для тех, кто заинтересован в деталях, мы включили очень подробное описание и Jupyter Notebook в качестве руководства.
1. Обзор
Давайте посмотрим, как различные компоненты нашей системы взаимодействуют друг с другом.
Мы развернем локально приложение Flask, которое отвечает за предоставление пользователю запрошенных прогнозов через конечную точку REST. Наше приложение также будет использовать библиотеку Whylogs для создания статистических профилей как входных, так и выходных функций нашего приложения во время производства. Затем эти статистические свойства будут отправляться микропакетами в WhyLabs через фиксированные интервалы времени. WhyLabs автоматически объединяет их, ежедневно создавая статистические профили.
Существуют различные способы загрузки зарегистрированных метрик на платформу. В этом примере мы периодически загружаем их микропакетами, как показано на диаграмме. Другой вариант — загружать их на каждом шаге журнала.
2. Настройка учетной записи WhyLabs
Чтобы отслеживать наше приложение, давайте сначала настроим учетную запись WhyLabs. В частности, нам понадобятся две части информации:
- токен API
- Идентификатор организации
Перейдите на https://whylabs.ai/free и получите бесплатную учетную запись. Вы можете следовать примерам, если хотите, но если вас интересует только эта демонстрация, вы можете пропустить инструкции по быстрому запуску.
После этого вам будет предложено создать токен API, который вы будете использовать для взаимодействия со своей панелью управления. Создав токен, скопируйте его и сохраните в надежном месте. Второй важной информацией здесь является идентификатор вашей организации. Обратите внимание и на это. WhyLabs дает вам пример кода того, как создать сеанс и отправить данные на вашу панель управления. Вы также можете протестировать его и проверить, проходят ли данные. В противном случае, после того как вы получите токен API и идентификатор организации, вы можете просто перейти на https://hub.whylabsapp.com/models, чтобы увидеть панель управления вашей новой модели. Чтобы перейти к этому шагу, мы использовали Документацию по API WhyLabs, которая также предоставляет дополнительную информацию о создании токена и основные примеры его использования.
3. Развертывание приложения Flask
После того, как панель мониторинга настроена и запущена, мы можем приступить к развертыванию самого приложения. Мы будем обслуживать приложение Flask с Gunicorn, упакованным в контейнер Docker для облегчения развертывания.
Конфигурация WhyLabs
Первым шагом будет настройка подключения к WhyLabs. В этом примере мы делаем это через файл .whylogs_flask.yaml
. Средство записи может быть настроено либо на вывод данных локально, либо в разные места, например, S3, путь MLFlow или непосредственно в WhyLabs. В этом файле мы также зададим имя проекта и другую дополнительную информацию.
Переменные среды
Приложение предполагает наличие набора переменных, поэтому мы определим их в файле .env
. Они загружаются позже с помощью библиотеки dotenv. Скопируйте содержимое ниже и замените значения WHYLABS_API_KEY
и WHYLABS_DEFAULT_ORG_ID
на те, которые вы получили при создании учетной записи WhyLabs. Вы можете оставить другие переменные как есть.
Давайте поговорим о некоторых других существующих переменных.
- WHYLABS_DEFAULT_DATASET_ID — идентификатор вашего набора данных. Модель-1 — это значение по умолчанию, которое создается автоматически после создания учетной записи. Оставьте его без изменений, если вы еще ничего не отправляли в WhyLabs. Но если он уже заполнен, вы можете изменить его на модель-2. Только не забудьте настроить новую модель в https://hub.whylabsapp.com/models. Вновь созданной модели будет присвоен новый идентификатор модели, и вы сможете использовать его в своем файле .env.
- ROTATION_TIME — период, используемый для отправки данных в WhyLabs. В реальных приложениях нам могут не понадобиться такие частые обновления, но для этого примера мы установили низкое значение, чтобы нам не приходилось так долго ждать, чтобы убедиться, что оно работает.
Создание среды
Приложение будет запускаться из контейнера Docker, но мы также запустим некоторые предварительные сценарии (для загрузки данных и обучения модели) и пост-скрипты (для отправки запросов), поэтому давайте создадим среду для этого руководства. . Если вы используете Conda, вы можете создать его из файла конфигурации environment.yml
:
conda env create -f environment.yml
Если это не сработает, как ожидалось, вы также можете создать среду с нуля:
conda create -n whylogs-flask python=3.7.11 conda activate whylogs-flask
А затем установить прямо из требований:
python -m pip install -r requirements.txt
Обучение модели
Если вы посмотрите внимательно, одна из наших переменных окружения называется MODEL_PATH
. У нас еще нет модели, поэтому давайте создадим ее. Мы будем использовать sklearn для обучения простой модели классификации SVC из набора данных Iris и сохраним ее как model.joblib
. Из корня папки нашего примера мы можем просто вызвать тренировку:
python train.py
Создание образа Docker
Теперь у нас есть все, чтобы запустить наше приложение. Чтобы создать образ, мы определяем Dockerfile ниже:
А затем соберите образ и запустите наш контейнер:
docker build --build-arg PYTHON_VERSION=3.7 -t whylabs-flask:latest . docker run --rm -p 5000:5000 -v $(pwd):/app whylabs-flask
Это запустит наше приложение локально на порту 5000. В этом примере мы запускаем наше приложение Flask как HTTP-сервер WSGI с Gunicorn. Установив переменную reload
, мы можем более эффективно выполнять отладку, автоматически перезагружая рабочие процессы при изменении кода.
Вы должны увидеть сообщение от gunicorn, запускающего сервер:
[2021-10-12 17:53:01 +0000] [1] [INFO] Starting gunicorn 20.1.0 [2021-10-12 17:53:01 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1) [2021-10-12 17:53:01 +0000] [1] [INFO] Using worker: sync [2021-10-12 17:53:01 +0000] [8] [INFO] Booting worker with pid: 8 [2021-10-12 17:53:01 +0000] [20] [INFO] Booting worker with pid: 20
4. Тестирование API
После запуска контейнера Docker мы должны проверить, работает ли API. Приложение имеет две конечные точки:
- /api/v1/health: возвращает статус 200, если API запущен и работает.
- /api/v1/predict: возвращает прогнозируемый класс с учетом входного вектора признаков.
API надлежащим образом задокументирован Swagger, поэтому вы можете перейти по адресу http:127.0.0.1:5000/apidocs, чтобы изучить документацию:
В /apidocs вы сможете увидеть примеры запросов, чтобы опробовать обе конечные точки, а также фрагменты кода curl, например:
curl -X GET "http://127.0.0.1:5000/api/v1/health" -H "accept: application/json" curl -X POST "http://127.0.0.1:5000/api/v1/predict" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"petal_length_cm\": 0, \"petal_width_cm\": 0, \"sepal_length_cm\": 0, \"sepal_width_cm\": 0}"
Вы должны получить «здоровый» ответ от первой команды. Аналогично, ответ на запрос прогноза должен быть:
{ "data": { "class": "Iris-virginica" }, "message": "Success" }
Хорошо, наше приложение правильно обслуживает наши запросы. Теперь мы можем просто проверить, доходят ли данные до нашей информационной панели в целости и сохранности.
Важно помнить, что данные не отправляются сразу, вместе с каждым выполненным запросом. Он отправляется периодически, в соответствии с переменной окружения ROTATION_TIME
, определенной в файле .env
. В этом примере было установлено значение 5 минут, что означает, что нам придется подождать 5 минут, прежде чем информация будет отправлена на нашу панель управления. Затем мы должны увидеть сообщение от Whylogs о том, что загрузка завершена.
После завершения загрузки полученная информация должна быть доступна на панели управления вашей модели в течение нескольких минут. На панели управления вашей модели вы можете проверить, был ли зарегистрирован какой-либо профиль, и получить доступ к панели управления вашей сводки:
На данный момент у нас зарегистрирован 1 профиль и 5 функций, что означает, что данные проходят. Теперь давайте еще немного изучим платформу на примере использования: мы добавим несколько выбросов в наше распределение данных и посмотрим, как это отразится на нашей информационной панели.
5. Обнаружение дрейфа признаков
Реальная ценность любой платформы для наблюдения проявляется, когда что-то идет не так. Что-то может пойти не так по-разному, но для этой демонстрации давайте выберем конкретный: дрейф функций.
Явление дрейфа в контексте машинного обучения может быть длинной темой, поэтому в этом случае мы ограничимся основным определением дрейфа признаков: когда происходит изменение распределения входных данных модели.
Мы будем использовать набор из 150 неизмененных образцов из набора данных Iris, чтобы представить нормальное распределение ежедневной партии. Затем, чтобы представить аномальную партию, мы возьмем тот же набор выборок, за исключением того, что мы заменим 30 из этих выборок для случайных выбросов одной случайной входной функцией. Мы продолжим запрашивать прогнозы с входными функциями следующим образом:
- День 1 – обычные данные
- День 2 — измененные данные (измененное распределение)
- День 3 — нормальные данные
Фрагмент кода ниже сделает 150 запросов с неизмененными входными функциями. На второй день мы просто меняем код, чтобы передать data_mod
в качестве полезной нагрузки вместо data
(строка 35) и повторяем процесс. Для этой демонстрации выбросы были добавлены к функции sepal_width
.
Давайте кратко рассмотрим некоторые разделы нашей панели инструментов. На странице входные данные содержится много полезной информации, например количество записей в каждом пакете, нулевая доля и предполагаемый тип объекта.
Одной из особенно полезных сведений является Расстояние распространения. Это временной ряд, который показывает среднее статистическое расстояние объекта от предыдущих пакетов данных за выбранный диапазон дат с использованием Расстояния Хеллингера для оценки расстояний между распределениями. Добавляя выбросы в признак sepal_width
, мы видим изменение расстояния распределения не только для самого признака sepal_width
, но и в результатах прогнозирования.
Примечание. Для остальных объектов расстояние, похоже, увеличилось за последний день. На самом деле это была ошибка с моей стороны, так как я отправил 1 дополнительную запись, всего 151 запись. Поскольку графики не в масштабе между признаками, эффект от этого изменения кажется высоким, но при проверке самих значений дополнительная запись дала расстояние распределения 0,02.
Мы можем дополнительно изучить отдельные функции, щелкнув по ним. На графиках распределения мы можем видеть влияние дрейфа на функции class
и sepal_width
.
В разделе profiles мы можем выбрать до 3 профилей наборов данных для сравнения, что очень удобно. На изображении ниже я выбрал несколько функций в каждом профиле для сравнения. Как и ранее, изменения, вызванные добавлением выбросов, также очень очевидны.
Хотя мы не сможем обсуждать здесь все доступные функции, некоторые из моих любимых:
- Ручная настройка порогов для каждого функционального монитора
- Планирование уведомлений для электронной почты/Slack
- Загрузка тренировочного набора в качестве базового эталонного набора
- Сегментировать данные во время профилирования
Не стесняйтесь исследовать их самостоятельно!
6. Заключение
Этап после развертывания приложений машинного обучения ставит перед нами бесчисленные проблемы, и процесс устранения неполадок в этих приложениях по-прежнему может быть очень ручным и громоздким. В этом посте мы рассмотрели пример того, как облегчить это бремя, улучшив наблюдаемость нашей системы с помощью WhyLabs.
Мы рассмотрели простой пример развертывания приложения Flask для классификации на основе известного набора данных Iris и интегрировали его с платформой WhyLabs с помощью библиотеки регистрации данных Whylogs. Мы также смоделировали сценарий Feature Drift, внедрив выбросы в наши входные данные, чтобы увидеть, как это отражается на нашей панели мониторинга. Несмотря на то, что это очень простой вариант использования, этот пример можно легко адаптировать для более специализированных сценариев.
Спасибо за чтение, и не стесняйтесь обращаться, если у вас есть какие-либо вопросы / предложения! Если вы попробуете это и у вас возникнут вопросы, я нашел Сообщество WhyLabs в Slack очень полезным и отзывчивым.