【问题标题】:Correct payload for TensorFlow Serving REST APITensorFlow Serving REST API 的正确负载
【发布时间】:2018-08-09 22:18:50
【问题描述】:

我已将 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 请求的正确负载格式是什么?

payload需要在tf.Example结构中格式化吗?

【问题讨论】:

标签: rest tensorflow keras tensorflow-serving tensorflow-estimator


【解决方案1】:

这里以Estimator api为例,希望对遇到类似问题的朋友有所帮助。

要使用Estimator 导出SavedModel,您需要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 docker 映像,您可以参考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()

如果您有任何问题,请在下方评论。

【讨论】:

    【解决方案2】:

    您可以尝试使用build_raw_serving_input_receiver_fn() 导出您的模型吗?并将 JSON 预测请求中的原始张量 (procedure) 传递为:

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

    鉴于您使用的是默认服务签名名称和单一命名输入,您可以将请求缩短为:

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

    关于您现有的代码,使用 build_parsing_serving_input_receiver_fn() 导出模型需要序列化的 tf.Example 字符串 blob 作为输入。 saved_model_cli 工具(作为 python 并且可以访问 protos)为您执行此序列化,因此运行良好。在使用 Web/REST API 的同时进行 proto 序列化会变得很麻烦(需要 protobuf 库),并且对您的使用来说是一种过度使用。

    【讨论】:

      【解决方案3】:

      正如上面的 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]))
                      )
                  )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-21
        • 2020-04-21
        • 2016-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多