
Содержание статьи
Кирилла Дубовикова

Представьте себе: вы сели на борт AI Hype Train и решили разработать приложение, которое будет анализировать эффективность разных типов палочек для еды. Чтобы монетизировать эту потрясающую программу искусственного интеллекта и произвести впечатление на венчурных капиталистов нам нужно будет открыть ее для всего мира. И лучше, чтобы он был масштабирован, поскольку каждый захочет им пользоваться.
В качестве отправной точки мы будем использовать этот набор данных, содержащий измерение эффективности зажима пищи разными людьми палочками разной длины.
Архитектура
Поскольку мы не только исследователи данных, но и ответственные инженеры программного обеспечения, мы сначала разработаем проект нашей архитектуры. Во-первых, нам нужно решить, как у нас будет доступ к нашей развернутой модели, чтобы делать прогнозы. Для TensorFlow наивным выбором было бы использовать TensorFlow Serving. Этот фреймворк позволяет разворачивать обученные модели TensorFlow, поддерживает версии модели и использует gRPC под капотом.
Основная оговорка относительно gRPC заключается в том, что он не очень дружен для общественности по сравнению, например, со службами REST. Кто-нибудь с минимальными инструментами может вызвать службу REST и быстро получить результат. Но когда вы используете gRPC, вы должны сначала сгенерировать код клиента из прото-файлов с помощью специальных утилит, а затем написать клиент на ваш любимый язык программирования.
TensorFlow Serving упрощает многое в этом конвейере, но все же это не самый простой фреймворк для использования API на стороне клиента. Рассмотрите TF Serving, если вам нужен молниеносный, надежный API со строгой типизацией, который будет использоваться в вашем приложении (например, как серверная служба для веб- или мобильного приложения).
Нам также нужно будет удовлетворить нефункциональные требования к нашей системе. Если многие пользователи захотят знать уровень эффективности своих палочек для еды, нам понадобится, чтобы система была устойчива к отказам и масштабирована. Кроме того, команде, занимающейся пользовательским интерфейсом, также нужно будет где-то развернуть свое веб-приложение chopstick’o’meter. И нам понадобятся ресурсы для прототипирования новых моделей машинного обучения, возможно, в Jupyter лаборатории с большой вычислительной мощностью. Одним из лучших ответов на эти вопросы является использование Kubernetes.
Kubernetes – это система с открытым кодом для автоматизации развертывания, масштабирования и управления контейнерными программами.
Имея Kubernetes на месте, имея знания и некоторое время, мы можем создать масштабируемое собственное облачное решение PaaS, обеспечивающее инфраструктуру и программное обеспечение для разработки проектов полного цикла обработки данных. Если вы не знакомы с Kubernetes, я предлагаю вам посмотреть это:
Kubernetes работает на базе технологии Docker, так что если вы не знакомы с ней, возможно, стоит сначала прочитать официальное руководство.
В общем, это очень насыщенная тема, которая заслуживает того, чтобы ее осветить в нескольких книгах, поэтому мы сосредоточимся на одной части: перемещении моделей машинного обучения в производство.
размышления
Да, этот набор данных невелик. И так применение глубокого обучения может быть не лучшей идеей. Просто имейте в виду, что мы здесь, чтобы учиться, и этот набор данных, безусловно, интересен. Части этого учебника, посвященной моделированию, будет некачественно, поскольку основное внимание сосредоточено на процессе развертывания модели.
Кроме того, нам нужно произвести впечатление на наших венчурных капиталистов, поэтому глубокое обучение обязательно! 🙂

код
Весь код и конфигурационные файлы, использованные в данной публикации, доступны в сопутствующем репозитории GitHub.
Учебный классификатор Deep Chopstick
Во-первых, мы должны выбрать структуру машинного обучения для использования. Поскольку статья предназначена для демонстрации возможностей обслуживания TensorFlow, мы выберем TensorFlow.
Как вы наверняка знаете, мы можем научить наш классификатор двумя способами: с помощью TensorFlow и TensorFlow Estimator API. API Estimator это попытка представить унифицированный интерфейс для моделей глубокого обучения так, как scikit-learn делает это для набора классических моделей ML. Для этой задачи мы можем использовать tf.estimator.LinearClassifier
для быстрого внедрения логистической регрессии и экспорта модели после завершения обучения.
Другой способ, которым мы можем это сделать, – использовать обычный TensorFlow для обучения и экспорта классификатора:
Настройка обслуживания TensorFlow

Итак, у вас есть отличная модель глубокого обучения с TensorFlow и вы хотите запустить ее в производство? Теперь пора взять в руки TensorFlow Serving.
TensorFlow Serving базируется на gRPC – библиотеке быстрого удаленного вызова процедур, использующей другой проект Google под капотом – буферы протоколов.
Protocol Buffers – это структура сериализации, позволяющая преобразовывать объекты из памяти в эффективный двоичный формат, пригодный для передачи через сеть.
Подытоживая, gRPC — это структура, позволяющая удаленные вызовы функций через сеть. Он использует буферы протоколов для сериализации и десериализации данных.
Основными компонентами TensorFlow Serving являются:
- Подходит для обслуживания — это фактически версия вашей обученной модели, экспортируемая в формат, пригодный для загрузки TF Serving
- Погрузчик — обслуживающий компонент TF, который по стечению обстоятельств загружает объекты обслуживания в память
- Менеджер реализует операции жизненного цикла servable. Он контролирует рождение (погрузку), долгую жизнь (обслуживание) и смерть (разгрузку) servable.
- Ядро — заставляет все компоненты работать вместе (официальная документация несколько расплывчата по поводу того, что на самом деле является ядром, но вы всегда можете просмотреть исходный код, чтобы понять, что он делает)
Вы можете прочитать более глубокий обзор архитектуры TF Serving в официальной документации.
Чтобы запустить службу на основе обслуживания TF, вам нужно:
- Экспортируйте модель в формат, совместимый с TensorFlow Serving. Другими словами, создайте Servable.
- Установите или скомпилируйте TensorFlow Serving
- Запустите TensorFlow Serving и загрузите последнюю версию экспортируемой модели (пригодно для обслуживания)
Настроить TernsorFlow Serving можно несколькими способами:
- Строительство из источника. Для этого необходимо установить Bazel и завершить длительный процесс компиляции.
- Использование предварительно собранного двоичного пакета. Обслуживание TF доступно как пакет deb.
Чтобы автоматизировать этот процесс и упростить дальнейшую установку в Kubernetes, мы создали для вас простой Dockerfile. Пожалуйста, клонируйте репозиторий статьи и следуйте инструкциям в файле README.md, чтобы создать образ TensorFlow Serving Docker:
➜ make build_image
В этом образе предварительно установлены TensorFlow Serving и все зависимости. По умолчанию он загружает модели с /models
каталог внутри контейнера докеров.
Запуск службы прогнозирования
Чтобы запустить наш сервис в созданном и готовом к использованию образе TF Serving, обязательно сначала научите и экспортируйте модель (или, если вы используете сопутствующее хранилище, просто запустите make train_classifier
команда).
После того, как классификатор обучен и экспортирован, вы можете запустить контейнер обслуживания с помощью ярлыка make run_server
или с помощью такой команды:
➜ docker run -p8500:8500 -d --rm -v /path/to/exported/model:/models tfserve_bin
-p
отображает порты из контейнера на локальную машину-d
запускает контейнер в фоновом (фоновом) режиме--rm
снимает контейнер после его остановки-v
сопоставляет локальный каталог с каталогом в запущенном контейнере. Таким образом, мы передаем наши экспортируемые модели экземпляра TF Serving, работающего внутри контейнера.
Вызов модельных служб со стороны клиента
Для вызова наших служб мы будем использовать grpc
tensorflow-serving-api
Пакеты Python. Обратите внимание, что этот пакет доступен только для Python 2, поэтому вы должны иметь отдельную виртуальную среду для клиента TF Serving.
Чтобы использовать этот API с Python 3, вам понадобится либо использовать неофициальный пакет отсюда, затем загрузить и распаковать пакет вручную, либо собрать TensorFlow Serving из исходного кода (см. документацию). Ниже приведены примеры клиентов для API Estimator и обычного TensorFlow:
Запуск производства с Kubernetes
Если у вас нет доступного кластера Kubernetes, вы можете создать его для локальных экспериментов с помощью minikube или легко развернуть настоящий кластер с помощью kubeadm.
В этом сообщении мы рассмотрим вариант minikube. После установки (brew cask install minikube
на Mac) мы можем запустить локальный кластер и поделиться его средой Docker с нашей машиной:
➜ minikube start...➜ eval $(minikube docker-env)
После этого мы сможем создать наш образ и разместить его в кластере с помощью
➜ make build_image
Более зрелым вариантом было бы использовать внутренний реестр докеров и вставить туда локально созданный образ, но мы оставим это вне, чтобы быть более лаконичным.
После того, как образ создан и доступен для экземпляра Minikube, нам нужно развернуть наш модельный сервер. Чтобы использовать функции балансировки нагрузки и высокой доступности Kubernetes, мы создадим развертывание, которое автоматически масштабирует наш сервер модели до трех экземпляров, а также будет контролировать их и работать. Вы можете прочитать больше о развертывании Kubernetes здесь.
Все объекты Kubernetes можно настроить в разных текстовых форматах и затем передать kubectl apply -f file_name
команда (meh) применить нашу конфигурацию к кластеру. Вот наша конфигурация развертывания сервера chopstick:
Давайте применим это развертывание с помощью kubectl apply -f chopstick_deployment.yml
команда. Через некоторое время вы увидите, что все компоненты запущены:
➜ kubectl get allNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEdeploy/chopstick-classifier 3 3 3 3 1d
NAME DESIRED CURRENT READY AGErs/chopstick-classifier-745cbdf8cd 3 3 3 1d
NAME AGEdeploy/chopstick-classifier 1d
NAME AGErs/chopstick-classifier-745cbdf8cd 1d
NAME READY STATUS RESTARTS AGEpo/chopstick-classifier-745cbdf8cd-5gx2g 1/1 Running 0 1dpo/chopstick-classifier-745cbdf8cd-dxq7g 1/1 Running 0 1dpo/chopstick-classifier-745cbdf8cd-pktzr 1/1 Running 0 1d
Обратите внимание, что на основе конфигурации развертывания Kubernetes создал для нас:
- Развертывание
- Набор копий
- Три капсулы, на которых работает наш образ классификатора палочек для еды
Теперь мы хотим назвать наш новый блестящий сервис. Чтобы это произошло, сначала нам нужно показать его внешнему миру. В Kubernetes это можно сделать, определив Службы. Вот определение службы для нашей модели:
Как всегда, мы можем установить его с помощью kubectl apply -f chopstick_service.yml
. Kubernetes назначит внешний порт для нашего LoadBalancer, и мы сможем увидеть его, запустив
➜ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEchopstick-classifier LoadBalancer 10.104.213.253 <pending> 8500:32372/TCP 1dkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d
Как видите, наш chopstick-classifier
доступен через порт 32372
в моем случае. В вашем автомобиле он может отличаться, поэтому не забудьте проверить его. Удобный способ получить IP-адрес и порт для любой службы при использовании Minikube — выполнить следующую команду:
➜ minikube service chopstick-classifier --urlhttp://192.168.99.100:32372
Вывод
Наконец-то мы можем позвонить в наш сервис!
python tf_api/client.py 192.168.99.100:32372 1010.0Sending requestoutputs { key: "classes_prob" value { dtype: DT_FLOAT tensor_shape { dim { size: 1 } dim { size: 3 } } float_val: 3.98174306027e-11 float_val: 1.0 float_val: 1.83699980923e-18 }}
Перед началом реального производства

Поскольку эта публикация предназначена преимущественно для образовательных целей и имеет некоторые упрощения для ясности, существует несколько важных моментов, которые следует рассмотреть перед тем, как перейти к производству:
- Используйте сетевой сервис, например linkerd.io. Доступ к службам из случайно сгенерированных портов узла не рекомендован в производстве. Как плюс, Linker придаст гораздо больше ценности вашей производственной инфраструктуре: мониторинг, поиск служб, высокоскоростная балансировка нагрузки и т.д.
- Используйте Python 3 везде, поскольку на самом деле нет причин использовать Python 2 сейчас
- Разумно применяйте Deep Learning. Несмотря на то, что это очень общая, впечатляющая и широко применимая структура, глубинная учеба не является единственным инструментом в распоряжении ученого по данным. Это также не серебряный шар, решающий любую проблему. Машинное обучение может предложить гораздо большее. Если у вас есть реляционные/табличные данные, небольшие наборы данных, строгие ограничения на вычислительные ресурсы, время обучения или возможность интерпретации модели, подумайте об использовании других алгоритмов и подходов.
- Свяжитесь с нами, если вам необходима помощь в решении задач машинного обучения: datalab@cinimex.ru