虽然这里有很多问题提出重新使用经过训练的张量流模型的问题,但使用自定义数据集上微调的最主流模型Inception-v3来预测某些单个图像的概率仍然是一个挑战.
在对这个主题做了一些研究之后(最相似的SO线程被证实是Tensorflow: restoring a graph and model then running evaluation on a single image)我可以得出结论,一些训练模型的冻结graph.pb文件就像有一个圣杯,因为你不需要重建图形,选择要恢复的张量或其他 – 只需调用tf.import_graph_def并通过sess.graph.get_tensor_by_name获取所需的输出层.
但问题是在提供张量流的例子中(例如classify_image.py),这样的“冻结图”有很好的输入和输出点,如DecodeJpeg / contents:0和softmax:0,你可以在这里提供自定义图像并且在使用自定义微调模型时没有这么好的入口点时检索答案.
例如,微调的Inception-v3模型冻结图将具有FIFOQueue,QueueDequeueMany和类似的十几个张量,在实际卷积层之前从TFRecord读取批次,输出张量看起来像是包含批量大小的不可用形状的tower_0 / logits / predictions,所以你只是没有适当的点来提供新的jpeg图像并获得预测.
是否有任何成功案例涉及使用此类批次馈送微调模型的新图像?或者可能有一些关于将TFRecord /批处理节点的输入包更改为JPEG的想法?
附:还有一个替代方案可以运行预先训练的模型,比如TF Serving,但是对于我来说,为每个其他步骤构建一个具有大量依赖关系的巨大的github repo似乎是压倒性的.
解决方法:
我没有使用Inception-v3模型,但我找到了类似情况的解决方案.
对于培训,我使用自定义多进程/多线程设置将我的样本加载到批处理中并将它们提供给FIFOQueue.冻结图上的运行推断始终无限期挂起.
这是我的方法:
创建冻结推理模型:
>构建一个完全独立的推理图.为输入创建占位符[in1,in2,…](形状对应于1个样本),并以与训练相同的方式创建模型.以下将模型的输出称为[out1,out2 …].
>使用tf.train.Saver()加载训练有素的模型参数(为此,新模型中的名称必须与训练模型中的名称相匹配).就像是:
loader = tf.train.Saver()
graph = tf.get_default_graph()
input_graph_def = graph.as_graph_def()
with tf.Session() as sess:
loader.restore(sess, input_checkpoint)
>创建冻结图:
frozen_graph_def = graph_util.convert_variables_to_constants(
sess,
input_graph_def,
output_node_names)
>优化模型:
optimized_graph_def = optimize_for_inference_lib.optimize_for_inference(
frozen_graph_def,
input_node_names,
output_node_names, tf.float32.as_datatype_enum)
>保存型号:
with tf.gfile.GFile(filename, "wb") as f:
f.write(optimized_graph_def.SerializeToString())
使用冻结模型进行推理:
>将模型加载到图表中
with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
tf.import_graph_def(
graph_def,
input_map=None,
return_elements=None,
name='',
op_dict=None,
producer_op_list=None
)
>访问您的输入/输出:
in1 = graph.get_tensor_by_name(input_tensor_names[0])
in2 = graph.get_tensor_by_name(input_tensor_names[1])
...
out1 = graph.get_tensor_by_name(output_tensor_names[0])
...
>运行推理:
with tf.Session(graph=graph) as sess:
sess.run([out1], feed_dict={in1: {data}, in2: {data})
提示:如何获取输入/输出节点/张量名称:
inputs = [in1, in2...]
outputs = [out1, out2...]
output_tensor_names = [n.name for n in outputs]
input_tensor_names = [n.name for n in inputs]
output_node_names = [n[:str(n).find(":")] for n in output_tensor_names]
input_node_names = [n[:str(n).find(":")] for n in input_tensor_names]
我希望这有帮助.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。