Пошаговое руководство от начальной настройки среды до обслуживания нескольких версий модели и управления ими с помощью TensorFlow Serving и Docker.

Оглавление

  1. "Введение"
  2. Настройка среды
  3. Создание моделей машинного обучения
    3.1 Генерация данных
    3.2 Разделение обучения, проверка и набор тестов
    3.3 Обучение и сохранение моделей регрессии
  4. Обслуживание моделей
    4.1 Установка TensorFlow Serving с помощью Docker
    4.2 Обслуживание последней модели
    4.3 Обслуживание нескольких версий модели
    4.4 Применение пользовательских меток к версии модели
    4.5 Автоматическая перезагрузка конфигураций с течением времени
  5. "Заключение"
  6. "Использованная литература"

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/

[5] https://www.tensorflow.org/tfx/serving/docker

[6] https://www.tensorflow.org/tfx/serving/serving_config