Правильная полезная нагрузка для TensorFlow Serving REST API

Я преобразовал модель Keras в оценщик Tensorflow, добавил Tensorflow Transform к графику, а затем экспортировал модель для обслуживания.

Когда я проверяю подпись модели, я вижу следующую информацию:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['examples'] tensor_info:
        dtype: DT_STRING
        shape: (-1)
        name: input_example_tensor:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['specialities'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 154)
        name: specialities/Softmax:0
  Method name is: tensorflow/serving/predict

Я преобразовал спецификации функций с tf.estimator.export.build_parsing_serving_input_receiver_fn, поэтому имя входного узла в подписи - example. Имя входного узла в моей модели - procedures.

Затем я использую saved_model_cli, чтобы вручную протестировать экспортированную модель, и все выглядит хорошо (у меня есть список вероятностей)

!saved_model_cli run --dir=/model_dir/1533849825 
                     --tag_set serve 
                     --signature_def serving_default  
                     --input_examples 'examples=[{"procedures": ["99214,17000,17000,13121,99203"]}]'

Теперь я загружаю эту модель в TF Serving, сервер модели запускается нормально.

Когда я запрашиваю прогноз модели с полезной нагрузкой json ниже (application / json), я получаю следующую ошибку:

{
  "signature_name":"serving_default",
  "instances":[
    {
       "examples":["99214,17000,17000,13121,99203"]
    }
  ]
}

Ошибка:

"error": "Expected serialized to be a vector, got shape: [1,1]

Другая структура полезной нагрузки приводит к этой ошибке

{
 "signature_name":"serving_default",
 "examples":[
    {
      "procedure":["99214,17000,17000,13121,99203"]
    }
  ]
}

Ошибка:

"error": "JSON Value: {\n    \"signature_name\": \"serving_default\",\n    
\"examples\": [\n        {\n            \"procedures\": 
["99214,17000,17000,13121,99203"]]\n        }\n    ]\n} not formatted 
correctly. Expecting object with \'instances\' key and a list/array as the value." 

Каков правильный формат полезной нагрузки для запроса TensorFlow Serving в этом случае прогнозирования?

Нужно ли форматировать полезную нагрузку в структуре tf.Example?


person neurix    schedule 09.08.2018    source источник
comment
Вы пытались вместо этого использовать raw_input_receiver_fn? tensorflow.org/api_docs/python/tf/estimator/export/   -  person sdcbr    schedule 10.08.2018


Ответы (3)


Я привожу здесь пример с Estimator api, надеюсь, это поможет кому-то, кто сталкивается с подобными проблемами.

Чтобы экспортировать SavedModel с Estimator, вам понадобится input_receiver_fn, чтобы принимать входные данные при обслуживании. input_receiver_fn в моем приложении выглядит следующим образом:

def _serving_input_receiver_fn():
  serialized_tf_sample = tf.placeholder(dtype=tf.string,
                                        shape=None, name='input_example_tensor')
  receiver_tensors = {'example': serialized_tf_sample}
  # example_proto: {'feature_name': tf.VarLenFeature(tf.int64),}
  features = tf.parse_example(serialized_tf_sample, example_proto)
  return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

Вы можете поместить следующий код в train_and_evaluate, чтобы экспортировать SavedModel

estimator.export_savedmodel(model_export_path, _serving_input_receiver_fn)

Для обслуживания модели вы можете вытащить tensorflow/serving образ докера, вы можете обратиться к https://www.tensorflow.org/serving/docker за помощью. (Я предлагаю вам вытащить изображение с тегом devel, так как лучше отлаживать)

Просто запустите приведенную ниже команду, чтобы начать обслуживание.

/usr/local/bin/tensorflow_model_server --port=8500 --rest_api_port=8501 --model_name=my_model --model_base_path my_model_path

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

import requests
resp = requests.post('http://host:8501/v1/models/my_model:predict', json={
        'instances': [
            {'example': {'b64':base64.b64encode(single_example.SerializeToString())}}
        ]})
resp.json()

Если у вас есть какие-либо вопросы, просто оставьте комментарий ниже.

person Wenmin Wu    schedule 01.02.2019

Можете ли вы попробовать экспортировать свою модель с помощью build_raw_serving_input_receiver_fn () вместо этого? И передайте необработанный тензор (procedure) в запросе прогноза JSON как:

{
 "signature_name": "serving_default",
 "instances": [
    {
      "procedure": ["99214,17000,17000,13121,99203"]
    }
  ]
}

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

{ 
  "instances": ["99214,17000,17000,13121,99203"]
}

Что касается вашего существующего кода, для экспорта модели с использованием build_parsing_serving_input_receiver_fn() в качестве входных данных требуется сериализованный строковый BLOB-объект tf.Example. Инструмент saved_model_cli (являющийся Python и имеющий доступ к протоколам) выполняет эту сериализацию за вас и, следовательно, работает хорошо. Выполнение прото-сериализации при использовании API-интерфейсов Web / REST может оказаться обременительным (требуются библиотеки protobuf) и является излишним для вашего использования.

person netfs    schedule 20.08.2018

Как сказано выше в netfs, использовать build_parsing_serving_input_receiver_fn() для REST API неудобно. Чтобы пояснить, насколько это громоздко, вот ответ на ваш исходный вопрос, тело POST должно быть примерно таким:

{
  "signature_name":"serving_default",
  "instances":[
    {
       "examples":{"b64": base64.b64encode(example.SerializeToString()).decode('utf-8')}
    }
  ]
}

example - это прототип объекта tf.Example. Например:

example = tf.train.Example(
            features=tf.train.Features(
              feature={"procedures": 
                          tf.train.Feature(int64_list=tf.train.Int64List(value=[99214,17000,17000,13121,99203]))
                )
            )
person Happy Gene    schedule 25.02.2020