我正在使用tf.estimator.Estimator
来训练模型:
def model_fn(features, labels, mode, params, config):
input_image = features["input_image"]
eval_metric_ops = {}
predictions = {}
# Create model
with tf.name_scope('Model'):
W = tf.Variable(tf.zeros([784, 10]), name="W")
b = tf.Variable(tf.zeros([10]), name="b")
logits = tf.nn.softmax(tf.matmul(input_image, W, name="MATMUL") + b, name="logits")
loss = None
train_op = None
if mode != tf.estimator.ModeKeys.PREDICT:
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits))
train_op = tf.contrib.layers.optimize_loss(loss=loss,
global_step=tf.contrib.framework.get_global_step(),
learning_rate=params["learning_rate"],
optimizer=params["optimizer"])
# Add prediction
classes = tf.as_string(tf.argmax(input=logits, axis=1, name="class"))
with tf.name_scope('Predictions'):
predictions["logits"] = logits
predictions["classes"] = classes
export_outputs = {"classes": tf.estimator.export.ClassificationOutput(classes=classes)}
export_outputs = {"classes": tf.estimator.export.PredictOutput({"labels": classes})}
spec = tf.estimator.EstimatorSpec(mode=mode,
predictions=predictions,
loss=loss,
train_op=train_op,
eval_metric_ops=eval_metric_ops,
export_outputs=export_outputs,
training_chief_hooks=None,
training_hooks=None,
scaffold=None)
return spec
def input_fn(dataset, n=10):
return dataset.images[:n], dataset.labels[:n]
model_params = {"learning_rate": 1e-3,
"optimizer": "Adam"}
#run_path = os.path.join(runs_path, datetime.now().strftime("%Y-%m-%d-%H-%M-%S"))
run_path = os.path.join(runs_path, "run1")
if os.path.exists(run_path):
shutil.rmtree(run_path)
estimator = tf.estimator.Estimator(model_fn=model_fn, model_dir=run_path, params=model_params)
# Train
inputs = lambda: input_fn(mnist.train, n=15)
estimator.train(input_fn=inputs, steps=1000)
在训练期间正确保存模型和重量。
现在我想在另一个脚本中重新加载模型+权重以进行预测。
但我不知道如何指定输入,因为我在model_fn
函数中没有引用它。
# Get some data to predict
input_data = mnist.test.images[:5]
tf.reset_default_graph()
run_path = os.path.join(runs_path, "run1")
# Load the model (graph)
input_checkpoint = os.path.join(run_path, "model.ckpt-1000")
saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=True)
# Restore the weights
sess = tf.InteractiveSession()
saver.restore(sess, input_checkpoint)
graph = sess.graph
# Get the op to compute for prediction
predict_op = graph.get_operation_by_name("Predictions/class")
# predictions = sess.run(predict_op, feed_dict=????)
以下是返回graph.get_collection("variables")
:
[<tf.Variable 'global_step:0' shape=() dtype=int64_ref>,
<tf.Variable 'Model/W:0' shape=(784, 10) dtype=float32_ref>,
<tf.Variable 'Model/b:0' shape=(10,) dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/learning_rate:0' shape=() dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/beta1_power:0' shape=() dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/beta2_power:0' shape=() dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/Model/W/Adam:0' shape=(784, 10) dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/Model/W/Adam_1:0' shape=(784, 10) dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/Model/b/Adam:0' shape=(10,) dtype=float32_ref>,
<tf.Variable 'OptimizeLoss/Model/b/Adam_1:0' shape=(10,) dtype=float32_ref>]
我是否需要为输入指定tf.placeholder
?但那么Tensorflow如何知道输入应该为这个特定的占位符提供信息呢?
此外,如果我在模型的开头指定类似features = tf.constant(features, name="input")
的内容,我就不能使用它,因为它不是Tensor而是操作。
修改
经过更多调查后,我发现我需要使用Estimator.export_savedmodel()
方法保存我的模型(并且在使用估算器进行培训时不会重新使用自动保存的检查点。
feature_spec = {"input_image": tf.placeholder(dtype=tf.float32, shape=[None, 784])}
input_receiver_fn = tf.estimator.export.build_raw_serving_input_receiver_fn(feature_spec)
estimator.export_savedmodel(model_path, input_receiver_fn, as_text=True)
然后我尝试加载模型并做预测,但我不知道如何用我的numpy图像提供模型:
preds = sess.run("class", feed_dict={"input_image": input_data})
除了错误:
/home/hadim/local/conda/envs/ws/lib/python3.6/site-packages/tensorflow/python/client/session.py in run(self, fetches, feed_dict, options, run_metadata)
776 try:
777 result = self._run(None, fetches, feed_dict, options_ptr,
--> 778 run_metadata_ptr)
779 if run_metadata:
780 proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)
/home/hadim/local/conda/envs/ws/lib/python3.6/site-packages/tensorflow/python/client/session.py in _run(self, handle, fetches, feed_dict, options, run_metadata)
931 except Exception as e:
932 raise TypeError('Cannot interpret feed_dict key as Tensor: '
--> 933 + e.args[0])
934
935 if isinstance(subfeed_val, ops.Tensor):
TypeError: Cannot interpret feed_dict key as Tensor: The name 'input_image' looks like an (invalid) Operation name, not a Tensor. Tensor names must be of the form "<op_name>:<output_index>".
答案 0 :(得分:2)
对于TypeError,我以这种方式解决它。
首先,为占位符命名:
feature_spec = {"input_image": tf.placeholder(dtype=tf.float32, shape=[None, 784], name='input_image')}
然后你可以像这样使用它:
feed_dict={"input_image:0": input_data}
希望它可以帮助别人。
修改
在这个问题中,在estimator.export_savedmodel(...)
之后
你可以做这样的预测:
with tf.Session(graph=tf.Graph()) as sess:
meta_graph_def = tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], model_path)
signature = meta_graph_def.signature_def
x_tensor_name = signature['classes'].inputs['input_image'].name
y_tensor_name = signature['classes'].outputs['labels'].name
x = sess.graph.get_tensor_by_name(x_tensor_name)
y = sess.graph.get_tensor_by_name(y_tensor_name)
predictions = sess.run(y, {x: mnist.test.images[:5]})
答案 1 :(得分:0)
输入Tensor的名称可能是input_image:0
。
您可以通过以下方式列出已保存模型的签名:
print(estimator.signature_def[tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY])
那应列出预期的输入/输出张量。
答案 2 :(得分:0)
我通过使用tensorflow.contrib.predictor
成功预测:
from tensorflow.contrib import predictor
predict_fn = predictor.from_saved_model(
export_dir='model/1535012949', # your model path
signature_def_key='predict',
)
predictions = predict_fn({'examples': examples}) # FYI, rename to `input_image`
但是我也想通过session
和tensors
进行预测,以便可以将转换模型与其他语言一起使用。期待一些完美的答案!
答案 3 :(得分:-1)
我正在使用tf.contrib.learn.Estimator。 正如我所看到的,语法和方法签名几乎相同,所以我认为差异与几个Tensorflow版本有关。 因此,您可以像往常一样使用
创建Estimatorestimator = learn.Estimator(
model_fn=your_model,
model_dir="tmp",
config=tf.contrib.learn.RunConfig(
save_checkpoints_steps=10,
save_summary_steps=10,
save_checkpoints_secs=None
)
)
然后你按estimator.fit(input_fn=input_function, steps=100)
然后你可以做预测调用
estimator .predict(prediction)
Mote,有一个技巧,与Tensorflow的known issue有关。调用predict
无法正确初始化Estimator,因此您需要调用
estimator.evaluate(x=prediction, y=label_array, steps=1)
在致电predict
之前。
希望,这有帮助。