Python slim tensorflow和tf记录批次中微调接收v3的问题

Python slim tensorflow和tf记录批次中微调接收v3的问题,python,tensorflow,deep-learning,tf-slim,tfrecord,Python,Tensorflow,Deep Learning,Tf Slim,Tfrecord,我正在尝试使用slim tensorflow库微调inceptionv3模型。 在为它编写代码时,我无法理解某些事情。我试着阅读源代码(没有合适的文档),并想出了一些事情,我能够微调它并保存检查点。以下是我遵循的步骤 1.我为我的训练数据创建了一个tf.record,这很好,现在我正在使用下面的代码读取数据 import tensorflow as tf import tensorflow.contrib.slim.nets as nets import tensorflow.contrib.s

我正在尝试使用slim tensorflow库微调inceptionv3模型。 在为它编写代码时,我无法理解某些事情。我试着阅读源代码(没有合适的文档),并想出了一些事情,我能够微调它并保存检查点。以下是我遵循的步骤 1.我为我的训练数据创建了一个tf.record,这很好,现在我正在使用下面的代码读取数据

import tensorflow as tf
import tensorflow.contrib.slim.nets as nets
import tensorflow.contrib.slim as slim
import matplotlib.pyplot as plt
import numpy as np

# get the data and labels here

data_path = '/home/sfarkya/nvidia_challenge/datasets/detrac/train1.tfrecords'

# Training setting
num_epochs = 100
initial_learning_rate = 0.0002
learning_rate_decay_factor = 0.7
num_epochs_before_decay = 5
num_classes = 5980

# load the checkpoint
model_path = '/home/sfarkya/nvidia_challenge/datasets/detrac/inception_v3.ckpt'

# log directory
log_dir = '/home/sfarkya/nvidia_challenge/datasets/detrac/fine_tuned_model'

with tf.Session() as sess:
    feature = {'train/image': tf.FixedLenFeature([], tf.string),
               'train/label': tf.FixedLenFeature([], tf.int64)}

    # Create a list of filenames and pass it to a queue
    filename_queue = tf.train.string_input_producer([data_path], num_epochs=1)

    # Define a reader and read the next record
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)

    # Decode the record read by the reader
    features = tf.parse_single_example(serialized_example, features=feature)

    # Convert the image data from string back to the numbers
    image = tf.decode_raw(features['train/image'], tf.float32)

    # Cast label data into int32
    label = tf.cast(features['train/label'], tf.int32)

    # Reshape image data into the original shape
    image = tf.reshape(image, [128, 128, 3])

    # Creates batches by randomly shuffling tensors
    images, labels = tf.train.shuffle_batch([image, label], batch_size=64, capacity=128, num_threads=2,
                                            min_after_dequeue=64)
现在,我正在使用slim对模型进行微调,下面是代码

  init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
    sess.run(init_op)

    # Create a coordinator and run all QueueRunner objects
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(coord=coord)

    # load model

    # load the inception model from the slim library - we are using inception v3
    #inputL = tf.placeholder(tf.float32, (64, 128, 128, 3))

    img, lbl = sess.run([images, labels])
    one_hot_labels = slim.one_hot_encoding(lbl, num_classes)

    with slim.arg_scope(slim.nets.inception.inception_v3_arg_scope()):
        logits, inceptionv3 = nets.inception.inception_v3(inputs=img, num_classes=5980, is_training=True,
                                                          dropout_keep_prob=.6)

    # Restore convolutional layers:

    variables_to_restore = slim.get_variables_to_restore(exclude=['InceptionV3/Logits', 'InceptionV3/AuxLogits'])
    init_fn = slim.assign_from_checkpoint_fn(model_path, variables_to_restore)

    # loss function
    loss = tf.losses.softmax_cross_entropy(onehot_labels=one_hot_labels, logits = logits)
    total_loss = tf.losses.get_total_loss()

    # train operation
    train_op = slim.learning.create_train_op(total_loss + loss, optimizer= tf.train.AdamOptimizer(learning_rate=1e-4))

    print('Im here')
    # Start training.
    slim.learning.train(train_op, log_dir, init_fn=init_fn, save_interval_secs=20, number_of_steps= 10)
现在我对代码有一些问题,我完全无法理解。一旦代码到达slim.learning.train,我看不到任何打印内容,但是,我可以在日志中看到,这是训练。现在, 1.我如何给代码提供纪元数?现在,它正在一步一步地运行,每个步骤的批处理大小为64。
2.如何确保在代码tf.train.shuffle\u batch中,我没有重复我的图像,而是在整个数据集上进行训练?
3.如何在培训过程中打印损失值?

以下是您问题的答案

  • 您不能直接向
    slim.learning.train
    提供纪元。相反,您将批数作为参数。它被称为
    步数
    。它用于设置名为“应停止”的操作。我假设您知道如何将历代数转换为批次

  • 我认为
    shuffle\u batch
    函数不会重复图像,因为它在内部使用。根据,
    randomsufflequeue
    使用后台线程将元素排队,如下所示:

    • 大小(队列)
      • 将元素添加到队列中
  • 它将元素排成以下列:

    • 退出队列的
      元素数
      • 等待
        size(queue)>=min\u-after\u-dequeue+1
        元素
      • 从队列中随机均匀地选择一个元素,将其从队列中删除,然后将其添加到输出批中
    因此,在我看来,元素重复的可能性很小,因为在
    出列操作中,所选元素从队列中移除。因此,它是抽样而不更换的

    是否会为每个历元创建一个新队列?

    输入到
    tf.train.shuffle\u batch
    的张量是
    image
    label
    ,它们最终来自
    filename\u队列
    。如果该队列无限期地生成TFRecord文件名,那么我认为
    shuffle\u batch
    不会创建新的队列。您还可以创建一个玩具代码,如了解
    shuffle\u batch
    的工作原理

    接下来,如何对整个数据集进行训练?在代码中,下一行获取TFRecord文件名的列表

    filename_queue = tf.train.string_input_producer([data_path], num_epochs=1)
    
    如果
    filename\u queue
    覆盖了您拥有的所有TFR记录,那么您肯定是在整个数据集上进行训练。现在,如何洗牌整个数据集是另一个问题。正如@mrry所提到的,目前还不支持(AFAIK)洗出内存数据集。因此,最好的方法是准备数据集的多个碎片,使每个碎片包含大约1024个示例。将TFRecord文件名列表洗牌为:

    filename_queue = tf.train.string_input_producer([data_path], shuffle=True, capacity=1000)
    
    注意,我删除了
    num_epochs=1
    参数并设置
    shuffle=True
    。这样,它将无限期地生成TFRecord文件名的无序列表。现在,在每个文件上,如果您使用
    tf.train.shuffle\u batch
    ,您将得到一个近乎统一的洗牌。基本上,当每个碎片中的示例数趋于1时,您的洗牌将变得越来越一致。我不喜欢设置
    num_epochs
    ,而是使用前面提到的
    number_of_steps
    参数终止训练

  • 要打印损失值,您可能只需编辑并引入
    logging.info('total loss=%f',total_loss)
    。我不知道有没有更简单的方法。另一种不改变代码的方法是在Tensorboard中查看摘要
  • 关于如何在Tensorboard中查看摘要,有很多非常有用的文章,包括本答案末尾的链接。一般来说,你需要做以下事情

  • 创建
    摘要
    对象
  • 将感兴趣的变量写入
    摘要
  • 合并所有单独的摘要
  • 创建一个
    摘要
    op
  • 创建摘要文件编写器
  • 在整个培训过程中,以所需的频率编写总结
  • 现在,如果您使用
    slim.learning.train
    ,步骤5和6已经自动完成

    对于前4个步骤,您可以检查文件。第472行显示了如何创建
    摘要
    对象。第490、512和536行将相关变量写入
    摘要中。第549行合并所有摘要,第553行创建一个op。您可以将此op传递给
    slim.learning.train
    ,还可以指定编写摘要的频率。在我看来,除了损失、总损失、准确性和学习率之外,不要在总结中写任何东西,除非你想做具体的调试。如果您编写直方图,那么对于ResNet-50这样的网络,tensorboard文件可能需要几十个小时才能加载(我的tensorboard文件曾经是28GB,加载6天的进度需要12个小时!)。顺便说一下,您实际上可以使用
    train\u image\u classifier.py
    文件进行微调,您将跳过上面的大部分步骤。然而,我更喜欢这样,因为你可以学到很多东西

    请参见有关如何在浏览器中查看进度的部分

    附加备注:

    • 您可以执行以下操作,而不是最小化总损失+损失

    loss = tf.losses.softmax_cross_entropy(onehot_labels=one_hot_labels, logits = logits)
    tf.losses.add_loss(loss)
    total_loss = tf.losses.get_total_loss()
    train_op = slim.learning.create_train_op(total_loss, optimizer=tf.train.AdamOptimizer(learning_rate=1e-4))
    
  • 我找到了p