如何从服务的 TensorFlow 模型中获取元数据?

How do I get the metadata from a served TensorFlow model?

我有几个模型 运行 TensorFlow 服务,我希望这些模型是自描述的,这样我们调用它们的服务就不需要直接嵌入诸如输入大小之类的东西. (例如,我们希望能够在不更新下游系统的情况下交换模型。)

当我使用元数据 API 时,我得到一个具有签名定义的响应,但它显然不是可解释的。该模型有效,所以我很确定这不是模型本身的问题。我还在 TensorFlow 模型上尝试了 saved_model_cli 工具,它 returns 是一个合理的签名定义。

编辑:如果我调用 REST API,元数据 API 也能正常工作。但我真的更想弄清楚如何让它与 gRPC 一起工作。

编辑,2019 年 10 月 21 日:我意识到响应中的数据是 Protocol Buffer 编码的消息。如果我理解正确,这意味着我需要使用 Protocol Buffer 数据进行解析。我试过了

from google.protobuf import text_format
text_format.Parse(result.metadata['signature_def'].value,
                  get_model_metadata_pb2.SignatureDefMap) 

这个,但是现在returns错误:

ParseError: 2:1 : '>': Expected identifier or number, got >.

旧代码:

$ saved_model_cli show --dir mymodel.pb/ --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_data'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, -1, 286339)
        name: input:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['output/Softmax:0'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 286338)
        name: output/Softmax:0
  Method name is: tensorflow/serving/predict

并且:

from tensorflow_serving.apis import get_model_metadata_pb2
import grpc
import tensorflow as tf
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
from tensorflow.contrib import util

MODEL_URI = '10.100.55.9:8500'
channel = grpc.insecure_channel(MODEL_URI)
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)

request = get_model_metadata_pb2.GetModelMetadataRequest()
request.model_spec.name = 'themodel'
request.model_spec.signature_name = 'serving_default'
request.metadata_field.append('signature_def')
result = stub.GetModelMetadata(request, 1.0)

哪个returns

In [5]: result.metadata['signature_def']                                                                                                                                             
Out[5]: 
type_url: "type.googleapis.com/tensorflow.serving.SignatureDefMap"
value: "\n>\n5__saved_model_init_op2%2#\n5__saved_model_init_op2\n\n[=13=]4NoOp2[=13=]20[=13=]1\n1[=13=]1\n7serving_default25[=13=]1\nJ\n[=13=]7input_12?\n1serving_default_input_1:00[=13=]12 230777777777[=13=]1230777777777[=13=]12[=13=]404112;\n[=13=]5dense22\n1StatefulPartitionedCall:00[=13=]123230777777777[=13=]12[=13=]4031122tensorflow/serving/predict"

我最终自己弄明白了。可能有一种更优雅的方法可以做到这一点,它只需要解析出我想要的响应的一部分,而不需要转换为 JSON 然后转换为 Python 对象来得到我想要的部分。但这行得通,所以我要 post 它。

通过对 REST API 代码进行逆向工程,我发现 Protocol Buffer 库中有一个很好的实用函数,可以将 Protocol Buffer 格式转换为 JSON,然后可以对其进行解析通过您选择的 Python JSON 解析器。

from google.protobuf.json_format import MessageToJson
import simplejson as json

parsed = json.loads(MessageToJson(result))