首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tensorflow classifier.export_savedmodel (初学者)

Tensorflow classifier.export_savedmodel (初学者)
EN

Stack Overflow用户
提问于 2017-08-12 01:41:46
回答 3查看 8K关注 0票数 7

我知道“为Tensorflow模型提供服务”页面

https://www.tensorflow.org/serving/serving_basic

但是这些函数假设您使用的是tf.Session(),而DNNClassifier教程没有...然后我查看了DNNClassifier的api文档,它有一个导出函数( export_savedmodel函数已被弃用),它看起来很简单,但我得到了一个"'NoneType‘对象不可迭代“的错误……这意味着我传入了一个空变量,但我不确定我需要更改什么……实际上,我已经从tensorflow.org上的get_started/tflearn页面复制并粘贴了代码,但随后添加了

代码语言:javascript
复制
  directoryName = "temp"

  def serving_input_fn():
    print("asdf")

  classifier.export_savedmodel(
    directoryName,
    serving_input_fn
  )

就在classifier.fit函数调用之后...export_savedmodel的其他参数是可选的,我相信...有什么想法吗?

带代码的教程:https://www.tensorflow.org/get_started/tflearn#construct_a_deep_neural_network_classifier

export_savedmodel https://www.tensorflow.org/api_docs/python/tf/contrib/learn/DNNClassifier#export_savedmodel接口文档

EN

回答 3

Stack Overflow用户

发布于 2018-01-19 04:04:02

有两种TensorFlow应用程序:

假设您正在使用tf.Session()的函数是来自“低级”Tensorflow示例的函数,而

  • DNNClassifier教程是一个“高级”Tensorflow应用程序。

我将解释如何导出“高级”Tensorflow模型(使用export_savedmodel)。

函数export_savedmodel需要参数serving_input_receiver_fn,这是一个没有参数的函数,它定义了模型和预测器的输入。因此,您必须创建自己的serving_input_receiver_fn,其中模型输入类型与训练脚本中的模型输入相匹配,而predictor输入类型与测试脚本中的predictor输入相匹配。

另一方面,如果您创建一个自定义模型,您必须定义由函数tf.estimator.export.PredictOutput定义的export_outputs,该输入是一个字典,它定义了必须与测试脚本中的predictor输出的名称相匹配的名称。

例如:

训练脚本

代码语言:javascript
复制
def serving_input_receiver_fn():
    serialized_tf_example = tf.placeholder(dtype=tf.string, shape=[None], name='input_tensors')
    receiver_tensors      = {"predictor_inputs": serialized_tf_example}
    feature_spec          = {"words": tf.FixedLenFeature([25],tf.int64)}
    features              = tf.parse_example(serialized_tf_example, feature_spec)
    return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

def estimator_spec_for_softmax_classification(logits, labels, mode):
    predicted_classes = tf.argmax(logits, 1)
    if (mode == tf.estimator.ModeKeys.PREDICT):
        export_outputs = {'predict_output': tf.estimator.export.PredictOutput({"pred_output_classes": predicted_classes, 'probabilities': tf.nn.softmax(logits)})}
        return tf.estimator.EstimatorSpec(mode=mode, predictions={'class': predicted_classes, 'prob': tf.nn.softmax(logits)}, export_outputs=export_outputs) # IMPORTANT!!!
    onehot_labels = tf.one_hot(labels, 31, 1, 0)
    loss          = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels, logits=logits)
    if (mode == tf.estimator.ModeKeys.TRAIN):
        optimizer = tf.train.AdamOptimizer(learning_rate=0.01)
        train_op  = optimizer.minimize(loss, global_step=tf.train.get_global_step())
        return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
    eval_metric_ops = {'accuracy': tf.metrics.accuracy(labels=labels, predictions=predicted_classes)}
    return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

def model_custom(features, labels, mode):
    bow_column           = tf.feature_column.categorical_column_with_identity("words", num_buckets=1000)
    bow_embedding_column = tf.feature_column.embedding_column(bow_column, dimension=50)   
    bow                  = tf.feature_column.input_layer(features, feature_columns=[bow_embedding_column])
    logits               = tf.layers.dense(bow, 31, activation=None)
    return estimator_spec_for_softmax_classification(logits=logits, labels=labels, mode=mode)

def main():
    # ...
    # preprocess-> features_train_set and labels_train_set
    # ...
    classifier     = tf.estimator.Estimator(model_fn = model_custom)
    train_input_fn = tf.estimator.inputs.numpy_input_fn(x={"words": features_train_set}, y=labels_train_set, batch_size=batch_size_param, num_epochs=None, shuffle=True)
    classifier.train(input_fn=train_input_fn, steps=100)
    full_model_dir = classifier.export_savedmodel(export_dir_base="C:/models/directory_base", serving_input_receiver_fn=serving_input_receiver_fn)

测试脚本

代码语言:javascript
复制
def main():
    # ...
    # preprocess-> features_test_set
    # ...
    with tf.Session() as sess:
        tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], full_model_dir)
        predictor   = tf.contrib.predictor.from_saved_model(full_model_dir)
        model_input = tf.train.Example(features=tf.train.Features( feature={"words": tf.train.Feature(int64_list=tf.train.Int64List(value=features_test_set)) })) 
        model_input = model_input.SerializeToString()
        output_dict = predictor({"predictor_inputs":[model_input]})
        y_predicted = output_dict["pred_output_classes"][0]

(在Python 3.6.3,Tensorflow 1.4.0中测试的代码)

票数 17
EN

Stack Overflow用户

发布于 2018-09-07 20:15:43

如果你试图在tensorflow >1.6时使用predictor,你可能会得到这个错误:

代码语言:javascript
复制
signature_def_key "serving_default". Available signatures are ['predict']. Original error:
No SignatureDef with key 'serving_default' found in MetaGraphDef.

以下是在1.7.0上测试的工作示例:

保存:

首先,您需要以dict格式定义特征长度,如下所示:

代码语言:javascript
复制
feature_spec = {'x': tf.FixedLenFeature([4],tf.float32)}

然后,您必须构建一个函数,该函数具有与要素形状相同的占位符,并使用tf.estimator.export.ServingInputReceiver返回

代码语言:javascript
复制
def serving_input_receiver_fn():
    serialized_tf_example = tf.placeholder(dtype=tf.string,
                                         shape=[None],
                                         name='input_tensors')
    receiver_tensors = {'inputs': serialized_tf_example}

    features = tf.parse_example(serialized_tf_example, feature_spec)
    return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

然后用export_savedmodel保存:

代码语言:javascript
复制
classifier.export_savedmodel(dir_path, serving_input_receiver_fn)

完整示例代码:

代码语言:javascript
复制
import os
from six.moves.urllib.request import urlopen

import numpy as np
import tensorflow as tf


dir_path = os.path.dirname('.')

IRIS_TRAINING = os.path.join(dir_path,  "iris_training.csv")
IRIS_TEST = os.path.join(dir_path,   "iris_test.csv") 

feature_spec = {'x': tf.FixedLenFeature([4],tf.float32)}

def serving_input_receiver_fn():
    serialized_tf_example = tf.placeholder(dtype=tf.string,
                                         shape=[None],
                                         name='input_tensors')
    receiver_tensors = {'inputs': serialized_tf_example}

    features = tf.parse_example(serialized_tf_example, feature_spec)
    return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)




def main():
    training_set = tf.contrib.learn.datasets.base.load_csv_with_header(
        filename=IRIS_TRAINING,
        target_dtype=np.int,
        features_dtype=np.float32)
    test_set = tf.contrib.learn.datasets.base.load_csv_with_header(
        filename=IRIS_TEST,
        target_dtype=np.int,
        features_dtype=np.float32)

    feature_columns = [tf.feature_column.numeric_column("x", shape=[4])]


    classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns,
                                          hidden_units=[10, 20, 10],
                                          n_classes=3,
                                          model_dir=dir_path)
  # Define the training inputs
    train_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={"x": np.array(training_set.data)},
      y=np.array(training_set.target),
      num_epochs=None,
      shuffle=True)

  # Train model.
    classifier.train(input_fn=train_input_fn, steps=200)


    classifier.export_savedmodel(dir_path, serving_input_receiver_fn)


if __name__ == "__main__":
    main()

正在恢复

现在让我们恢复模型:

代码语言:javascript
复制
import tensorflow as tf 
import os

dir_path = os.path.dirname('.') #current directory
exported_path= os.path.join(dir_path,  "1536315752")

def main():
    with tf.Session() as sess:

        tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], exported_path)

        model_input= tf.train.Example(features=tf.train.Features(feature={
                'x': tf.train.Feature(float_list=tf.train.FloatList(value=[6.4, 3.2, 4.5, 1.5]))        
                })) 

        predictor= tf.contrib.predictor.from_saved_model(exported_path)

        input_tensor=tf.get_default_graph().get_tensor_by_name("input_tensors:0")

        model_input=model_input.SerializeToString()

        output_dict= predictor({"inputs":[model_input]})

        print(" prediction is " , output_dict['scores'])


if __name__ == "__main__":
    main()

以下是包含数据和说明的Ipython notebook demo示例:

票数 3
EN

Stack Overflow用户

发布于 2017-08-12 05:57:44

有两个可能的问题和答案。首先,您会遇到DNNClassifier的会话丢失,它使用更高级的估计器API (而不是更低级的API,您可以自己操作操作)。tensorflow的好处在于,所有的高级和低级API或多或少都是可互操作的,所以如果您想要一个会话并对该会话执行某些操作,只需添加以下内容:

代码语言:javascript
复制
sess = tf.get_default_session()

您可以在本教程的其余部分开始挂接。

对您的问题的第二种解释是,实际上export_savedmodel和serving教程中的示例代码试图实现相同的目标,那么export_savedmodel呢?当你训练你的图表时,你设置了一些基础设施来向图表提供输入(通常是来自训练数据集的批次),然而,当你切换到“服务”时,你通常会从其他地方读取你的输入,并且你需要一些单独的基础设施来取代用于训练的图表的输入。底线是,您用打印填充的serving_input_fn()本质上应该返回一个输入操作。在documentation中也提到了这一点

serving_input_fn:不带参数并返回InputFnOps的函数。

因此,它应该做一些类似于添加输入链的事情,而不是print("asdf") (这应该类似于builder.add_meta_graph_and_variables正在添加的内容)。

例如,可以在(在cloudml示例中)[https://github.com/GoogleCloudPlatform/cloudml-samples/blob/master/census/customestimator/trainer/model.py#L240]中找到serving_input_fn()的示例。

代码语言:javascript
复制
def json_serving_input_fn():
  """Build the serving inputs."""
  inputs = {}
  for feat in INPUT_COLUMNS:
    inputs[feat.name] = tf.placeholder(shape=[None], dtype=feat.dtype)
  return tf.estimator.export.ServingInputReceiver(inputs, inputs)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45640951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档