TensorFlow服务RESTAPI的正确有效负载

TensorFlow服务RESTAPI的正确有效负载,rest,tensorflow,keras,tensorflow-serving,tensorflow-estimator,Rest,Tensorflow,Keras,Tensorflow Serving,Tensorflow Estimator,我已将Keras模型转换为Tensorflow估计器,将Tensorflow转换添加到图形中,然后导出模型以提供服务 当我检查模型签名时,我可以看到以下信息: signature_def['serving_default']: The given SavedModel SignatureDef contains the following input(s): inputs['examples'] tensor_info: dtype: DT_STRING

我已将Keras模型转换为Tensorflow估计器,将Tensorflow转换添加到图形中,然后导出模型以提供服务

当我检查模型签名时,我可以看到以下信息:

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\u parsing\u serving\u input\u receiver\u fn
转换了特征规范,因此签名中输入节点的名称为
示例
。我的模型中输入节点的名称是
procedures

然后我使用
saved\u model\u cli
手动测试导出的模型,一切看起来都很好(我得到了一个概率列表)

现在,我将这个模型加载到TF服务中,模型服务器启动正常

当我使用下面的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服务请求的正确有效负载格式是什么?


负载是否需要在tf.Example结构中格式化?

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

{
 "signature_name": "serving_default",
 "instances": [
    {
      "procedure": ["99214,17000,17000,13121,99203"]
    }
  ]
}
鉴于您使用的是默认服务签名名和单一命名输入,您可以将请求缩短为:

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

关于现有代码,使用
build\u parsing\u service\u input\u receiver\u fn()导出模型需要序列化
tf。例如
string blob作为输入
saved_model_cli
tool(作为python并可以访问protos)为您执行此序列化,因此工作良好。在使用Web/REST api的同时进行proto序列化可能会变得很麻烦(需要protobuf libs),这对于您的使用来说是一种过分的做法。

我在这里举了一个使用
估计器
api的例子,希望它能帮助遇到类似问题的人

要使用
Estimator
导出
SavedModel
,您需要一个
input\u receiver\u fn
以在服务时查看输入。我的应用程序中的
输入\u接收器\u fn
如下所示:

def服务输入接收器fn():
序列化的\u tf\u sample=tf.placeholder(dtype=tf.string,
shape=None,name='input\u example\u tensor')
接收器\u张量={'example':序列化的\u tf\u sample}
#示例_proto:{'feature_name':tf.VarLenFeature(tf.int64),}
features=tf.parse_示例(序列化的_-tf_示例,示例_-proto)
返回tf.estimator.export.ServingInputReceiver(特征、接收器张量)
您可以将以下代码置于
train\u和\u evaluate
下,以导出
SavedModel

estimator.export_savedmodel(model_export_path, _serving_input_receiver_fn)
要为模型提供服务,您可以拉取
tensorflow/service
docker图像,您可以参考帮助。(我建议您使用devel标记拉取映像,因为调试会更好)

只需运行下面的命令即可开始服务

/usr/local/bin/tensorflow\u model\u server--port=8500--rest\u api\u port=8501--model\u name=my\u model--model\u base\u path my\u model\u path

客户端代码很简单,但是应该注意。因为序列化的示例应该使用base64编码并添加一个
b64

导入请求
resp=requests.post('http://host:8501/v1/models/my_model:predict,json={
“实例”:[
{'example':{'b64':base64.b64encode(single_example.SerializeToString())}
]})
resp.json()

如果您有任何问题,请在下面进行评论。

正如上面netfs所说的那样,为REST API使用
build\u parsing\u service\u input\u receiver\u fn()
。为了详细说明它有多麻烦,下面是您最初问题的答案,帖子正文应该是这样的:

{
  "signature_name":"serving_default",
  "instances":[
    {
       "examples":{"b64": base64.b64encode(example.SerializeToString()).decode('utf-8')}
    }
  ]
}
示例
是一个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]))
                )
            )

你试过用“原始输入接收器”来代替吗?请参见此处
example = tf.train.Example(
            features=tf.train.Features(
              feature={"procedures": 
                          tf.train.Feature(int64_list=tf.train.Int64List(value=[99214,17000,17000,13121,99203]))
                )
            )