TensorFlow v1.10 + обслуживает пользовательский оценщик? - PullRequest
0 голосов
/ 18 ноября 2018

Есть несколько вопросов относительно обслуживания с TensorFlow, например:

Однако многие из них, как я обнаружил, устарели, относятся к Estimator export_outputs или используют другой API (например, C #).

Кроме того, "Basic" Руководство по обслуживанию совсем не так.Предполагается знакомство с docker , требуется использование отдельного TensorFlow repo , а руководство по загрузке модели ограничено следующим:

Загрузите экспортированную модель со стандартным TensorFlow ModelServer

Используйте изображение для обслуживания Docker, чтобы легко загрузить модель для обслуживания:

docker run -p 8500:8500 \
--mount type=bind,source=/tmp/mnist,target=/models/mnist \
-e MODEL_NAME=mnist -t tensorflow/serving &

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

Итак, вот простая пользовательская оценка

Может кто-нибудь объяснить мне в терминах непрофессионала,для тех, кто не знает, что такое служба gRPC, как взять мою экспортированную модель из colab (скажем, я загружаю каталог файлов как есть из colab в /tmp/colab/<contents-from-linked-colab>)и подавать его (желательно без докера)

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Предположим, у вас есть собственный оценщик, обученный и готовый служить, как тот, который указан в вашем вопросе.Процедура сохранения и обслуживания обученной модели оценщика:

  1. Экспорт оценщика в формат SavedModel.
  2. Служение SavedModel с помощью TensorFlow ModelServer.
  3. Feedвходные данные для обслуживаемой модели и наблюдение результатов прогнозирования.

В некоторых случаях ваша обученная модель оценки может быть лучше развернута и повторно использована без ее обслуживания.Иногда лучше заморозить модель и развернуть ее непосредственно внутри программы.Или иногда вы хотите конвертировать модель в javascript или облегченную версию TensorFlow.Есть много способов повторно использовать обученный оценщик, не обслуживая его.Но поскольку в вашем вопросе конкретно говорится об обслуживании, этот ответ о конкретном обслуживании со стандартным ModelServer.

1.Экспорт в формат SavedModel

Из документов :

Чтобы подготовить обученного оценщика к обслуживанию, вы должны экспортировать его в стандартном формате SavedModel.

Для этого мы можем использовать функцию export_saved_model, и для этого необходимо сначала определить функцию приемника обслуживающего входа.Функция приемника обслуживающего входа определяет и присваивает имена всем тензорам, которые становятся входными данными для модели во время обслуживания.

Существует два вида функций приемника обслуживающего входа, и каждый тип сообщает TensorFlow, как следует ожидать ввода на шаге 3:

  • Анализ функций приемника обслуживающего входа : Входы предоставляются в виде сериализованных Example protobufs.Этот тип говорит TensorFlow ожидать, что вход модели будет поступать от строкового тензора, который будет проанализирован в элементах.Этот приемник может быть построен с использованием tf.estimator.export.build_parsing_serving_input_receiver_fn.

  • Функции приемника необработанных входных сигналов : входы предоставляются непосредственно как Tensor protobufs.Этот приемник может быть построен с использованием tf.estimator.export.build_raw_serving_input_receiver_fn.

Ваш код colab создает две функции приемника, которые выполняют одно и то же:

serving_fn = tf.estimator.export.build_raw_serving_input_receiver_fn(
    {'input_tensors': tf.placeholder(tf.float32, I_SHAPE(None), name="input_tensors")})

и:

def serving_input_receiver_fn():
  input_tensors = tf.placeholder(tf.float32, I_SHAPE(None), name="input_tensors")
​
​
  features = {'input_tensors' : input_tensors}
  receiver_tensors = {'input_tensors': input_tensors}
  return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

Но экспорт выполняется только одним:

est.export_savedmodel('./here', serving_input_receiver_fn)

Вы можете удалить свой метод serving_input_receiver_fn и использовать первое определение:

est.export_savedmodel('./here', serving_fn)

и

exporter = tf.estimator.BestExporter(
    name="best_exporter",
    serving_input_receiver_fn=serving_fn,
    exports_to_keep=5
)

2.Служите SavedModel

В вашем вопросе говорилось, что вы предпочитаете обслуживать свою модель без использования докера.Согласно его Dockerfile , образ docker просто запускает двоичный файл TensorFlow ModelServer , который вы можете установить или собрать из источника вне контейнера, как описано в его README, или вы можете скопировать егоиз контейнера tensorflow/serving.

Как только вы установили двоичный файл, запустите его, чтобы запустить сервер gRPC, прослушивающий порт, который вы хотите, например, 8500:

tensorflow_model_server --port=8500 --model_name=my_model --model_base_path=/path/to/export/dir

Теперь вы«обслуживаем» модель.Если вы хотите только запустить модель, не требуя ничего от репозитория tenorflow_serving, вы можете вместо этого использовать интерфейс командной строки сохраненной модели *1081* для запуска SavedModel без сервера модели.Он должен быть уже установлен вместе с TensorFlow, если вы установили из готового двоичного файла.

3.Запрос работающего сервера модели

Стандартный способ запроса модели - это служба gRPC, предоставляемая ModelServer.gRPC - это платформа RPC , которая использует формат буфера протокола Google для определения сервисов и связи между хостами.Он разработан, чтобы быть быстрым, кроссплатформенным и масштабируемым.Это особенно удобно, когда все ваши данные уже обработаны в формате protobuf, например, при работе с файлами TFRecord.

Существуют библиотеки gRPC для многих разных языков, и вы даже можете общаться с вашим сервером, например, cURL, нопоскольку ваш вопрос помечен для Python, я буду использовать пакеты Python grpcio и tenorflow-Обслуживание-api для выполнения вызовов gRPC, необходимых для прогнозирования с помощью обслуживаемой модели.

После запуска сервера и установки пакетов Python вы можете проверить соединение, запросив метаданные def сигнатуры модели:

from __future__ import print_function
import grpc
from tensorflow_serving.apis import get_model_metadata_pb2
from tensorflow_serving.apis import model_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc


with grpc.insecure_channel("localhost:8500") as channel:
  stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)

  request = get_model_metadata_pb2.GetModelMetadataRequest(
      model_spec=model_pb2.ModelSpec(name="my_model"),
      metadata_field=["signature_def"])

  response = stub.GetModelMetadata(request)
  sigdef_str = response.metadata["signature_def"].value

  print ("Name:", response.model_spec.name)
  print ("Version:", response.model_spec.version.value)
  print (get_model_metadata_pb2.SignatureDefMap.FromString(sigdef_str))

С моделью из вашего колаба вы увидите

Name: my_model
Version: ...
signature_def {
  key: "labels"
  value {
    inputs {
      key: "input_tensors"
      value {
        name: "input_tensors:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: 20
          }
          dim {
            size: 7
          }
        }
      }
    }
    outputs {
      key: "output"
      value {
        name: "Sigmoid:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: 20
          }
          dim {
            size: 4
          }
        }
      }
    }
    method_name: "tensorflow/serving/predict"
  }
}
signature_def {
  key: "serving_default"
  value {
    inputs {
      key: "input_tensors"
      value {
        name: "input_tensors:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: 20
          }
          dim {
            size: 7
          }
        }
      }
    }
    outputs {
      key: "output"
      value {
        name: "Sigmoid:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: 20
          }
          dim {
            size: 4
          }
        }
      }
    }
    method_name: "tensorflow/serving/predict"
  }
}

Таким образом, согласно определению сигнатуры, модель ожидает словарь, сопоставляющий ключ input_tensors с протоколом Tensor типа и формы с плавающей точкой [-1, 20, 7], и выводит словарь, сопоставляющий ключ output с протоколом Tensor с плавающей точкой. тип и форма точки [-1, 20, 4]. Мы можем создать прототип Tensor в Python из массива numpy, используя tf.make_tensor_proto и преобразовать обратно, используя tf.make_ndarray:

from __future__ import print_function
import grpc
import numpy as np
import tensorflow as tf
from tensorflow_serving.apis import model_pb2
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc


# Dummy input data for batch size 3.
batch_input = np.ones((3, 20, 7), dtype="float32")


with grpc.insecure_channel("localhost:8500") as channel:
  stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)

  request = predict_pb2.PredictRequest(
      model_spec=model_pb2.ModelSpec(name="my_model"),
      inputs={"input_tensors": tf.make_tensor_proto(batch_input)})

  response = stub.Predict(request)

  batch_output = tf.make_ndarray(response.outputs["output"])
  print (batch_output.shape)

Действительно, у вас должен быть массив формы с плавающей точкой (3, 20, 4), возвращаемый вашей службой оценочной модели.

Для получения дополнительной информации о том, как службы gRPC определены и используются в Python, см. Учебное пособие на веб-сайте gRPC . Подробные сведения об API * 1120 см. В определениях протокола .proto .

.
0 голосов
/ 21 ноября 2018

В связанном коде colab после того, как вы запустите оценщик , вы должны иметь папки saved_model.pb и /variables в colab .файловая система по умолчанию.Я буду ссылаться на то, где находятся эти файлы, как OUTPUT_PATH.

Чтобы выяснить, что такое OUTPUT_PATH, давайте кратко рассмотрим соответствующий код из colab здесь:

Оценщик> определить экспортер

exporter = tf.estimator.BestExporter(
    name="best_exporter",
    serving_input_receiver_fn=serving_input_receiver_fn,
    exports_to_keep=5
) # this will keep the 5 best checkpoints

и

Оценщик> инициатор оценки

est = tf.estimator.Estimator(
    model_fn = model_fn,
    config = run_config, # <--- model_dir is set in here
    params = run_params,
)

Поскольку под Setup > Constants вы определяете MODEL_DIR = './test', ваш BestExporter сохраняется в test/export/best_exporter/<model_num>/

Таким образом, ваш OUTPUT_PATH равен этому.

Загрузите эту папку, где вы хотите сохранить результаты.Для лучшей читаемости переименуйте <model_num> с чем-то значимым, например, test/export/best_exporter/demo_model

Служение с помощью docker для ясности, и с измененной командой docker:

docker run -p 8500:8500 \
--mount type=bind,\
        source=$OUTPUT_PATH,\
        target=/models/$MODEL_NAME \
-e MODEL_NAME=$MODEL_NAME -t tensorflow/serving &

Для тех, кто не связан с Docker, source=$OUTPUT_PATH,target=/models/$MODEL_NAME сопоставляет каталог OUTPUT_PATH с каталогом контейнера докера /models/$MODEL_NAME.

Таким образом, в этом случае у вас будет:

source=<path-to-downloaded-dir>/test/export/best_exporter/demo_model,\
target=/models/demo_model,\
-e MODEL_NAME=demo_model

, так как мы предполагаем, что источником является model_dir, а где <path-to-downloaded-dir> где вы скачали /test/export/best_exporter/demo_model.

Затем, следуя примеру grpc, напишите клиент.Если вы предпочитаете RESTful API, возможно, вам нужно изменить порт док-станции на 8501:8501 или использовать оба вместе 8500-8501:8500-8501.Вот мой другой ответ , чтобы объяснить эту команду docker.

Если вы не хотите docker, попробуйте установить tf-Обслуживание локально , почти ту же командузапустить сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...