TensorFlow ExportOutputs、PredictOuput 和指定 signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY

Sum*_*ron 5 python tensorflow tensorflow-serving tensorflow-estimator

语境

我有一个带有非常简单演示的colabEstimator目的是学习/理解EstimatorAPI,目的是为即插即用模型制定一个约定,其中包含有用的交易技巧(例如,如果验证通过,则提前停止)设置停止改进,导出模型等)。

这三个的Estimator模式(TRAINEVAL,和PREDICT)返回EstimatorSpec

根据文档

__new__(
    cls,
    mode,
    predictions=None,          # required by PREDICT
    loss=None,                 # required by TRAIN and EVAL
    train_op=None,             # required by TRAIN
    eval_metric_ops=None,
    export_outputs=None,
    training_chief_hooks=None,
    training_hooks=None,
    scaffold=None,
    evaluation_hooks=None,
    prediction_hooks=None.     
)
Run Code Online (Sandbox Code Playgroud)

在这些命名参数中,我想提请注意predictionsexport_outputs,它们在文档中被描述为:

  • predictions:预测张量或张量的字典。
  • export_outputs:描述要导出到SavedModel并在服务期间使用的输出签名。一个字典{name: output},其中:
    • name:此输出的任意名称。
    • output: 一个ExportOutput对象,例如ClassificationOutput, RegressionOutput, 或PredictOutput。单头模型只需要在这个字典中指定一个条目。多头模型应该为每个头指定一个条目,其中之一必须使用signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY. 如果未提供条目,PredictOutput则将创建到预测的默认映射。

因此应该清楚我为什么提出export_outputs;也就是说,因为人们最有可能在未来使用他们训练的模型(通过从 a 加载它SavedModel)。

为了使这个问题更容易理解/增加一些清晰度:

  • “单头”模型是人们遇到的最常见的模型,其中将input_fn features转换为单数(批处理)output

  • “多头”模型是具有多个输出的模型

例如,这个多头模型input_fn(根据Estimatorapi)返回一个元组,(features, labels)即这个模型有两个头)。

def input_fn():
  features = ...
  labels1 = ...
  labels2 = ...
  return features, {'head1': labels1, 'head2': labels2}
Run Code Online (Sandbox Code Playgroud)

如何指定signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY是这个问题的核心。即,如何指定它?(例如它应该是一个 dict {signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: head}

是的,所以在colab 中,您会看到我们的模型export_outputs实际上是以多头方式定义的(尽管不应该如此):

estimator functions > model_fn该的colab

def model_fn(...):

    # ...

    # send the features through the graph
    MODEL = build_fn(MODEL)

    # prediction
    MODEL['predictions'] = {'labels': MODEL['net_logits']} # <--- net_logits added in the build_fn

    MODEL['export_outputs'] = {
        k: tf.estimator.export.PredictOutput(v) for k, v in MODEL['predictions'].items()
    }

    # ...
Run Code Online (Sandbox Code Playgroud)

在这个特定的例子中,如果我们扩展字典理解,我们的功能相当于:

MODEL['export_outputs'] = {
    'labels': tf.estimator.export.PredictOutput(MODEL['net_logits'])
}
Run Code Online (Sandbox Code Playgroud)

它在这种情况下有效,因为我们的字典有一个键,因此有一个PredictOutput,而在colab 中,我们model_fn只有一个头部,格式更合适:

MODEL['export_outputs'] = {
    'predictions': tf.estimator.export.PredictOutput(MODEL['predictions'])
}
Run Code Online (Sandbox Code Playgroud)

正如它所述PredictOutput

__init__(outputs)
Run Code Online (Sandbox Code Playgroud)

在哪里

  • outputs:表示预测的张量或字符串的 dict 到张量。

因此,我的问题如下:

  1. 如果PredictOutput可以是一本字典,什么时候/为什么要使用多个PredictOutputs 作为他们export_outputsEstimatorSpec

  2. 如果一个人有一个多头模型,(比如有多个PredictOutputs)一个人如何实际指定signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY

  3. 什么是点predictionsEstimatorSpec时候,也“需要”(任何人谁在乎使用SavedModel收费)export_outputs

Kar*_*mel 1

感谢您提出详细的问题;你显然已经在这里挖得很深了。

  1. 还有 RegressionOutput 和 ClassificationOutput 类,它们不能是字典。使用export_outputs 字典可以对这些用例进行概括。

  2. 您希望从保存的模型默认提供服务的头部应采用默认签名密钥。例如:

export_outputs = {
  signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
    PredictOutput(outputs={'some_output_1': output_1}),
  'head-2': PredictOutput(outputs={'some_output_2': output_2}),
  'head-3': PredictOutput(outputs={'some_output_3': output_3})
}
Run Code Online (Sandbox Code Playgroud)
  1. 原因1:许多人使用默认的export_outputs(这又是预测的值),或者不导出到保存的模型。原因二:历史。预测是第一位的,随着时间的推移,越来越多的功能被添加。这些功能需要灵活性和额外信息,因此被独立打包到 EstimatorSpec 中。