我认为,如果有一个很好的解决方案来完成一个关键的任务,即根据convnet in the CIFAR-10 tutorial创建的模型测试一个新图像,这将对Tensorflow社区非常有帮助。
我可能错了,但这一关键步骤,使训练模型在实践中可用似乎是缺乏的。该教程中有一个“缺少的链接”——一个脚本,它将直接加载单个图像(作为数组或二进制),将其与经过训练的模型进行比较,并返回一个分类。
先前的答案给出了部分的解决方案,解释了整体的方法,但没有一个是我能够成功实现的。其他零碎的东西到处都可以找到,但不幸的是还没有形成一个有效的解决方案。请考虑我做过的研究,在标记为重复或已经回答之前。
Tensorflow: how to save/restore a model?
Unable to restore models in tensorflow v0.8
https://gist.github.com/nikitakit/6ef3b72be67b86cb7868
最流行的答案是第一个,其中@RyanSepassi和@YaroslavBulatov描述了这个问题和一种方法:需要“手动构造一个具有相同节点名的图,并使用Saver将权重加载到其中”。尽管这两个答案都是有用的,但不清楚如何将其插入CIFAR-10项目。
一个全功能的解决方案是非常理想的,所以我们可以移植到其他单一图像分类问题。在这方面有几个问题需要回答,但仍然没有完整的答案(例如Load checkpoint and evaluate single image with tensorflow DNN)。
我希望我们能集中在一个每个人都能使用的工作脚本上。
下面的脚本还不起作用,我很高兴从您那里听到如何改进,以提供一个使用CIFAR-10tf教程训练模型的单一图像分类解决方案。
假设所有的变量、文件名等都是原始教程中未涉及的。
新文件: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()
有两种方法可以将单个新图像馈送到cifar10模型。第一种方法是一种更干净的方法,但需要修改主文件,因此需要重新培训。当用户不想修改模型文件,而是想使用现有的check point/meta graph文件时,可以使用第二种方法。
第一种方法的代码如下:
该脚本要求用户创建两个占位符和一个条件执行语句以使其工作。
占位符和条件执行语句添加到cifar10_train.py中,如下所示:
cifar10模型中的输入连接到queue runner对象,queue runner对象是一个多级队列,可以并行预取文件中的数据。看到队列运行器的漂亮动画here
虽然队列运行器在预取大型数据集以进行训练方面是有效的,但对于只需要对单个文件进行分类的推理/测试来说,它们是一种过激的做法,而且它们更需要修改/维护。 为此,我添加了一个占位符“is_training”,在训练时设置为False,如下所示:
另一个占位符“imgs”为图像保存一个形状张量(1,32,32,3),该张量将在推断过程中提供——第一个维度是批大小,在本例中是一个。我修改了cifar模型以接受32x32图像,而不是24x24,因为原始cifar10图像是32x32。
最后,条件语句将占位符或队列运行器输出提供给图形。“is_training”占位符在推理过程中设置为False,“img”占位符被馈送一个numpy数组——numpy数组被从3维向量重塑为4维向量,以符合模型中推理函数的输入张量。
这就是它的全部。任何模型都可以用一个/用户定义的测试数据进行推断,如上面的脚本所示。基本上是读取图形,将数据馈送到图形节点并运行图形以获得最终输出。
现在是第二种方法。另一种方法是修改cifar10.py和cifar10_eval.py,将批大小更改为1,并将来自队列运行器的数据替换为从文件中读取的数据。
将批大小设置为1:
读取图像文件后调用推断。
然后将logits传递给eval_一次,并修改eval once以计算logits:
没有单独的脚本来运行这种推理方法,只需运行cifar10_eval.py,它现在将从用户定义的位置读取批大小为1的文件。
下面是我如何一次运行一个图像。我承认,重新使用范围似乎有点老套。
这是一个helper函数
下面是在for循环中一次运行单个映像的代码的主要部分。
这里有一个替代的实现上面使用占位符-在我看来它有点干净。但出于历史原因,我将留下上面的例子。
有了这个
输出
相关问题 更多 >
编程相关推荐