使用微调的Inception-v3模型预测单个图像

时间:2016-11-05 23:47:49

标签: python tensorflow

即使这里有很多问题提出重新使用经过训练的张量流模型的问题,但使用自定义数据集上微调的最主流模型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:0softmax:0可以提供自定义图像并从中检索答案,而在使用自定义微调模型时没有这么好的入口点。

例如,经过微调的Inception-v3模型冻结图将具有FIFOQueueQueueDequeueMany和类似的十几个张量,在实际卷积层之前从TFRecord读取批量并且输出张量将看起来像{ {1}}包含批次大小的形状无法使用,因此您没有适当的点来提供新的jpeg图像并获得预测。

是否有任何成功案例涉及使用此类批次投放的微调模型和新图像?或者可能有一些关于将TFRecord /批处理节点的输入包更改为JPEG的想法?

P.S。还有一种替代方法可以运行预先训练的模型,例如TF Serving,但是对于我来说,构建一个巨大的github仓库以及其他每一步都有很多依赖性。

1 个答案:

答案 0 :(得分: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())
    
  6. 使用冻结模型进行推理:

    1. 将模型加载到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
          )
      
    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})
      
    4. 提示:如何获取输入/输出节点/张量名称:

      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]
      

      我希望这会有所帮助。