Пошаговое руководство по обслуживанию (предварительно обученной) модели классификатора изображений из TensorFlow Hub с использованием TensorFlow Serving и gRPC.

gRPC (вызовы удаленных процедур gRPC) — это относительно новый кроссплатформенный высокопроизводительный удаленный вызов процедур (RPC) с открытым исходным кодом, разработанный Google примерно в 2016 году.

Основным преимуществом gRPC является его скорость и вес по сравнению с REST API. Он построен на HTTP/2 и передает сообщения, используя Protobuf (протокольные буферы), что делает работу намного быстрее и легче.

REST API, с другой стороны, построены на HTTP/1.1 и используют JSON или XML в качестве наиболее популярных форматов обмена сообщениями.

Подробнее об их сравнении можно прочитать здесь.

В моем предыдущем руководстве мы рассмотрели обслуживание моделей машинного обучения (ML) в виде REST API с помощью TensorFlow Serving.



В этом руководстве основное внимание уделяется достижению той же цели, но с использованием gRPC.

Если вы следовали моему последнему руководству по обслуживанию модели машинного обучения в качестве REST API с использованием Docker и TensorFlow Serving, то вы можете напрямую перейти к шагу 2⬇️ этого руководства.😉

Архитектура gRPC: обзор

В gRPC клиентское приложение может напрямую вызывать метод серверного приложения на другом компьютере, как если бы это был локальный объект. Таким образом, упрощается создание распределенных систем и сервисов.

В традиционном протоколе HTTP невозможно отправить несколько запросов или получить несколько ответов одновременно в одном соединении. Следовательно, для каждого запроса/ответа необходимо открывать новое соединение.
gRPC основан на HTTP/2, что позволяет ему одновременно обрабатывать несколько запросов/ответов, тем самым значительно повышая скорость.

gRPC также использует Protobuf в качестве своего IDL (языка определения интерфейса). Protobuf хранит все контракты данных и функций в виде прото-файла. Затем эти прото-файлы совместно используются как сервером, так и клиентом во время связи. Файл proto действует как промежуточный контракт для клиента, чтобы вызвать любую доступную функцию с сервера.

Шаг: 0. Предпосылки и настройка

  1. Убедитесь, что вы используете Python 3.x
  2. Убедитесь, что у вас установлен docker. Если нет, вы можете сделать это здесь.
  3. Следуйте аналогичной структуре проекта, как показано в репозитории кода.
  4. Создайте виртуальную среду и активируйте ее
    virtualenv venv
    source venv/bin/activate
  5. Установите зависимости
    — создайте файл requirements.txt следующим образом
    — теперь установите требования как pip3 install -r requirements.txt
Pillow==9.1.1
tensorflow
tensorflow_hub
requests
numpy
grpcio
tensorflow_serving_api

6. Установите TensorFlow Serving используя docker

Первым шагом к началу работы с TensorFlow Serving является извлечение последнего образа докера из командной строки следующим образом:

docker pull tensorflow/serving

Чтобы убедиться, что у вас есть правильное изображение, вы можете проверить терминал как docker images, и он должен сгенерировать следующее:

Шаг 1: (Загрузить и) сохранить (предварительно обученную) модель

В load_model() мы загружаем предварительно обученную модель TensorFlow MobileNet_V2 из TensorFlow hub.

В save_model() мы сохраняем модель в папке /models/, чтобы позже наш API мог получить к ней доступ.

Шаг 2. Внедрите клиент gRPC для обслуживания модели с помощью TF Serving.

Пояснения

  • Lines 11–13: мы устанавливаем небезопасное соединение с URL-адресом хостинга (здесь: localhost:9000) и создаем для него stub.
    stub — это фрагмент кода, который используется для преобразования параметров во время RPC (удаленный вызов процедур). Поскольку клиент и сервер расположены в разных местах, заглушка берет на себя связанные с преобразованием затраты. Это позволяет удаленному серверу воспринимать RPC как локальный вызов функции.
  • Lines 14–16: Мы готовим запрос с model name и model signature
  • Line 18: Изображение предварительно обработано для соответствия требованиям модели.
  • Line 20: Мы добавляем предварительно обработанное изображение как input в запрос. tf.make_tensor_proto используется для преобразования массива numpy в protobuf.

Убедитесь, что вы добавляете правильное имя входного слоя вашей модели здесь. Вы можете получить его либо из model.summary(), либо изучив метаграф модели с помощью saved_model_cli show — dir ‘path/to/the/model/’ — all

  • Line 21: Мы отправляем запрос прогноза через stub с timeout из 10 seconds.
  • Line 24–26: Когда у нас есть прогнозы в форме protobuf, нам нужно преобразовать их в numpy, чтобы иметь возможность декодировать/назначать им метки.
  • Line 29: Мы расшифровываем наши прогнозы (теперь в формате numpy ndarray) и присваиваем им метки. Это дает нам label и confidence предсказания.

Шаг 3. Запустите TF Serving как на портах REST, так и на портах gRPC.

TensorFlow Serving запускается в док-контейнере следующим образом:

$ docker run --name myTFServing 
       -it 
       -v path/to/repository/img-classifier-tfx:/img-classifier-tfx 
       -p 9001:9001 
       -p 9000:9000 
       --entrypoint /bin/bash tensorflow/serving

Пояснения:

  • docker run --name <myContainerName> : создает контейнер с именем myTFServing (здесь вы можете использовать любое имя). Имя контейнера позже используется для целей идентификации.
  • -it : запускает контейнер в интерактивном режиме.
  • -v path/to/repository/img-classifier-tfx:/img-classifier-tfx привязывает том с хоста к каталогу внутри контейнера.
  • -p <host_port>:<container_port> сопоставляет порт хоста с портом контейнера.
    Здесь мы предоставляем 2 порта 9001 и 9000 для REST API и gRPC соответственно.
  • --entrypoint /bin/bash : указывает, что исполняемый файл /bin/bash должен запускаться при запуске контейнера.
  • tensorflow/serving — это имя образа, из которого создан контейнер.

Шаг 4. Подайте модель

Как только мы запустим и запустим контейнер, наша следующая цель — обслуживать модель через gRPC.

Изнутри работающего док-контейнера мы запускаем TensorFlow Serving следующим образом:

$ cd img-classifier-tfx/

$ tensorflow_model_server 
         --port=9000 
         --model_name=<model_name> 
         --model_base_path=/img-classifier-tfx/src/pred/path/to/models/

Обратите внимание, что мы используем тот же порт 9000, который был сопоставлен ранее.
Параметры --model_name и --model_base_path обозначают имя, под которым была сохранена модель, и расположение модели соответственно.

Шаг 5: Получение результатов прогноза

Чтобы предсказать изображения, теперь мы вызываем serve_grpc() с действительным URL-адресом изображения и должны получить соответствующие предсказанные результаты !!

Полную реализацию кода можно найти здесь.



Полезные советы по отладке при использовании TensorFlow Serving с gRPC

  • Настоятельно рекомендуется использовать TF Serving через контейнеры Docker из-за их легкой интеграции.
  • Убедитесь, что вы добавляете правильное имя слоя ввода/вывода вашей модели при определении вашего запроса.
    Вы можете получить его либо из model.summary(), либо изучив метаграф модели с помощью
    saved_model_cli show —- dir ‘absolute/path/to/the/model/’ — — all
    Вы должны увидеть что-то похожее на следующее. Обратите внимание на имена входного и выходного слоев оттуда.

  • Если вы хотите запустить tensorflow_model_server отдельно для REST/gRPC, вы можете запустить следующее:
    REST API
    tensorflow_model_server
    --rest_api_port=9001
    --model_name=<model_name>
    --model_base_path=/img-classifier-tfx/src/pred/path/to/models/

    gRPC
    tensorflow_model_server
    — port=9000
    — model_name=<model_name>
    — model_base_path=/img-classifier-tfx/src/pred/path/to/models/

Заключение

gRPC вместе с TensorFlow Serving — довольно многообещающая альтернатива при использовании массивных наборов данных и оптимизации скорости и производительности.

Однако у него есть и свои недостатки. Поскольку gRPC использует HTTP/2, доступ к службе gRPC из веб-браузера невозможен. Ни один современный браузер не обеспечивает контроль над веб-запросами, необходимый для поддержки клиента gRPC. Поэтому нам нужен прокси-уровень и gRPC-web для выполнения преобразований между HTTP/1.1 и HTTP/2.

Кроме того, Protobuf сжимает сообщения gRPC в нечитаемый формат, в отличие от JSON сообщений в интерфейсе REST. Таким образом, это усложняет отладку. Разработчикам требуются дополнительные инструменты, такие как инструмент командной строки gRPC, для анализа полезной нагрузки Protobuf и для общей отладки.

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

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

Если вам понравилась статья, подпишитесь, чтобы получать мои последние статьи.
Чтобы связаться со мной, либо свяжитесь со мной в LinkedIn или через ashmibanerjee.com.