I think it would be immensely helpful to the Tensorflow community if there was a well-documented solution to the crucial task of testing a single new image against the model created by the convnet in the CIFAR-10 tutorial.

我认为如果有针对CIFAR-10教程中由convnet创建的模型测试单个新图像的关键任务的详细解决方案,那么Tensorflow社区将会非常有用。

I may be wrong, but this critical step that makes the trained model usable in practice seems to be lacking. There is a "missing link" in that tutorial—a script that would directly load a single image (as array or binary), compare it against the trained model, and return a classification.

我可能错了,但是这个让训练有素的模型在实践中可用的关键步骤似乎缺乏。该教程中有一个“缺失的链接” - 一个直接加载单个图像(作为数组或二进制文件)的脚本,将其与训练模型进行比较,然后返回分类。

Prior answers give partial solutions that explain the overall approach, but none of which I've been able to implement successfully. Other bits and pieces can be found here and there, but unfortunately haven't added up to a working solution. Kindly consider the research I've done, before tagging this as duplicate or already answered.

先前的答案提供了解释整体方法的部分解决方案,但我没有能够成功实施。其他零碎可以在这里和那里找到,但遗憾的是还没有添加到一个可行的解决方案。在将此标记为重复或已经回答之前,请考虑我已完成的研究。

Tensorflow: how to save/restore a model?

Tensorflow:如何保存/恢复模型?

Restoring TensorFlow model

恢复TensorFlow模型

Unable to restore models in tensorflow v0.8

无法在tensorflow v0.8中恢复模型

https://gist.github.com/nikitakit/6ef3b72be67b86cb7868

https://gist.github.com/nikitakit/6ef3b72be67b86cb7868

The most popular answer is the first, in which @RyanSepassi and @YaroslavBulatov describe the problem and an approach: one needs to "manually construct a graph with identical node names, and use Saver to load the weights into it". Although both answers are helpful, it is not apparent how one would go about plugging this into the CIFAR-10 project.

最流行的答案是第一个,其中@RyanSepassi和@YaroslavBulatov描述了问题和方法:人们需要“手动构建具有相同节点名称的图形,并使用Saver将权重加载到其中”。虽然这两个答案都很有帮助,但是如何将其插入CIFAR-10项目并不明显。

A fully functional solution would be highly desirable so we could port it to other single image classification problems. There are several questions on SO in this regard that ask for this, but still no full answer (for example Load checkpoint and evaluate single image with tensorflow DNN).

一个功能齐全的解决方案非常需要,因此我们可以将其移植到其他单个图像分类问题中。在这方面有几个问题要求,但仍然没有完整的答案(例如加载检查点和评估具有张量流DNN的单个图像)。

I hope we can converge on a working script that everyone could use.

我希望我们能够集中在每个人都可以使用的工作脚本上。

The below script is not yet functional, and I'd be happy to hear from you on how this can be improved to provide a solution for single-image classification using the CIFAR-10 TF tutorial trained model.

以下脚本尚未正常运行,我很高兴听到您如何改进,以便使用CIFAR-10 TF教程训练模型为单图像分类提供解决方案。

Assume all variables, file names etc. are untouched from the original tutorial.

假设所有变量,文件名等都不受原始教程的影响。

New file: cifar10_eval_single.py

新文件:cifar10_eval_single.py

import cv2
import tensorflow as tf

FLAGS = tf.app.flags.FLAGS

tf.app.flags.DEFINE_string('eval_dir', './input/eval',
                           """Directory where to write event logs.""")
tf.app.flags.DEFINE_string('checkpoint_dir', './input/train',
                           """Directory where to read model checkpoints.""")

def get_single_img():
    file_path = './input/data/single/test_image.tif'
    pixels = cv2.imread(file_path, 0)
    return pixels

def eval_single_img():

    # below code adapted from @RyanSepassi, however not functional
    # among other errors, saver throws an error that there are no
    # variables to save
    with tf.Graph().as_default():

        # Get image.
        image = get_single_img()

        # Build a Graph.
        # TODO

        # Create dummy variables.
        x = tf.placeholder(tf.float32)
        w = tf.Variable(tf.zeros([1, 1], dtype=tf.float32))
        b = tf.Variable(tf.ones([1, 1], dtype=tf.float32))
        y_hat = tf.add(b, tf.matmul(x, w))

        saver = tf.train.Saver()

        with tf.Session() as sess:
            sess.run(tf.initialize_all_variables())
            ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)

            if ckpt and ckpt.model_checkpoint_path:
                saver.restore(sess, ckpt.model_checkpoint_path)
                print('Checkpoint found')
            else:
                print('No checkpoint found')

            # Run the model to get predictions
            predictions = sess.run(y_hat, feed_dict={x: image})
            print(predictions)

def main(argv=None):
    if tf.gfile.Exists(FLAGS.eval_dir):
        tf.gfile.DeleteRecursively(FLAGS.eval_dir)
    tf.gfile.MakeDirs(FLAGS.eval_dir)
    eval_single_img()

if __name__ == '__main__':
    tf.app.run()

4 个解决方案

#1


7

There are two methods to feed a single new image to the cifar10 model. The first method is a cleaner approach but requires modification in the main file, hence will require retraining. The second method is applicable when a user does not want to modify the model files and instead wants to use the existing check-point/meta-graph files.

将单个新图像提供给cifar10模型有两种方法。第一种方法是更简洁的方法,但需要在主文件中进行修改,因此需要重新训练。当用户不想修改模型文件而是想要使用现有的检查点/元图文件时,第二种方法是适用的。

The code for the first approach is as follows:

第一种方法的代码如下:

import tensorflow as tf
import numpy as np
import cv2

sess = tf.Session('', tf.Graph())
with sess.graph.as_default():
    # Read meta graph and checkpoint to restore tf session
    saver = tf.train.import_meta_graph("/tmp/cifar10_train/model.ckpt-200.meta")
    saver.restore(sess, "/tmp/cifar10_train/model.ckpt-200")

    # Read a single image from a file.
    img = cv2.imread('tmp.png')
    img = np.expand_dims(img, axis=0)

    # Start the queue runners. If they are not started the program will hang
    # see e.g. https://www.tensorflow.org/programmers_guide/reading_data
    coord = tf.train.Coordinator()
    threads = []
    for qr in sess.graph.get_collection(tf.GraphKeys.QUEUE_RUNNERS):
        threads.extend(qr.create_threads(sess, coord=coord, daemon=True,
                                         start=True))

    # In the graph created above, feed "is_training" and "imgs" placeholders.
    # Feeding them will disconnect the path from queue runners to the graph 
    # and enable a path from the placeholder instead. The "img" placeholder will be 
    # fed with the image that was read above.
    logits = sess.run('softmax_linear/softmax_linear:0', 
                     feed_dict={'is_training:0': False, 'imgs:0': img})

    #Print classifiction results.
    print(logits) 

The script requires that a user creates two placeholders and a conditional execution statement for it to work.

该脚本要求用户创建两个占位符和条件执行语句以使其起作用。

The placeholders and conditional execution statement are added in cifar10_train.py as shown below:

占位符和条件执行语句添加在cifar10_train.py中,如下所示:

def train():   
"""Train CIFAR-10 for a number of steps."""   
    with tf.Graph().as_default():
        global_step = tf.contrib.framework.get_or_create_global_step()

    with tf.device('/cpu:0'):
        images, labels = cifar10.distorted_inputs()

    is_training = tf.placeholder(dtype=bool,shape=(),name='is_training')
    imgs = tf.placeholder(tf.float32, (1, 32, 32, 3), name='imgs')
    images = tf.cond(is_training, lambda:images, lambda:imgs)
    logits = cifar10.inference(images)

The inputs in cifar10 model are connected to queue runner object which is a multistage queue that can prefetch data from files in parallel. See a nice animation of queue runner here

cifar10模型中的输入连接到队列运行器对象,该对象是一个多级队列,可以并行从文件中预取数据。在这里查看一个漂亮的队列运动员动画

While queue runners are efficient in prefetching large dataset for training, they are an overkill for inference/testing where only a single file is needed to be classified, also they are a bit more involved to modify/maintain. For that reason, I have added a placeholder "is_training", which is set to False while training as shown below:

虽然队列运行器在预取大型数据集以进行训练时非常有效,但它们对于推理/测试来说是一种过度杀伤,其中只需要对单个文件进行分类,修改/维护也需要更多参与。出于这个原因,我添加了一个占位符“is_training”,在训练时设置为False,如下所示:

 import numpy as np
 tmp_img = np.ndarray(shape=(1,32,32,3), dtype=float)
 with tf.train.MonitoredTrainingSession(
     checkpoint_dir=FLAGS.train_dir,
     hooks=[tf.train.StopAtStepHook(last_step=FLAGS.max_steps),
            tf.train.NanTensorHook(loss),
            _LoggerHook()],
     config=tf.ConfigProto(
         log_device_placement=FLAGS.log_device_placement)) as mon_sess:
   while not mon_sess.should_stop():
     mon_sess.run(train_op, feed_dict={is_training: True, imgs: tmp_img})

Another placeholder "imgs" holds a tensor of shape (1,32,32,3) for the image that will be fed during inference -- the first dimension is the batch size which is one in this case. I have modified cifar model to accept 32x32 images instead of 24x24 as the original cifar10 images are 32x32.

另一个占位符“imgs”对于将在推理期间馈送的图像保持形状的张量(1,32,32,3) - 第一个维度是批量大小,在这种情况下是一个。我修改了cifar模型以接受32x32图像而不是24x24,因为原始cifar10图像是32x32。

Finally, the conditional statement feeds the placeholder or queue runner output to the graph. The "is_training" placeholder is set to False during inference and "img" placeholder is fed a numpy array -- the numpy array is reshaped from 3 to 4 dimensional vector to conform to the input tensor to inference function in the model.

最后,条件语句将占位符或队列运行器输出提供给图形。在推理期间,“is_training”占位符被设置为False,并且“img”占位符被馈送到numpy数组中 - numpy数组从3到4维向量重新整形以符合模型中的输入张量到推理函数。

That is all there is to it. Any model can be inferred with a single/user defined test data like shown in the script above. Essentially read the graph, feed data to the graph nodes and run the graph to get the final output.

这就是它的全部。任何模型都可以使用单个/用户定义的测试数据推断,如上面的脚本所示。基本上读取图形,将数据提供给图形节点并运行图形以获得最终输出。

Now the second method. The other approach is to hack cifar10.py and cifar10_eval.py to change batch size to one and replace the data coming from the queue runner with the one read from a file.

现在是第二种方法。另一种方法是破解cifar10.py和cifar10_eval.py以将批量大小更改为1并将来自队列运行器的数据替换为从文件中读取的数据。

Set batch size to 1:

将批量大小设置为1:

tf.app.flags.DEFINE_integer('batch_size', 1,
                             """Number of images to process in a batch.""")

Call inference with an image file read.

使用读取的图像文件调用推理。

def evaluate():   with tf.Graph().as_default() as g:
    # Get images and labels for CIFAR-10.
    eval_data = FLAGS.eval_data == 'test'
    images, labels = cifar10.inputs(eval_data=eval_data)
    import cv2
    img = cv2.imread('tmp.png')
    img = np.expand_dims(img, axis=0)
    img = tf.cast(img, tf.float32)

    logits = cifar10.inference(img)

Then pass logits to eval_once and modify eval once to evaluate logits:

然后将logits传递给eval_once并修改eval一次以评估logits:

def eval_once(saver, summary_writer, top_k_op, logits, summary_op): 
    ...
    while step < num_iter and not coord.should_stop():
        predictions = sess.run([top_k_op])
        print(sess.run(logits))

There is no separate script to run this method of inference, just run cifar10_eval.py which will now read a file from the user defined location with a batch size of one.

没有单独的脚本来运行这种推理方法,只需运行cifar10_eval.py,它现在将从批量大小为1的用户定义位置读取文件。

更多相关文章

  1. Django代理模型返回父模型
  2. [caffe(二)]Python加载训练caffe模型并进行测试2
  3. python的PIL绘制多行文本的图像。
  4. 新人求助:tensorflow官方文档里构建第一个多层卷积网络,训练和评估
  5. 铯:使用自己的OpenStreetMap服务器。:“未能获得图像块”错误
  6. 双插槽与单插槽内存模型?
  7. 如何将图像加载到PictureBox;基于存储在DataBase中的图像位置
  8. 如何使用来自其他模型的信息来注释查询集,或者在Django Rest Fram
  9. 使用进度条延迟加载图像会使图像在显示时发生损坏

随机推荐

  1. Android Gradle实用技巧——多渠道打包
  2. Android 实现APP开屏广告
  3. android代码混淆 GSON完满解决
  4. 分析谷歌收购摩托罗拉无线对移动产业带来
  5. 使用webview调起QQ临时会话
  6. Android学习之DexClassLoader类装载器使
  7. Android M InCallUI动画简析
  8. 16位科技大佬点评Android和iPhone平台优
  9. Android开发笔记——改变字体颜色的三种
  10. Android网络编程-----从服务器端获取xml