即使这里有很多问题提出重新使用经过训练的张量流模型的问题,但使用自定义数据集上微调的最主流模型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读取批量并且输出张量将看起来像{ {1}}包含批次大小的形状无法使用,因此您没有适当的点来提供新的jpeg图像并获得预测。
是否有任何成功案例涉及使用此类批次投放的微调模型和新图像?或者可能有一些关于将TFRecord /批处理节点的输入包更改为JPEG的想法?
P.S。还有一种替代方法可以运行预先训练的模型,例如TF Serving,但是对于我来说,构建一个巨大的github仓库以及其他每一步都有很多依赖性。
答案 0 :(得分:0)
我没有使用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())
使用冻结模型进行推理:
将模型加载到graph
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]
我希望这会有所帮助。