本文介绍了TF 估计器:无法从保存的模型加载 *.pb的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 TF Estimator 创建了一个简单的模型,并使用 export_savedmodel 函数保存模型.我使用了一个简单的 Iris 数据集,它有 4 个特征.

I create a simple model using TF Estimator and save the model using export_savedmodel function. I use a simple Iris dataset which has 4 features.

num_epoch = 50
num_train = 120
num_test = 30

# 1 Define input function
def input_function(x, y, is_train):
    dict_x = {
        "thisisinput" : x,
    }

    dataset = tf.data.Dataset.from_tensor_slices((
        dict_x, y
    ))

    if is_train:
        dataset = dataset.shuffle(num_train).repeat(num_epoch).batch(num_train)
    else:   
        dataset = dataset.batch(num_test)

    return dataset

def my_serving_input_fn():
    input_data = {
        "thisisinput" : tf.placeholder(tf.float32, [None, 4], name='inputtensors')
    }
    return tf.estimator.export.ServingInputReceiver(input_data, input_data)

def main(argv):
    tf.set_random_seed(1103) # avoiding different result of random

    # 2 Define feature columns
    feature_columns = [
        tf.feature_column.numeric_column(key="thisisinput",shape=4),
    ]

    # 3 Define an estimator
    classifier = tf.estimator.DNNClassifier(
        feature_columns=feature_columns,
        hidden_units=[10],
        n_classes=3,
        optimizer=tf.train.GradientDescentOptimizer(0.001),
        activation_fn=tf.nn.relu,
        model_dir = 'modeliris2/'
    )

    # Train the model
    classifier.train(
        input_fn=lambda:input_function(xtrain, ytrain, True)
    )

    # Evaluate the model
    eval_result = classifier.evaluate(
        input_fn=lambda:input_function(xtest, ytest, False)
    )

    print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
    print('\nSaving models...')
    classifier.export_savedmodel("modeliris2pb", my_serving_input_fn)

if __name__ == "__main__":
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' 
    tf.app.run(main)

运行程序后,它会生成一个文件夹,其中包含 saved_model.pb.我看到很多教程建议使用 contrib.predictor 加载 saved_model.pb 但我不能.我使用 contrib.predictor 函数来加载模型:

After running the program, it produces a folder which contains saved_model.pb. I see many tutorials suggest to use contrib.predictor to load saved_model.pb but I can't. I've use contrib.predictor function to load the model:

def main(a):
    with tf.Session() as sess:
        PB_PATH= "modeliris2pb/1536219836/"
        predict_fn = predictor.from_saved_model(PB_PATH)

if __name__=="__main__":
    main()

但它产生了一个错误:

ValueError: 得到了 signature_def_key "serving_default".可用的签名是['预测'].原始错误:没有带密钥的 SignatureDef在 MetaGraphDef 中找到serving_default".

还有其他更好的方法来加载 *.pb 文件吗?为什么会发生这个错误?我怀疑是因为 my_serving_input_fn() 函数,但我不知道为什么

Is there another way that is better to load *.pb files? Why does this error happen? I'm suspicious it is because the my_serving_input_fn() function, but I don't know why

推荐答案

我遇到了同样的问题,我试图在网上搜索但没有解释,所以我尝试了不同的方法:

I was facing same issue , I tried to search on web but there are no explanation about this so i tried different approach:

首先你需要像这样以字典格式定义特征长度:

First you need to define features length in dict format like this:

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

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

Then you have to build a function which have placeholder with same shape of features and return using tf.estimator.export.ServingInputReceiver

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 保存:

Then just save with export_savedmodel :

classifier.export_savedmodel(dir_path, serving_input_receiver_fn)

完整示例代码:

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()

正在恢复

现在让我们恢复模型:

Restoring

Now let's restore the model :

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 演示示例:

Here is Ipython notebook demo example with data and explanation :

这篇关于TF 估计器:无法从保存的模型加载 *.pb的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 07:28