Научитесь использовать Tensorflow Serving для создания веб-сервиса для обслуживания вашей модели Tensorflow.

Это вторая часть серии блогов, посвященных обучению модели Tensorflow, обслуживанию Tensorflow и его производительности. «В предыдущем посте мы использовали объектно-ориентированный подход для обучения модели классификатора изображений и экспортировали ее как SavedModel. Я рекомендую просмотреть его перед этим постом, так как мы собираемся использовать одну и ту же модель. Вы можете найти полные коды приложений для серии блогов здесь:



Что такое обслуживание Tensorflow?

Существует множество альтернативных способов использования моделей Tensorflow в приложениях. Одним из самых простых является использование Tensorflow вместе с фреймворками Flask, Django, Fastapi и т. д. для создания веб-приложения на основе Python. Фреймворки вроде ML.NET или deeplearning4j можно использовать, если требуется разработка на других языках. Tensorflow Lite, Pytorch Live и CoreML — это платформы для мобильных приложений. Однако в многоуровневых архитектурах и микросервисах рекомендуется делать модели машинного обучения автономными приложениями. Эта концепция называется обслуживание модели, и обслуживание модели как услуги имеет много преимуществ. Например, модели можно обновлять в производстве без простоев или использовать множество различных клиентских приложений. Для обслуживания моделей можно использовать такие приложения, как Tensorflow Serving, TorchServe, Triton, KFServing.

Tensorflow Serving позволяет нам обслуживать модели Tensorflow в качестве веб-сервисов без необходимости в дополнительном приложении. Он поддерживает обслуживание нескольких версий нескольких моделей через протоколы gRPC и REST. Однако для этого требуется, чтобы модели были в формате SavedModel Tensorflow. Сохраненные модели открыты для тонкой настройки и некоторых модификаций после обучения, особенно если они созданы с использованием Keras. Дополнительные функции и подписи могут быть добавлены в SavedModels, а затем обслуживаться с помощью TFServing.

Изучите сохраненную модель

Мы обучили модель ResNet50 в предыдущем среднем посте и сохранили ее в формате SaveModel. Мы можем использовать эту команду, чтобы показать сигнатуры моделей, которые будут обслуживаться Tensorflow Serving: saved_model_cli show --all --dir model_path

signature_def['serving_bytes']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['image_bytes_string'] tensor_info:
        dtype: DT_STRING
        shape: unknown_rank
        name: serving_bytes_image_bytes_string:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['output_0'] tensor_info:
        dtype: DT_FLOAT
        shape: (1, 10)
        name: StatefulPartitionedCall:0
  Method name is: tensorflow/serving/predict

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['input_tensor'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, -1, -1, 3)
        name: serving_default_input_tensor:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['output_0'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 10)
        name: StatefulPartitionedCall_1:0
  Method name is: tensorflow/serving/predict

Из вывода видно, что signalserving_default принимает ввод массива 4d, тогда как serving_bytes принимает ввод массива в кодировке base64 (в виде строки). Обе подписи выводят массив с 10 числами (вероятностями), так как модель обучена на MNIST и имеет 10 классов.

Запуск обслуживания Tensorflow

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

Приведенный ниже скрипт создает и запускает контейнер Tensorflow Serving с заданной моделью. Порт 8500 используется для gRPC API, а 8501 — для REST API. Этот скрипт привязывает каталог модели на хосте к контейнеру и считывает модель оттуда. Однако при использовании Tensorflow Serving в производственных средах рекомендуется размещать модели в образах Docker вместо использования привязок.

docker run -p 8500:8500 -p 8501:8501 -d --name resnet_serving \
  -v /directory/on/host/models:/models \
  -e MODEL_NAME=ResnetModel tensorflow/serving:2.8.0-gpu

Чтобы проверить, правильно ли он работает, перейдите по этому адресу в веб-браузере: http://hostname:8501/v1/models/ResnetModel. Он возвращает json, как показано ниже, если он работает правильно:

{
 "model_version_status": [
  {
   "version": "1",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

Использование службы REST

И протоколы REST, и gRPC имеют свои преимущества и недостатки. Вероятно, наиболее важным из них является то, что протокол REST более распространен.

Чтобы вызвать модель с помощью REST API, отправьте POST-запрос на http://hostname:8501/v1/models/ResnetModel:predict с таким телом запроса:

{
  "signature_name": "serving_bytes", 
  "instances": [{"b64": "fill_with_base64_encoded_image_bytes"}]
}

Поскольку модель обучается на наборе данных MNIST, содержащем рукописные цифры от 0 до 9, сервис возвращает активации без применения softmax для 10 классов. В приведенном ниже примере прогнозом модели будет класс с наивысшим значением активации, 3-й индекс (принадлежащий номеру 2):

{"predictions": [[-14.9772987, -6.99252939, 13.5781298, -8.89471, -6.88773823, -4.63609457, 0.168618962, -9.86182785, -2.09211802, -1.32305372]]}

Тот же результат можно получить, вызвав serving_defaultsignature со значениями пикселей RGB. Эта подпись поддерживает одновременную обработку нескольких изображений, поскольку она имеет 4-мерный ввод (пакет, высота, ширина, канал):

{
  "signature_name": "serving_default", 
  "instances": [[[[0, 0, 0], [0, 0, 0], [255, 255, 255], ...]
}

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

Использование службы gRPC

Использование gRPC Tensorflow Serving API официально поддерживается только для Python. Есть несколько клиентов с открытым исходным кодом для других языков, но они могут быть недоступны для последних версий Tensorflow Serving. Для Python должен быть установлен tensorflow-serving-api: pip install tensorflow-serving-api. Сервисная заглушка с незащищенным соединением (отметьте здесь для безопасного соединения) создается ниже:

Прогнозы для serving_defaultsignature можно сделать с помощью заглушки, определенной выше:

Методы tf.make_tensor_proto и tf.make_ndarray используются для преобразования массива numpy в/из тензора. В одном запросе serving_default можно отправить несколько изображений для получения более быстрых результатов. Для относительно больших изображений (например, 600x600px) можно использовать serving_bytessignature для получения более быстрых результатов:

Заключение

Мы использовали Tensorflow Serving для создания REST и gRPC API для двух сигнатур нашей модели классификации изображений. REST API прост в использовании и работает быстрее при использовании массивов байтов base64 вместо целочисленных массивов. Для использования gRPC API необходимо использовать внешние платформы. Однако это происходит быстрее при отправке нескольких изображений в виде пустых массивов.

Пожалуйста, проверьте репозиторий GitHub для получения полного кода. Не стесняйтесь задавать любые вопросы в комментариях. В следующем посте мы измерим производительность Tensorflow Serving и обсудим, как повысить ее производительность.