Tensorflow、Tensorflow-serving:SavedModel 签名的多个输入

Tensorflow, Tensorflow-serving: Multiple inputs for SavedModel signature

我正在尝试导出我的模型以通过 SavedModel 提供服务,并且 运行 在 do 推理调用中遇到服务客户端的问题。

error: 
grpc.framework.interfaces.face.face.AbortionError: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="Missing ModelSpec")

我有 4 个必须提供的占位符,输入、dropout(推理时将为 1.0)和(一个糟糕的解决方法)用于加载预训练的 GoogleW2V 向量嵌入(由于它们的大小,我必须提供它们通过占位符进入图表以进行嵌入查找。我将它们分成两半,因为在服务客户端中我必须创建一个 tensor_proto 来提供给占位符并且您不能创建大于 2 GB 的张量原型。所以作为解决方法,我将它们分成两半并在图中连接它们)

在我的模型中,我将签名保存如下(我试图让它尽可能简单,以帮助弄清楚如何使用多个输入)。

builder = saved_model_builder.SavedModelBuilder(export_path)

tensor_info_x = utils.build_tensor_info(model._input)
tensor_info_dropout = utils.build_tensor_info(model._dropout)
tensor_info_emb1 = utils.build_tensor_info(model._embeddingPlaceholder1)
tensor_info_emb2 = utils.build_tensor_info(model._embeddingPlaceholder2)
tensor_info_y = utils.build_tensor_info(model.softmaxPredictions)

prediction_signature = signature_def_utils.build_signature_def(
inputs={'inputs': tensor_info_x,
        'dropout': tensor_info_dropout,
        'googlew2v1': tensor_info_emb1,
        'googlew2v2': tensor_info_emb2
 },
 outputs={'softmaxPredictions': tensor_info_y},
 method_name=signature_constants.PREDICT_METHOD_NAME)

builder.add_meta_graph_and_variables(
    tfSession,
    [tag_constants.SERVING],
    signature_def_map={
       'softmaxPredictions': prediction_signature
})

builder.save()

在客户端中我进行推断:

def do_sem_inference(vs, data):

    host, port = CONFIG.semserver.split(':')
    channel = implementations.insecure_channel(host, int(port))
    stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)
    request = predict_pb2.PredictRequest()
    request.model_spec.name = 'sem'
    request.model_spec.signature_name = 'softmaxPredictions'

    proto = tf.contrib.util.make_tensor_proto(data, dtype=tf.int32)
    request.inputs['inputs'].CopyFrom(proto)

    dropoutProto = tf.contrib.util.make_tensor_proto(1.0, dtype=tf.float32)
    request.inputs['dropout'].CopyFrom(dropoutProto)

    #####
    # This is the reason I have to break the GoogleW2V in half, tensor_proto cannot be larger than 2GB
    #####

    googlew2vProto1 = tf.contrib.util.make_tensor_proto(vs.wordVectors()[:1500000], dtype=tf.float32)
    request.inputs['googlew2v1'].CopyFrom(googlew2vProto1)
    googlew2vProto2 = tf.contrib.util.make_tensor_proto(vs.wordVectors()[1500000:], dtype=tf.float32)
    request.inputs['googlew2v2'].CopyFrom(googlew2vProto2)

    result_future = stub.Predict.future(request, 100.0)
    results = tf.contrib.util.make_ndarray(result_future.result().outputs['outputs'])

但是我得到错误(如上所示):

Traceback (most recent call last):
  File "sem_client.py", line 121, in <module>
    tf.app.run()
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/platform/app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "sem_client.py", line 114, in main
    result = do_sem_inference(vectorSpace, embeddingLookup(vectorSpace, sentence))
  File "sem_client.py", line 66, in do_sem_inference
    results = tf.contrib.util.make_ndarray(result_future.result().outputs['outputs'])
  File "/usr/local/lib/python2.7/dist-packages/grpc/beta/_client_adaptations.py", line 112, in result
    raise _abortion_error(rpc_error_call)
grpc.framework.interfaces.face.face.AbortionError: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="Missing ModelSpec")

我在网上搜索了有关使用多个输入作为签名的帮助,有人说使用 exporter.generic_signature,但源代码说这已被弃用并改为使用 SavedModel。我还没有看到任何清楚的例子来说明如何使用 generic_signature。我还没有发现通过 SavedModel 使用多个签名输入的示例,知道如何让它工作吗?

感谢您的帮助和建议。

P.S。我也对避免将 googleW2V 嵌入分成两半并通过占位符输入它们的想法感兴趣(同样,由于需要提供此模型)。目标是查找 googleW2V 中的嵌入并在我的模型中使用它们(我知道不使用 googlew2v 嵌入的方法,但我更愿意使用这些)。

所以我想我弄清楚了正在发生的事情和手头的问题,一旦我坐下来思考它就有点傻了。

googlew2v 向量嵌入大约为 ~3GB。在我的服务客户端中,我试图为嵌入设置输入张量,然后进行 RPC 调用......必须有一些保护措施不允许我尝试对那么多数据进行 RPC (do'h)。这个错误不是很清楚,但是一旦我随机使用嵌入的一小部分,它就没问题了。

我想我可以为我的用例想出一个解决方法。但现在我无法让 googlew2v 嵌入成为我模型中的占位符(否则我必须在服务器期间提供它们并且它不允许我通过 RPC 发送非常大的数据。即使它做到了这将需要永远)。

我现在在我的项目中有一个解决方法(我只是在训练和服务之前进行嵌入查找等)。但是,如果可能的话,我希望可以选择通过变量或其他方式将 Googlew2v 嵌入包含在我的模型中,而不必将它们作为占位符(这样我就可以利用 tf.nn.embedding_lookup 并行性和速度)。

导出 pb 模型时可以在构建器中使用资产,使用 input_x = tf.placeholder(tf.string, ... )

定义模型时可以使用 able = lookup.index_table_from_file(vocab_path)