使用调整后的CNN教程对图像进行分类 - 系统正在混淆输出

时间:2017-07-07 14:39:18

标签: python tensorflow

对不起,这是一个很长的!

我80%确定问题在于我不完全理解tensorflow如何使用tf.train.batch函数对数据进行排队。

我正在尝试调整其中一个tensorflow教程来对大量图片进行分类。

可以在此处找到教程:https://www.tensorflow.org/tutorials/deep_cnn

我已经构建了一些模块,可以用cifar10使用的相同格式对原始数据进行编码。我正在使用它来构建培训和评估数据,该程序能够高度准确地评估。准确度取决于我投入的图像集的质量。为了简单起见,我使用黄色或蓝色的32x32单色图块(分别为0和1类)进行了培训。方便地,网络能够识别它是否被给予黄色或蓝色瓷砖,具有100%的准确度。

我也能够使cifar10_eval.py适应输出预测而不是准确百分比。这允许我作为列表输入未分类的数据和输出预测。为此,我交换了声明:     top_k_op = tf.nn.in_top_k(logits, labels, 1) 对于:     output_2 = tf.argmax(logits, 1) 我在eval_once函数调用中添加了一个变量和一个布尔值,以允许它访问" output_2"的定义。让我在这个和" top_k_op"之间切换取决于我是处于评估模式还是我正在预测新数据。

到目前为止一切顺利。此方法适用于少量输入数据,但只要我想输出超过128个分类就会失败。不巧的是128是批量大小。

理论上,二进制文件中的第一项(3073字节)应该对应于列表中的第一项,当我预测新数据时,该项目会被生成。对于最多128张图像的输入会发生这种情况,但是当我尝试对更多图像进行分类时,数据会混乱。实际上,一些预测完全丢失了!

发生这种情况有几个原因。本教程不是为了关注数据的读取或处理顺序而设计的,只是单个图像与其标签相对应。最初数据丢失是随机的(!)但是我已经设法通过删除多线程(线程= 1而不是16)来移除随机元素,并将其从文件名洗牌中停止。

filename_queue = tf.train.string_input_producer(filenames, shuffle=False)

string_input_producer有一个隐藏/可选参数,用于随机播放文件名。对于模型评估,我已将其设置为false,如上所述。

但是......在评估大于单个批次的数据时,我仍然遇到混乱的数据丢失问题。

有谁知道为什么会发生这种情况并对如何修复它有任何想法?

理论上我可以重新设计代码来重建图形并一次评估128个图像。但是,我想对数百万张图片进行分类,并觉得我在尝试每批打开一个新的图表实例时遇到了麻烦。

PS,我完成了我的作业: 我已经验证了我的初始数据到二进制转换是通过运行一个程序来运行的,该程序可以读取cifar10样式的文件并将其解释为图像的大块。我已经在原始的cifar10二进制文件和我自己的二进制文件上运行了这段代码,并且能够完美地重建它们。

当我对未分类的数据进行编码时,我添加了一个零的类别标签,以确保教程可以读取该文件。但是,我确保此标签在文件读取阶段被丢弃,因此在生成预测列表时不会使用。

我已经通过将列表作为python输出直接打印到屏幕上并且还使用它来组装可以与原始输入进行比较的PNG图像来验证输出预测。此验证适用于小批量生产,并且在较大的批量生产中开始崩溃。

我还对本文未讨论过的教程做了一些修改。这些是简单的修改,例如将类别数量更改为2而不是10.我确信这不是问题。

PPS,这是修改过的脚本中的一些函数的副本。我没有粘贴所有东西,因为这个问题已经很大了:

来自cifar10_eval:

def eval_once(saver, summary_writer, top_k_op, output_2, summary_op, mapping=False):
  """Run Eval once.
  Args:
    saver: Saver.
    summary_writer: Summary writer.
    top_k_op: Top K op.
    summary_op: Summary op.
  """
  with tf.Session() as sess:
    ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
    if ckpt and ckpt.model_checkpoint_path:
      # Restores from checkpoint
      saver.restore(sess, ckpt.model_checkpoint_path)
      # Assuming model_checkpoint_path looks something like:
      #   /my-favorite-path/cifar10_train/model.ckpt-0,
      # extract global_step from it.
      global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
    else:
      print('No checkpoint file found')
      return

    # Start the queue runners.
    coord = tf.train.Coordinator()
    try:
      threads = []
      for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS):
        threads.extend(qr.create_threads(sess, coord=coord, daemon=True,
                                         start=True))

      num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size))
      true_count = 0  # Counts the number of correct predictions.
      total_sample_count = num_iter * FLAGS.batch_size
      step = 0
      output=[]
      if mapping:   # if in mapping mode generate a map, if in default mode (variable set to False by default) then tally predictions instead.
          while step < num_iter and not coord.should_stop():
            step += 1
            hold = sess.run(output_2)
            print(hold)
            for i in range (len(hold)):        
                output.append(hold[i])

  return(output)

来自cifar10_input:

def inputs(mapping, data_dir, batch_size):
  """Construct input for CIFAR evaluation using the Reader ops.
  Args:
    mapping: bool, indicating if one should use the raw or pre-classified eval data set.
    data_dir: Path to the CIFAR-10 data directory.
    batch_size: Number of images per batch.
  Returns:
    images: Images. 4D tensor of [batch_size, IMAGE_SIZE, IMAGE_SIZE, 3] size.
    labels: Labels. 1D tensor of [batch_size] size.
  """
  filelist = os.listdir(data_dir)
  filenames = []

  if mapping:
#      from Raw_Image_Processor import file_name
      for f in filelist:
            if f.startswith("raw_batch"):
                filenames.append(os.path.join(data_dir, f))
      num_examples_per_epoch = NUM_EXAMPLES_PER_EPOCH_FOR_TRAIN
  else:
      for f in filelist:
            if f.startswith("eval_batch"):
                filenames.append(os.path.join(data_dir, f))
      num_examples_per_epoch = NUM_EXAMPLES_PER_EPOCH_FOR_EVAL

  for f in filenames:
    if not tf.gfile.Exists(f):
      raise ValueError('Failed to find file: ' + f)

  # Create a queue that produces the filenames to read.
  filename_queue = tf.train.string_input_producer(filenames, shuffle=False)

  # Read examples from files in the filename queue.
  read_input = read_cifar10(filename_queue)
  reshaped_image = tf.cast(read_input.uint8image, tf.float32)

  height = IMAGE_SIZE
  width = IMAGE_SIZE

  # Image processing for evaluation.
  # Crop the central [height, width] of the image.
  resized_image = tf.image.resize_image_with_crop_or_pad(reshaped_image,
                                                         height, width)

  # Subtract off the mean and divide by the variance of the pixels.
  float_image = tf.image.per_image_standardization(resized_image)

  # Set the shapes of tensors.
  float_image.set_shape([height, width, 3])
  read_input.label.set_shape([1])

  # Ensure that the random shuffling has good mixing properties.
  min_fraction_of_examples_in_queue = 0.4
  min_queue_examples = int(num_examples_per_epoch *
                           min_fraction_of_examples_in_queue)

  # Generate a batch of images and labels by building up a queue of examples.
  return _generate_image_and_label_batch(float_image, read_input.label,
                                         min_queue_examples, batch_size,
                                         shuffle=False)

来自cifar10_input:

def _generate_image_and_label_batch(image, label, min_queue_examples,
                                    batch_size, shuffle):
  """Construct a queued batch of images and labels.
  Args:
    image: 3-D Tensor of [height, width, 3] of type.float32.
    label: 1-D Tensor of type.int32
    min_queue_examples: int32, minimum number of samples to retain
      in the queue that provides of batches of examples.
    batch_size: Number of images per batch.
    shuffle: boolean indicating whether to use a shuffling queue.
  Returns:
    images: Images. 4D tensor of [batch_size, height, width, 3] size.
    labels: Labels. 1D tensor of [batch_size] size.
  """
  # Create a queue that shuffles the examples, and then
  # read 'batch_size' images + labels from the example queue.
  num_preprocess_threads = 16
  if shuffle:
    images, label_batch = tf.train.shuffle_batch(
        [image, label],
        batch_size=batch_size,
        num_threads=num_preprocess_threads,
        capacity=min_queue_examples + 3 * batch_size,
        min_after_dequeue=min_queue_examples)
  else:
    images, label_batch = tf.train.batch(
        [image, label],
        batch_size=batch_size,
        num_threads=1,
        capacity=1,
        enqueue_many = False)

  # Display the training images in the visualizer.
  tf.summary.image('images', images)

  return images, tf.reshape(label_batch, [batch_size])

编辑: 部分解决方案在下面的评论中给出。信息丢失取决于批量大小,因此事实证明增加批量大小(仅在映射模式下)是一种有效的解决方法。

但是,我仍然不确定在超过批量大小时它丢失和/或扰乱信息的原因。据推测,批量采取的是一些非连续的顺序。我不需要它来进行项目前进,但如果有人能解释如何或为什么会发生这种情况,我们将不胜感激。

编辑2: 它回来了!我已将批量大小设置为等于一个二进制文件(在我的情况下大约为10,000个图像)。数据不会在此批次中丢失或混乱,但是当我尝试处理多个文件(大约30个)时,它会稍微混合批量而不是以FIFO为基础输出它们。

图片可能是您查看正在发生的事情的最简单方法: classification map 这是岩石面的重建图像,分类器已经被训练以识别三个类别。正如你所看到的那样,重建工作基本上很顺利但是,在图像顶部附近有两个干净的断点,其中批次(或3)以非时间顺序输出。这些应该出现在图像的底部而不是顶部附近。

0 个答案:

没有答案