Плюс - Как написать клиент GRPC для обернутой модели

После того, как вы обучили свою модель на основе Tensorflow или Keras, нужно подумать о том, как ее использовать, развернуть в производственной среде. Вы можете сделать его Dockerize как микросервис, реализуя собственный интерфейс GRPC (или REST- или нет). Затем разверните его на сервере или в кластере Kubernetes и попросите другие клиентские микросервисы вызывать его. Библиотека Google Tensorflow Serving помогает здесь сохранить вашу модель на диск, а затем загрузить и использовать интерфейс GRPC или RESTful для взаимодействия с ней.

Я пытался использовать это и обнаружил, что учебники / примеры немного сложны, особенно если вы используете настраиваемую модель, поэтому вот более простой вариант. Я до сих пор не уверен в использовании части TF Serving, так как иметь собственную оболочку GRPC поверх вашей модели не так уж сложно. Но обслуживание TF - это многообещающе. Думаю, со временем узнаю. На данный момент мы сосредоточимся на сохранении простой модели и ее работе с помощью клиента GRPC.

Шаг 1. Сохранение модели в режиме, совместимом с TF Serving

У нас есть простая модель. Я использовал простейший классификатор изображений MNIST, модель. См. Это в записной книжке, размещенной на Colab - https://colab.research.google.com/drive/1ioqL7hD-mrruOlAK-d2axenKVTHrU8gQ (пожалуйста, не обращайте внимания на многие отладочные отпечатки в записной книжке). После того, как NW обучен, нам нужно сохранить веса.

# No need to train if weights are already there
from pathlib import Path
from keras.models import load_model
weightfile ='/content/gdrive/My Drive/Colab Notebooks/my_model_20.h5'
my_file = Path(weightfile)
if my_file.is_file():
  print("Weight file exisits")
  model = load_model(weightfile) 
else:
  print("Weight file do not exist")
  # train the model and save it
  history =model.fit(X_train, Y_train,batch_size=32, epochs=20, 
                   callbacks=[plot],
                   validation_data=(X_test, Y_test),
                   verbose=1)
  model.save(weightfile)

Обратите внимание на то, как файл веса загружается / или сохраняется в приведенном выше фрагменте.

Что, если мы хотим сохранить модель и загрузить модель, чтобы получить к ней интерфейс REST или GRPC. Это то, что делает служба TF.

Сначала мы можем сохранить его способом, совместимым с TF Serving. Поскольку я использую Google Colab, я сохраняю модель на своем Google Диске, вы можете сохранить ее на диск или где-нибудь еще.

import shutil 
import os
tf.keras.backend.clear_session()
# The export path contains the name and the version of the model
tf.keras.backend.set_learning_phase(0) # Ignore dropout at inference
weightfile ='/content/gdrive/My Drive/Colab Notebooks/my_model_20.h5'
export_path = '/content/gdrive/My Drive/Colab Notebooks/ServingModel20'
if os.path.exists( export_path+"/1"):
    shutil.rmtree( export_path+"/1")
    
export_path = export_path+"/1"
# Fetch the Keras session and save the model
with tf.keras.backend.get_session() as sess:
    model = load_model(weightfile)
    tf.saved_model.simple_save(
        sess,
        export_path,
        inputs={'input_image': model.input},
        outputs={t.name:t for t in model.outputs})

В случае успеха результат будет похож на

WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/saved_model/simple_save.py:85: calling SavedModelBuilder.add_meta_graph_and_variables (from tensorflow.python.saved_model.builder_impl) with legacy_init_op is deprecated and will be removed in a future version.
Instructions for updating:
Pass your op to the equivalent parameter main_op instead.
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: /content/gdrive/My Drive/Colab Notebooks/ServingModel20/1/saved_model.pb

Обратите внимание на соглашение о пути к папке в приведенном выше фрагменте - ServingModel20 / 1, где 1 обозначает первую версию модели. TF Serving будет следить за корневым каталогом и автоматически развертывать более поздние версии - это одна из его функций. Итак, после того, как вы каким-то образом выполнили ML CI (что само по себе является публикацией), вы можете развернуть свою модель в ServingModel20 / 2 - и предварительно контейнер TF Serving автоматически загрузит новую модель.

Теперь давайте проверим, можем ли мы загрузить модель с TF Serving. (Обратите внимание, что версии модели по соглашению хранятся в подкаталогах / 1, / 2 и т. Д., Что может быть полезно для управления версиями модели).

!saved_model_cli show --dir '/content/gdrive/My Drive/Colab Notebooks/ServingModel20/1' --all

Вы получите параметры модели, если загрузка прошла успешно, как

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['input_image'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1, 28, 28)
        name: conv2d_1_input:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['dense_2/Softmax:0'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 10)
        name: dense_2/Softmax:0
  Method name is: tensorflow/serving/predict

Обратите внимание на выделение жирным шрифтом, так как именно так вводятся и выводятся интерфейсы для GRPC или REST после обслуживания модели.

Шаг 2. Загрузка сохраненной модели и ее обслуживание с помощью TF Serve

Я загрузил модель в свою домашнюю папку и использовал образ докера tensorflow / serve: latest-gpu от команды TF Serving для загрузки модели - ServingModel20 из сопоставленной папки тома. (Обратите внимание, что у моего ноутбука есть графический процессор, поэтому я использую образ Docker с тегом графического процессора (обратите внимание, что отображение порта 8900 на локальном компьютере - это GRPC, а 8901 - интерфейс REST)

TFServing server
sudo docker run  --runtime= -t --rm -p 8900:8500 -p 8901:8501 -v /home/alex/coding/IPython_neuralnet/ServingModel20:/models/mnist -e MODEL_NAME=mnist tensorflow/serving:latest-gpu

В случае успеха вы получите результат, как показано ниже

2019-01-28 10:37:47.192669: I tensorflow_serving/model_servers/server.cc:286] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
[evhttp_server.cc : 237] RAW: Entering the event loop ...
2019-01-28 10:37:47.194034: I tensorflow_serving/model_servers/server.cc:302] Exporting HTTP/REST API at:localhost:8501 .

Обратите внимание, что REST отображается в порту 8501, а интерфейс GRPC - в порту 8500 (порт сопоставлен с 8901 и 8900 на моем компьютере),

Вот и все! Осталось только написать клиента GRPC.

Шаг 3. Написание клиента GRPC.

Хотя есть пример из TF Serving, мне потребовалось некоторое время, чтобы разобраться в том, как заставить его работать. Я упростил для себя проверку, а здесь - клиент python.

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

channel = grpc.insecure_channel(hostport)                           stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)                           request = predict_pb2.PredictRequest()                           request.model_spec.name = 'mnist'                           request.model_spec.signature_name = 'serving_default'

Получение вывода

result_future.result().outputs['dense_2/Softmax:0'].float_val)

Все эти ключи указаны в спецификации модели. Вот код

Шаг 4. Запуск клиента

Теперь нам нужно запустить клиента. Самый простой - запустить в докер-контейнере. Я использовал тот же контейнер Docker tensorflow_tfserving: latest-gpu для его запуска, но для упрощения обработки MNIST и некоторые модули python установили Keras и некоторые другие библиотеки python и сохранили их как alexcpn / tfserving-dev-gpu. (я сохранил mnist_client.py в / home / alex / coding в приведенном ниже фрагменте)

TFServing Client GPRC
sudo docker run --runtime=nvidia  --net=host -it -v /home/alex/coding:/coding --rm alexcpn/tfserving-dev-gpu bash

Теперь внутри этого контейнера давайте запустим клиент Python и дадим IP-адрес сервера, на котором запущен контейнер TF Serving.

python mnist_client.py  --num_test=1000 --server=<your server ip  ex 10.xx.xx.15>:8901

Если все прошло успешно, вы должны получить результат, как показано ниже или аналогичный

Using TensorFlow backend.
hello from TFServing client slim
Shape is  (28, 28)  Label is  7
Time to Send  20000  is  5.93926405907
[ 100 ] From Callback Predicted Result is  7 confidence=  1.0
[ 200 ] From Callback Predicted Result is  7 confidence=  1.0

Используйте nvidia-smi, чтобы проверить использование графического процессора. Обратите внимание, что с REST вывод должен быть медленнее, поскольку GRPC использует более эффективный HTTP2.

watch -n 0.5 nvidia-smi 

Что-то, что нужно переосмыслить

Поскольку интерфейс выдает вывод последнего уровня, вам может потребоваться добавить микросервис, чтобы преобразовать его в обнаруженные классы; на практике это означает, что вам может потребоваться другая служба Micro, чтобы обернуть это и предоставить клиентам более общий интерфейс GRPC.

Кроме того, вход представляет собой массив numpy. Таким образом, по сравнению с обычными сетями для изображений высокой четкости это добавит много накладных расходов NW. Хотя есть небольшие накладные расходы на вычислительные ресурсы и время для кодирования и отправки в формате jpeg или png и декодирования его на приемнике, эти накладные расходы могут быть компенсированы снижением скорости передачи по сравнению с отправкой необработанного массива numpy по сети. Поэтому нам нужно посмотреть, действительно ли формат ввода массива numpy подходит для обнаружения в реальном времени, например, из видеопотока - когда мы используем несколько узлов с графическим процессором для горизонтального масштабирования.

Кроме того, это тесно связано с другими проектами, такими как Kubeflow. См. Эти прекрасные наборы слайдов от Дэвида Арончика, менеджера Google, а теперь главы отдела стратегии машинного обучения в Microsoft. Это описывает, как Kubeflow, основанный на Kubernetes и использующий TFServing, вписывается в производственный конвейер.

Другие ссылки

[1] Использование TensorFlow для обслуживания с Docker, https://www.tensorflow.org/serving/docker#gpu_serving_example (часть официального документа)

[2] Обучение и обслуживание моделей машинного обучения с tf.keras, Stijn Decubber, https://medium.com/tensorflow/training-and-serving-ml-models-with-tf-keras-fd975cc0fa27 (Показывает, как это через TFServing REST API)

[3] Оптимизация моделей TensorFlow для обслуживания, GCP, Лукман Рэмси, https://medium.com/google-cloud/optimizing-tensorflow-models-for-serving-959080e9ddbf (описывает, почему обслуживание TF)