【问题标题】:Tensorflow, Tensorflow-serving: Multiple inputs for SavedModel signatureTensorflow,Tensorflow-serving:SavedModel 签名的多个输入
【发布时间】:2017-11-23 06:24:35
【问题描述】:

我正在尝试导出我的模型以通过 SavedModel 进行服务,并且在执行推理调用时遇到了服务客户端的问题。

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

我有 4 个必须提供的占位符,输入、丢弃(推理时将是 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 对签名使用多个输入的示例,知道如何让它工作吗?

感谢您的帮助和建议。

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

【问题讨论】:

  • 你如何开始你的张量流服务?我可以看到你启动命令吗?期望意味着您没有通过model_spec,但是在您的代码中您确实设置了该值,所以我不太确定您的问题;附言您可以将嵌入加载为变量并将它们作为推理图的一部分导出。如果它们太大,您可以将它们分成分区。
  • tf-serving/serving$ bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9002 --model_name=sem --model_base_path=/home/dev/sem/export/CW11Sem/ 现在对于嵌入,我将它们作为变量加载。我创建一个变量和一个占位符,然后将占位符分配给变量并通过 feed_dict 提供占位符:self.X = tf.Variable(tf.constant(0.0, shape=[1500000, 300]), trainable=False, name="X") self._embeddingPlaceholder1 = tf.placeholder(tf.float32, [1500000,300]) self.set_x = self.X.assign(self._embeddingPlaceholder)
  • 无法编辑我看到的错字,嵌入代码是正确的,忽略最后 self._embeddingPlaceholder 上缺少的 1
  • 所以我更相信这个问题实际上是由于多输入签名。我能够删除/处理额外的占位符(因此我只有输入作为占位符),并且我能够导出、服务器并从相同的模型减去额外的占位符(因此签名输入)得到结果。我会尝试让这个工作,但仍然会喜欢额外的占位符和输入签名问题的一些帮助......
  • 您可以通过数组初始化一个变量,而不是通过占位符分配它们,如果这样做将只有 2 个占位符:tensor_info_x 和 tensor_info_dropout,并且导出模型时签名中有 2 个输入项。跨度>

标签: tensorflow tensorflow-serving


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    导出pb模型时可以在builder中使用asset,使用input_x = tf.placeholder(tf.string, ... )定义模型时可以使用able = lookup.index_table_from_file(vocab_path)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2021-12-26
      相关资源
      最近更新 更多