Пошаговое руководство от начальной настройки среды до обслуживания нескольких версий модели и управления ими с помощью TensorFlow Serving и Docker.
Оглавление
- "Введение"
- Настройка среды
- Создание моделей машинного обучения
3.1 Генерация данных
3.2 Разделение обучения, проверка и набор тестов
3.3 Обучение и сохранение моделей регрессии - Обслуживание моделей
4.1 Установка TensorFlow Serving с помощью Docker
4.2 Обслуживание последней модели
4.3 Обслуживание нескольких версий модели
4.4 Применение пользовательских меток к версии модели
4.5 Автоматическая перезагрузка конфигураций с течением времени - "Заключение"
- "Использованная литература"
1. Введение
В этом посте описаны все шаги, необходимые для начала обслуживания моделей машинного обучения в качестве веб-сервисов с помощью TensorFlow Serving, гибкой и высокопроизводительной системы обслуживания¹.
В этом примере мы настроим виртуальную среду, в которой будем генерировать синтетические данные для задачи регрессии, обучать несколько моделей и, наконец, развертывать их как веб-службы, получая доступ к прогнозам из REST API.
Единственным предварительным условием для этого руководства является рабочий компьютер с установленными Python² и Docker Engine³. Наконец, мы будем использовать curl⁴ для написания вызовов API и использования моделей машинного обучения через их конечные точки прогнозирования.
2. Настройка среды
virtual environment
— это самосогласованная среда Python, которую можно создать для управления и разделения проектов: она обеспечивает изоляцию, чтобы зависимости не влияли на другие пакеты в той же операционной системе.
Для этого урока мы создадим virtual environment
внутри папки myProject
. Из командной строки:
# create the virtual environment python -m venv /myProject # activate the environment myProject\Scripts\activate
После активации среды мы можем установить необходимые зависимости:
pip install scikit-learn
использовать удобные методы подготовки данных;pip install tensorflow
для разработки машинного обучения;pip install matplotlib
для визуального изучения данных и показателей модели;pip install jupyter
пользоваться блокнотами.
После установки зависимостей мы запускаем Jupyter Notebook, выполнив:
jupyter notebook
В веб-интерфейсе Jupyter Notebook мы можем создать блокнот (create_models.ipynb
) в папке myProject
, так как мы будем использовать его для создания моделей машинного обучения, которые будут обслуживаться с помощью TensorFlow Serving.
3. Создавайте модели машинного обучения
Начиная с нашего блокнота, импортируем ранее установленные зависимости:
3.1 Генерация данных
Мы генерируем синтетические данные следующим образом:
3.2 Разделение поезда, проверка и набор тестов
Мы разделяем наш набор данных на:
- Наборы для обучения и проверки: используются во время процедуры обучения.
- Тестовый набор: используется для оценки производительности вне выборки.
Наблюдаем за полученными наборами:
Когда мы обучаем новую модель, мы хотим сохранить ее в подпапке корня нашего проекта с произвольным именем saved_models
. Внутри этого пространства мы будем сохранять каждую модель в выделенном каталоге с возрастающими целыми числами:
3.3 Обучайте и сохраняйте регрессионные модели
Мы подгоняем первую простую модель из плотного слоя:
Теперь давайте создадим еще одну немного другую модель:
Мы можем наблюдать прогнозы тестового набора для двух разных моделей:
Изучая содержимое папки ./myProject/saved_models
, мы можем наблюдать, как обученные модели сохраняются в специальных каталогах:
Наша конечная цель — изучить, как развернуть набор заданных моделей в качестве веб-сервисов для логического вывода с помощью TensorFlow Serving. Поэтому мы не будем углубляться в задачу моделирования, хотя можно протестировать разные модели или дополнительно улучшить стратегию обучения.
4. Подавайте модели
4.1 Установите TensorFlow Serving с помощью Docker
Самый простой способ начать работу с TensorFlow Serving — загрузить последний образ докера⁵. Из командной строки:
docker pull tensorflow/serving
После извлечения образа мы можем проверить его доступность, запустив:
docker images
4.2 Подавать последнюю модель
Создаем работающий контейнер из вытащенного образа:
docker run --name myTFServing -it -v C:\myProject:/myProject -p 9001:9001 --entrypoint /bin/bash tensorflow/serving
Давайте рассмотрим эту команду более подробно:
docker run
создает контейнер из входного изображения.--name <myName>
задает имя для идентификации контейнера Docker.-it
запускает контейнер в интерактивном режиме.-v <host_volume>:<container_volume>
привязывает том с хоста к каталогу внутри контейнера. В нашем случае контейнер будет обращаться к папке проектаC:\myProject
на хосте из каталога/myProject
внутри контейнера.-p <host_port>:<container_port>
привязывает порт хоста к порту контейнера.--entrypoint
указывает исполняемый файл, который должен запускаться при запуске контейнера. В нашем случае/bin/bash
.tensorflow/serving
— это имя образа, из которого создается контейнер.
Изнутри контейнера проверяем наличие папки /myProject
и ее содержимое, которое должно совпадать с C:\myProject
на хосте:
Пока мы находимся внутри контейнера, запускаем TensorFlow Serving следующим образом:
tensorflow_model_server --rest_api_port=9001 --model_name=regression_experiments --model_base_path=/myProject/saved_models
Заметим, что мы передаем папку, в которой модели хранились, во флаг model_base_path
, и указываем произвольное имя модели с model_name
. Это имя станет частью конечной точки, предоставляемой TensorFlow Serving.
После выполнения команды журналы предполагают, что для логического вывода загружается только последняя модель:
Мы можем проверить прогнозы, выполнив вызовы API с curl
из-за пределов контейнера. Например, мы начинаем с получения доступных моделей с помощью:
curl -X GET http:/localhost:9001/v1/models/regression_experiments
Этот вызов возвращает:
Действительно, TensorFlow Serving автоматически загружает по умолчанию только самые последние версии различных моделей, доступных в model_base_path.
Мы проверяем предсказание следующим образом:
curl -X POST "http://localhost:9001/v1/models/regression_experiments:predict" ^ -H "Content-Type: application/json" ^ -d "{\"instances\":[[1.0], [2.0], [5.0]]}"
Примечания
- На компьютере с Windows символ
^
можно использовать для новой строки в операторе curl. В системах MacOS или Unix вместо этого следует использовать символ обратной косой черты\
. - Может возникнуть соблазн использовать чередование двойных кавычек
"
и одинарных кавычек'
для написания оператора curl. Например, набрав:-d '{"instances":[..]}'
. В Windows это может привести к следующему сообщению:{"error":"Malformed request: POST /v1/models/regression_experiments/predict"}
или другим ошибкам синтаксического анализа curl/JSON. Чтобы избежать каких-либо проблем, команда должна содержать только двойные кавычки"
(замаскированные обратной косой чертой при вложенности).
4.3 Подавать несколько версий модели
В реальном сценарии нам может потребоваться выставить несколько моделей одновременно. Например, нам может понадобиться постепенно переключать трафик с предыдущей версии службы на новую (сине-зеленое развертывание) или нам может потребоваться случайным образом перенаправить пользователей на одну из нескольких сосуществующих версии для целей тестирования (A/B-тестирование).
Мы можем легко поручить TensorFlow Serving загрузить разные версии модели и сделать их доступными для вывода с помощью файлов конфигурации⁶.
Внутри папки myProject
мы создаем файл cfg1.conf
следующим образом:
model_config_list { config { name: 'regression_experiments' base_path: '/myProject/saved_models' model_platform: 'tensorflow' model_version_policy: {all: {}} } }
В этом файле мы устанавливаем политику, предписывающую TensorFlow Serving учитывать все доступные модели внутри заданного базового пути.
Запускаем TensorFlow Serving из контейнера следующим образом:
# entering the container in interactive mode docker exec -it myTFServing bin/bash # starting TensorFlow Serving with configuration file tensorflow_model_server --rest_api_port=9001 --allow_version_labels_for_unavailable_models --model_config_file=/myProject/cfg1.conf
Из сервисных логов видно, что теперь при запуске загружаются обе версии модели:
Проверим доступные модели GET-запросом извне контейнера:
curl -X GET http:/localhost:9001/v1/models/regression_experiments
Теперь мы можем выполнять внешние вызовы API к сервису и перенаправлять трафик по желанию на любую желаемую версию следующим образом:
# call to model version 1 curl -X POST "http://localhost:9001/v1/models/regression_experiments/versions/1:predict" ^ -H "Content-Type: application/json" ^ -d "{\"instances\":[[1.0], [2.0], [5.0]]}" # call to model version 2 curl -X POST "http://localhost:9001/v1/models/regression_experiments/versions/2:predict" ^ -H "Content-Type: application/json" ^ -d "{\"instances\":[[1.0], [2.0], [5.0]]}"
4.4 Применение пользовательских меток к версиям модели
Мы можем легко применить строковые метки к версиям модели⁶. Таким образом, можно добавить уровень «семантической абстракции» к нашей службе прогнозирования, улучшая читаемость и облегчая практики DevOps. Например, уровень интеграции, использующий наши модели через интерфейс REST, может предпочесть вызывать «производственную» или «тестовую» версию, а не случайное целое число, такое как «23» или «57».
Такого результата можно добиться, указав нужные метки в конфигурационном файле. Давайте создадим файл cfg2.conf
в каталоге проекта следующим образом:
model_config_list { config { name: 'regression_experiments' base_path: '/myProject/saved_models' model_platform: 'tensorflow' model_version_policy { specific { versions: 1 versions: 2 } } version_labels { key: 'production' value: 1 } version_labels { key: 'test' value: 2 } } }
В этом файле мы присвоили версиям наших моделей метки production
и test
соответственно. Теперь мы можем запустить службу:
# entering the container in interactive mode docker exec -it myTFServing bin/bash # starting TensorFlow Serving with configuration file tensorflow_model_server --rest_api_port=9001 --allow_version_labels_for_unavailable_models --model_config_file=/myProject/cfg2.conf
После запуска службы мы можем выполнять внешние вызовы API. Примечательно, что на этот раз конечная точка будет /v1/models/<model_name>/labels/
вместо /v1/models/<model_name>/versions/
:
# call to production model curl -X POST "http://localhost:9001/v1/models/regression_experiments/labels/production:predict" ^ -H "Content-Type: application/json" ^ -d "{\"instances\":[[1.0], [2.0], [5.0]]}" # call to test model curl -X POST "http://localhost:9001/v1/models/regression_experiments/labels/test:predict" ^ -H "Content-Type: application/json" ^ -d "{\"instances\":[[1.0], [2.0], [5.0]]}"
4.5 Автоматически перезагружать конфигурации с течением времени
Мы использовали файлы конфигурации, передав их флагу --model_config_file
при запуске.
Мы также можем передать флаг --model_config_file_poll_wait_seconds
, чтобы поручить TensorFlow Serving периодически проверять наличие обновлений в файлах конфигурации по указанному пути. Например, заявление
# entering the container in interactive mode docker exec -it myTFServing bin/bash # starting TensorFlow Serving tensorflow_model_server --rest_api_port=9001 --allow_version_labels_for_unavailable_models --model_config_file=/myProject/cfg2.conf --model_config_file_poll_wait_seconds=30
запустит службу внутри контейнера myTFServing
на основе конфигураций из файла cfg2.conf
, и периодически будут получаться обновления. Мы можем проверить из журналов, как система каждые 30 секунд проверяет наличие обновлений:
5. Вывод
В этом посте мы рассмотрели, как развертывать модели с помощью TensorFlow Serving, делая прогнозы легко доступными через REST API.
В частности, мы начали с нуля. Мы создали виртуальную среду, в которую установили минимальный набор зависимостей, необходимых для генерации синтетических данных и соответствия ряду моделей. Затем мы вытащили образ TensorFlow Serving Docker и создали из него работающий контейнер, охватывающий все шаги, необходимые для управления и обслуживания нескольких версий модели.
6. Ссылки
[1] https://www.tensorflow.org/tfx/serving/architecture
[2] https://docs.python.org/3/using/
[3] https://docs.docker.com/engine/install/
[4] https://curl.se/