【问题标题】:Use fine-tuned Inception-v3 model to predict on a single image使用微调的 Inception-v3 模型在单个图像上进行预测
【发布时间】:2017-03-19 13:50:29
【问题描述】:

尽管这里有很多关于 SO 提出重用训练过的 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 获取所需的输出层。

但问题在于,在 tensorflow 提供的示例中(例如,classify_image.py),这样的“冻结图”已经很好地准备了输入和输出点,分别如 DecodeJpeg/contents:0softmax:0,您可以在其中提供您的自定义图像并从中检索答案,而在使用自定义微调模型时,您没有这么好的入口点。

例如,微调的 Inception-v3 模型冻结图将在实际卷积层之前具有 FIFOQueueQueueDequeueMany 和类似的十几个张量,以从 TFRecord 读取批次,并且输出张量将看起来像 tower_0/logits/predictions 不可用包含批量大小的形状,因此您没有合适的点来输入新的 jpeg 图像并得到预测。

是否有任何成功案例涵盖了使用新图像批量馈送的微调模型?或者关于将 TFRecord/batch 节点的输入包更改为 JPEG 的一些想法?

附:还有一种运行预训练模型(例如 TF Serving)的替代方法,但构建一个巨大的 github 存储库,对每个其他步骤都有大量依赖项,这对我来说似乎是压倒性的。

【问题讨论】:

  • 您需要加载专门构建的推理图而不是训练图。 Slim、tf.contrib.learn.Estimator、keras 和其他框架都可以让你构建一个漂亮的推理图。

标签: python tensorflow


【解决方案1】:

我没有使用 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. 将模型加载到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})
    

提示:如何获取输入/输出节点/张量名称:

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]

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 2019-05-19
    • 1970-01-01
    • 2018-03-10
    • 2017-02-22
    • 2021-11-21
    相关资源
    最近更新 更多