Пошаговое руководство по обслуживанию (предварительно обученной) модели классификатора изображений из 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. Предпосылки и настройка
- Убедитесь, что вы используете Python 3.x
- Убедитесь, что у вас установлен docker. Если нет, вы можете сделать это здесь.
- Следуйте аналогичной структуре проекта, как показано в репозитории кода.
- Создайте виртуальную среду и активируйте ее
virtualenv venv
source venv/bin/activate - Установите зависимости
— создайте файл 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 APItensorflow_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.