Feed_dict不接受我的数据

时间:2017-12-05 13:31:16

标签: python numpy image-processing tensorflow

我一直在努力能够在一些张量流代码中提供我自己的图像,以查看代码如何对我自己的图像而不是MNIST集做出反应。我已经能够将图像(我认为)导入tensorflow,但我有两个占位符,可以获取我的图像数据和标签数据。我尝试使用feed_dict(对我来说似乎仍然是正确的)能够在我的其余代码中使用我的数据,但它不会接受我提供的任何数据。我知道我不能把它作为Tensor,显然不是一批,但我能想到的唯一方法就是把它作为一个列表。我看到feed_dict能够使用numpy数组,但我不知道如何将数据转换为numpy数组。

我是TensorFlow和python的新手所以请原谅我犯的任何错误,我仍在学习一切是如何运作的。

with tf.name_scope('Image_Data_Input'):
  def read_labeled_image_list(image_list_file):
    print('read_labeled_image_list function opened')
    f = open(image_list_file, 'r') 
    print('image_list_file opened')
    filenames = []
    labels = []
    print('Arrays formed')
    for line in f:
      filename, label = line[:-1].split(' ')
      filenames.append(filename)
      labels.append(label)
    print('Lines deconstructed')
    return filenames, labels

def read_image(input_queue):
    label = input_queue[1]
    file_contents = tf.read_file(input_queue[0])
    decoded_image = tf.image.decode_jpeg(file_contents, channels=3)
    print('Image decoded to JPEG')
    decoded_image.set_shape([2560, 1440, 3])
    decoded_image = tf.image.resize_images(decoded_image, [128, 128])
    return decoded_image, label

image_list, label_list = read_labeled_image_list(image_list_file)
images = tf.convert_to_tensor(image_list, dtype=tf.string)
labels = tf.convert_to_tensor(label_list, dtype=tf.string)

input_queue = tf.train.slice_input_producer([images, labels], num_epochs=None, shuffle=True)

image, label = read_image(input_queue)

当我粘贴我的代码时,缩进表现得有些奇怪,所以我不确定所有内容是否正确放置。

现在我有这些占位符:

with tf.name_scope('input'):
  x = tf.placeholder(tf.float32, shape=[None, 784])
  y_ = tf.placeholder(tf.float32, shape=[None, 10])

我已经看到代码以这种方式将数据路由到这些占位符:

batch_x, batch_y = tf.train.batch([image, label], batchsize)
#_, summary = sess.run([train_writer, summary_op], feed_dict={x: batch_x, y_: batch_y})

但我似乎无法做到这一点。

有谁知道我怎么能让这项工作?

再次对任何错误表示歉意,并提前致谢。

1 个答案:

答案 0 :(得分:1)

如错误所示,您无法将张量输入占位符。 batch_xbatch_y是张量。新的tf.Dataset API是将数据输入模型的首选方式(指南here)。我认为Dataset.from_tensor_slices只需要很少的重写。除此之外,构建图表以便batch_xbatch_y流入您正在使用的模型中。然后你不需要使用占位符。

我不推荐这个,但为了完整性,我想提一下另一种方法。你可以:

numpy_batch_x, numpy_batch_y = sess.run([batch_x, batch_y])
_, summary = sess.run([train_writer, summary_op], 
    feed_dict={x: numpy_batch_x, y_: numpy_batch_y})

PS:如果train_writertf.summary.FileWriter,我想你想:

summary = sess.run([summary_op], ...)
train_writer.add_summary(summary)

编辑:为了应对数据集API的混淆,我将展示如何使用数据集处理此问题。我打算用TFRecords。它可能不是最简单的解决方案,但它是一种方式。

import numpy as np
from scipy.misc import imread  # There are others that would work here.
from cv2 import resize  # Again, others to choose from.

def read_labeled_image_list(...)
    # See question
    return filenames, labels

def make_tfr(tfr_dir="/YOUR/PREFERRED/TFR/DIR")
    def _int64_list_feature(a_list):
        return tf.train.Feature(int64_list=tf.train.Int64List(value=a_list)

    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

    writer = tf.python_io.TFRecordWriter(tfr_dir)
    all_image_paths, all_labels = read_labeled_image_list(...)
    for path, label in zip(all_image_paths, all_labels):
        disk_im = imread(path)
        resized_im = cv2.resize(disk_im, (128, 128))
        raw_im = resized_im.tostring()
        # Construct an example proto-obj,
        example = tf.train.Example(
            # which wants a Features proto-obj,
            features=tf.train.Features(
                # which wants a dict.
                feature={
                    'image_raw': _bytes_feature(raw_im),
                    'label': _int64_list_feature(label)
        })) # close your example object
        serialized = example.SerializeToString()
        writer.write(serialized)

make_tfr()  # After you've done it successfully once, comment out.

def input_pipeline(batch_size, epochs, tfr_dir="/YOUR/PREFERRED/TFR/DIR"):
    # with tf.name_scope("Input"):  maybe you like to scope as much as I do?
    dataset = tf.data.TFRecordDataset(tfr_dir)

    def parse_protocol_buffer(example_proto):
        features = {'image_raw': tf.FixedLenFeature((), tf.string),
                    'label': tf.FixedLenFeature((), tf.int64)}
        parsed_features = tf.parse_single_example(
            example_proto, features)
        return parsed_features['image_raw'], parsed_features['label']

    dataset = dataset.map(parse_protocol_buffer)

    def convert_parsed_proto_to_input(image_string, label):
        image_decoded = tf.decode_raw(image_string, tf.uint8)
        image_resized = tf.reshape(image_decoded, (128, 128, 3))
        image = tf.cast(image_resized, tf.float32)
        # I usually put my image elements in [-1, 1]
        return image * (2. /255) -1, label

    dataset = dataset.map(converted_parsed_proto_to_input)
    dataset = dataset.shuffle(buffer_size=1000)
    dataset = dataset.repeat(batch_size * epochs)
    return dataset

def model(image_tensor):
    ...
    # However you want to do this.
    return predictions

def loss(predictions, labels):
    ...
    return some_loss

def train(some_loss):
    ...
    return train_op

batch_size = 50
iterations = 10000
train_dataset = input_pipeline(batch_size, iterations)
train_iterator = train_dataset.make_initializable_iterator()
image, label = train_iterator.get_next()
predictions = model(image)
loss_op = loss(image, predictions)
train_op = train(loss_op)
summary_op = tf.summary.merge_all()
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    train_writer = tf.summary.FileWriter("/YOUR/LOGDIR", sess.graph)
    sess.run(train_iterator.initializer)
    for epoch in range(iterations + 1):
        _, summary = sess.run([train_op, summary_op])
        train_writer.add_summary(summary, epoch)

你说你是TensorFlow的新手。我希望这不会吓到你。我不久前是TensorFlow的新手,弄清楚如何制作一个好的输入管道真是太痛苦了。学习TFRecords似乎不可能。你还说你是Python的新手,所以我会警告你cv2有一个难以安装的声誉。您可能想要查看其他方法来调整图像大小(虽然我建议不要使用PIL,这可能更令人困惑和困难)。

基本上,我发布这段代码是因为写TFRecords的文档令人困惑(Exhibit A vs blog post帮助我解决了问题)但TFRecords是我知道如何制作的方式数据集最好。即使您没有使用TFRecords路线,这也可以帮助您使用数据集的map功能,例如注意我如何通过label通过convert...,即使它没有被使用。制作数据集(特别是来自TFRecords)是很多代码行,但Dataset是构造输入管道的首选方法,它旨在替换您正在使用的旧queue方法。 / p>

作为旁注,queue策略的目的是将内存中的数据直接读入图形而不使用占位符。与队列策略相比,占位符速度慢且内存密集,但如果正确实现,数据集甚至会更好。

我在评论中看到您希望看到占位符名称范围与您的图表相关联。在数据集方式中,您将在图表上看到一些数据集节点。如果你用我评论的内容来限定它们,那么显而易见的是,所有内容都是正确的。你的方式,你实际上是将这个队列和预处理结构添加到图表上。由于您必须对图像进行去张量化以将其传递到占位符中,因此您的数据无法正常显示。

现在,正如我在原帖中所提到的,您可以将batch_xbatch_y传递到模型中,完全忘记placeholder和数据集。如果队列正确实现,您将看到从预处理阶段直接连接的所有内容。尽管如此,在重塑它们之前,您的图像仍然很大。阅读它们将是一项艰巨的任务。我建议采用艰难的学习途径来使用DatasetsTFRecords

我希望这可以帮助您在代码中实现数据集。我希望这可以帮助你让TensorBoard运行。我希望如果您决定走这条路线,这可以帮助您找出TFRecords。

PS:关于TensorBoard验证模型是否有效的主题,您可以附加tf.summary.image(img)作为model(...)的第一行。然后查看图像短划线,看看它是否符合您的期望。

编辑2 example = tf.train.Example(features=tf.train.Features(feature={}))