2016-11-05 36 views
3

尽管这里有很多问题提出了重复使用经过训练的tensorflow模型的问题,但使用最主流的模型Inception-v3罚款仍然是一个挑战调整自定义数据集以仅预测某个单一图像的概率。使用微调的Inception-v3模型来预测单个图像

在对这个话题做了一些研究之后(最相似的SO-thread肯定是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获取所需的输出图层。

但问题是,配备tensorflow(如classify_image.py),这样的«冻结图»例子的有精心准备的输入和输出点像DecodeJpeg/contents:0softmax:0分别在那里你可以养活你的自定义图像,并检索答案来自于,而您在使用自定义微调模型时没有这样好的切入点。

例如,微调启-V3模型冷冻图表将收到实际卷积层张量的FIFOQueueQueueDequeueMany和类似的打读取来自TFRecord的与输出张量将看起来像tower_0/logits/predictions与不可用的形状含有批量大小批次,所以你只是没有适当的点来提供一个新的JPEG图像,并得到预测。

是否有任何成功的故事报道这种批量馈送的微调模型与新图像的使用?或者,也许有关于将TFRecord/batch节点的输入包更改为JPEG的想法?

P.S.还有一种替代方式可以运行预训练模型,比如TF Serving,但是建立一个巨大的github回购库,每个其他步骤都有大量的依赖关系,这对我来说似乎压倒一切。

+0

您需要加载专门构建的推理图,而不是训练图。 Slim,tf.contrib.learn.Estimator,keras和其他框架都允许您构建一个很好的推理图。 –

回答

0

我没有使用Inception-v3模型,但是我找到了解决类似情况的方法。 对于培训,我使用自定义多进程/多线程设置将我的样本分批加载并将它们送入FIFOQueue。在冻结图上运行推理总是无限期地挂起。 这里是我的方法:

创建冻结推理模型:

  1. 建立一个完全独立的推理图。为您的输入创建占位符[in1,in2,...](形状对应于1个样本),并以与培训相同的方式创建模型。您的模型的输出在下文中将被称为[out1,out2...]
  2. 使用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) 
    
  3. 创建一个冻结图:

    frozen_graph_def = graph_util.convert_variables_to_constants(
        sess, 
        input_graph_def, 
        output_node_names) 
    
  4. 优化模型:

    optimized_graph_def = optimize_for_inference_lib.optimize_for_inference(
        frozen_graph_def, 
        input_node_names, 
        output_node_names, tf.float32.as_datatype_enum) 
    
  5. 保存模型:

    with tf.gfile.GFile(filename, "wb") as f: 
        f.write(optimized_graph_def.SerializeToString()) 
    

执行推断与冻结模式:

  1. 负荷模型到

    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 
        ) 
    
  2. 访问您的输入/输出:

    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]) 
    ... 
    
  3. 运行推论:

    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] 

我希望这有助于。

相关问题