使用调整后的CNN教程系统对图像进行分类会使输出结果混乱

2024-04-19 18:35:58 发布

您现在位置:Python中文网/ 问答频道 /正文

对不起,这条很长!你知道吗

我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个图像的输入上,但当我尝试对更多图像进行分类时,数据会变得混乱。事实上,有些预测完全失败了!你知道吗

发生这种情况有几个原因。本教程并不关心数据的读取或处理顺序,只关心单个图像与其标签相对应。最初数据丢失是随机的(!)但是我通过删除多线程(threads=1而不是16)成功地删除了random元素,并阻止了它洗牌文件名。你知道吗

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

string\u input\u producer有一个隐藏的/可选的参数,用于洗牌文件名。对于模型评估,我已将其设置为false,如上所述。你知道吗

然而。。。。在评估大于单个批的数据时,我仍然会遇到混乱的数据丢失问题。你知道吗

有人知道为什么会这样吗?有人知道怎么解决吗?你知道吗

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

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

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

我已经通过将列表作为python输出直接打印到屏幕上,并使用它组装一个可以与原始输入进行比较的PNG图像来验证输出预测。这种验证对于小批量非常有效,并且在大批量中开始崩溃。你知道吗

我还对本帖中未讨论的教程进行了一些修改。这些都是简单的修改,比如将类别数改为2而不是10。我相信这不是问题所在。你知道吗

第PS,这是修改后的脚本中的一些函数的副本。我没有粘贴所有内容,因为这个问题已经很大了:

来自cifar10\u评估:

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\U输入:

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\U输入:

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: 它回来了!我已经将批大小设置为相当于一个二进制文件(在我的例子中大约是10000个图像)。在这个批处理中,数据不会丢失或混乱,但当我尝试处理多个文件(大约30个)时,它会稍微混合批处理,而不是以先进先出的方式输出它们。你知道吗

图片可能是最简单的方式让你看到正在发生的事情: classification map 这是岩石表面的重建图像,从中训练分类器识别三个类别。正如你所看到的,重建基本上是顺利的。但是,在图像顶部附近有两个干净的中断,其中一批(或3批)已按非时间顺序输出。这些应该出现在图片的底部而不是顶部附近。你知道吗


Tags: ofthe数据in图像imagesizeif