我认为,如果针对 CIFAR-10 教程中由 convnet 创建的模型测试单个新图像这一关键任务,有一个有据可查的解决方案,那将对 Tensorflow 社区非常有帮助。
我可能是错的,但似乎缺乏使训练模型在实践中可用的关键步骤。该教程中有一个“缺失的链接”——一个直接加载单个图像(作为数组或二进制)、将其与训练模型进行比较并返回分类的脚本。
先前的答案给出了解释整体方法的部分解决方案,但我没有一个能够成功实施。可以在这里和那里找到其他点点滴滴,但不幸的是还没有加起来成为一个有效的解决方案。在将其标记为重复或已回答之前,请考虑我所做的研究。
https://gist.github.com/nikitakit/6ef3b72be67b86cb7868
最流行的答案是第一种,@RyanSepassi 和@YaroslavBulatov 描述了问题和一种方法:需要“手动构建具有相同节点名称的图,并使用 Saver 将权重加载到其中”。尽管这两个答案都有帮助,但尚不清楚如何将其插入 CIFAR-10 项目。
非常需要一个功能齐全的解决方案,这样我们就可以将其移植到其他单一图像分类问题中。在这方面有几个关于 SO 的问题要求这个,但仍然没有完整的答案(例如 Load checkpoint and evaluate single image with tensorflow DNN )。
我希望我们可以汇集一个每个人都可以使用的工作脚本。
以下脚本尚未运行,我很高兴收到您的来信,了解如何改进它以提供使用 CIFAR-10 TF 教程训练模型进行单图像分类的解决方案。
假设原始教程中的所有变量、文件名等都没有改变。
新文件: 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()
原文由 pepe 发布,翻译遵循 CC BY-SA 4.0 许可协议
有两种方法可以将单个新图像提供给 cifar10 模型。第一种方法是一种更简洁的方法,但需要在主文件中进行修改,因此需要重新训练。当用户不想修改模型文件而是想使用现有的检查点/元图文件时,第二种方法适用。
第一种方法的代码如下:
该脚本要求用户创建两个占位符和一个条件执行语句才能运行。
在cifar10_train.py中添加占位符和条件执行语句如下图:
cifar10 模型中的输入连接到队列运行器对象,该对象是一个多级队列,可以并行地从文件中预取数据。 在此处 查看队列赛跑者的精彩动画
虽然 queue runners 在预取大型数据集进行训练时很有效,但对于只需要对单个文件进行分类的推理/测试来说,它们就有点矫枉过正了,而且它们还需要更多地参与修改/维护。出于这个原因,我添加了一个占位符“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:
使用读取的图像文件调用推理。
然后将 logits 传递给 eval_once 并修改 eval once 以评估 logits:
没有单独的脚本来运行这种推理方法,只需运行 cifar10_eval.py,它现在将从用户定义的位置读取一个批量大小为 1 的文件。