Python Tensorflow队列-列车和验证数据之间的切换

Python Tensorflow队列-列车和验证数据之间的切换,python,queue,tensorflow,Python,Queue,Tensorflow,我试图利用队列从Tensorflow中的文件加载数据 我想在每个历元结束时运行带有验证数据的图表,以便更好地了解培训的进展情况 这就是我遇到问题的地方。我似乎不知道该怎么做 使用队列时,在培训数据和验证数据之间进行切换 我已经将我的代码简化为一个简单的玩具示例,以使其更易于使用 寻求帮助。我没有包含加载图像文件、执行推理和训练的所有代码,而是在最开始的时候将其截断 文件名加载到队列中的点 import tensorflow as tf # DATA train_items = ["

我试图利用队列从Tensorflow中的文件加载数据

我想在每个历元结束时运行带有验证数据的图表,以便更好地了解培训的进展情况

这就是我遇到问题的地方。我似乎不知道该怎么做 使用队列时,在培训数据和验证数据之间进行切换

我已经将我的代码简化为一个简单的玩具示例,以使其更易于使用 寻求帮助。我没有包含加载图像文件、执行推理和训练的所有代码,而是在最开始的时候将其截断 文件名加载到队列中的点

import tensorflow as tf

#  DATA
train_items = ["train_file_{}".format(i) for i in range(6)]
valid_items = ["valid_file_{}".format(i) for i in range(3)]

# SETTINGS
batch_size = 3
batches_per_epoch = 2
epochs = 2

# CREATE GRAPH
graph = tf.Graph()
with graph.as_default():
    file_list = tf.placeholder(dtype=tf.string, shape=None)
    
    # Create a queue consisting of the strings in `file_list`
    q = tf.train.string_input_producer(train_items, shuffle=False, num_epochs=None)
    
    # Create batch of items.
    x = q.dequeue_many(batch_size)
    
    # Inference, train op, and accuracy calculation after this point
    # ...


# RUN SESSION
with tf.Session(graph=graph) as sess:
    # Initialize variables
    sess.run(tf.global_variables_initializer())
    sess.run(tf.local_variables_initializer())
    
    # Start populating the queue.
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    
    try:
        for epoch in range(epochs):
            print("-"*60)
            for step in range(batches_per_epoch):
                if coord.should_stop():
                    break
                train_batch = sess.run(x, feed_dict={file_list: train_items})
                print("TRAIN_BATCH: {}".format(train_batch))
    
            valid_batch = sess.run(x, feed_dict={file_list: valid_items})
            print("\nVALID_BATCH : {} \n".format(valid_batch))
    
    except Exception, e:
        coord.request_stop(e)
    finally:
        coord.request_stop()
        coord.join(threads)
变异与实验 为
num\u历元尝试不同的值
num_epochs=无
如果我将
tf.train.string\u input\u producer()
中的
num\u epochs
参数设置为
None
它给出以下输出, 这表明它按预期运行了两个时代,但它使用的是数据 在运行评估时从培训集中删除

------------------------------------------------------------
TRAIN_BATCH: ['train_file_0' 'train_file_1' 'train_file_2']
TRAIN_BATCH: ['train_file_3' 'train_file_4' 'train_file_5']

VALID_BATCH : ['train_file_0' 'train_file_1' 'train_file_2']

------------------------------------------------------------
TRAIN_BATCH: ['train_file_3' 'train_file_4' 'train_file_5']
TRAIN_BATCH: ['train_file_0' 'train_file_1' 'train_file_2']

VALID_BATCH : ['train_file_3' 'train_file_4' 'train_file_5']
num_epochs=2 如果我将
tf.train.string\u input\u producer()
中的
num\u epochs
参数设置为
2
它给出如下输出:, 这表明它甚至没有运行完整的两个批次 (评估仍在使用培训数据)

num_epochs=1 如果我将
tf.train.string\u input\u producer()
中的
num\u epochs
参数设置为
1
希望它能被冲走 队列中的任何传统训练数据,以便它可以使用验证 数据,我得到以下输出,这表明它在 它可以通过一个历元的训练数据,但不能通过 加载评估数据

------------------------------------------------------------
TRAIN_BATCH: ['train_file_0' 'train_file_1' 'train_file_2']
TRAIN_BATCH: ['train_file_3' 'train_file_4' 'train_file_5']
capacity
参数设置为各种值 我还尝试在中设置
容量
参数
tf.train.string\u input\u producer()。但是这些
对结果没有影响

我应该采取什么其他方法? 我可以采取什么其他方法在培训和验证数据之间切换? 我需要创建单独的队列吗?我不知道怎样才能把那件事办妥
工作我还需要创建其他协调员和队列运行程序吗?

首先,您可以手动读取代码中的示例(到numpy数组),并以任何方式传递它:

data = tf.placeholder(tf.float32, [None, DATA_SHAPE])
for _ in xrange(num_epochs):
  some_training = read_some_data()
  sess.run(train_op, feed_dict={data: some_training})
  some_testing = read_some_test_data()
  sess.run(eval_op, feed_dict={data: some_testing})
如果需要使用队列,可以尝试有条件地将队列从“培训”更改为“测试”队列:


第二种方法是——在这篇文章中,鼓励为训练和测试构建两个单独的图表(共享权重),这是实现您想要的另一种方法。

好的,所以我有一个适合我的解决方案。它基于tensorflow github问题部分的代码。它使用了
QueueBase.from_list()
函数。它感觉很粗糙,我对它并不完全满意,但至少我正在让它工作

import tensorflow as tf

# DATA
train_items = ["train_file_{}".format(i) for i in range(6)]
valid_items = ["valid_file_{}".format(i) for i in range(3)]

# SETTINGS
batch_size = 3
batches_per_epoch = 2
epochs = 2

# ------------------------------------------------
#                                            GRAPH
# ------------------------------------------------
graph = tf.Graph()
with graph.as_default():
    # TRAIN QUEUE
    train_q = tf.train.string_input_producer(train_items, shuffle=False)

    # VALID/TEST QUEUE
    test_q = tf.train.string_input_producer(valid_items, shuffle=False)

    # SELECT QUEUE
    is_training = tf.placeholder(tf.bool, shape=None, name="is_training")
    q_selector = tf.cond(is_training,
                         lambda: tf.constant(0),
                         lambda: tf.constant(1))

    # select_q = tf.placeholder(tf.int32, [])
    q = tf.QueueBase.from_list(q_selector, [train_q, test_q])

    # # Create batch of items.
    data = q.dequeue_many(batch_size)


# ------------------------------------------------
#                                          SESSION
# ------------------------------------------------
with tf.Session(graph=graph) as sess:
    # Initialize variables
    sess.run(tf.global_variables_initializer())
    sess.run(tf.local_variables_initializer())

    # Start populating the queue.
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)


    try:
        for epoch in range(epochs):
            print("-" * 60)
            # TRAIN
            for step in range(batches_per_epoch):
                if coord.should_stop():
                    break
                print("TRAIN.dequeue = " + str(sess.run(data, {is_training: True})))

            # VALIDATION
            print "\nVALID.dequeue = " + str(sess.run(data, {is_training: False}))

    except Exception, e:
        coord.request_stop(e)

    finally:
        coord.request_stop()
        coord.join(threads)
给出以下输出,这是我所期望的

------------------------------------------------------------
TRAIN.dequeue = ['train_file_0' 'train_file_1' 'train_file_2']
TRAIN.dequeue = ['train_file_3' 'train_file_4' 'train_file_5']

VALID.dequeue = ['valid_file_0' 'valid_file_1' 'valid_file_2']
------------------------------------------------------------
TRAIN.dequeue = ['train_file_0' 'train_file_1' 'train_file_2']
TRAIN.dequeue = ['train_file_3' 'train_file_4' 'train_file_5']

VALID.dequeue = ['valid_file_0' 'valid_file_1' 'valid_file_2']

我留下这条线索,希望有更好的解决办法

我正在整理一份可能解决这个问题的潜在方法列表。其中大多数只是模糊的建议,没有实际的代码示例来说明如何使用它们

默认占位符 暗示

使用tf.cond() 暗示

sygi在这个stackoverflow线程上也提出了建议

使用tf.group()和tf.cond() 暗示

make_template()方法 建议及

共享权重法 sygi在这个stackoverflow线程()中建议。这可能与make_template()方法相同

QueueBase()方法。 建议使用示例代码 在这个线程上,代码适合我的问题

训练桶法
建议创建两个不同的队列

如果您有两台不同的机器,我建议您使用单独的机器进行培训和验证(如果没有,您可以使用两种不同的过程)。对于2个机壳:

  • 第一台机器只有训练数据。它使用队列将数据批量传递到图形模型,并使用GPU进行训练。在每一步之后,它都会将新模型(
    model\u iteration
    )保存在第二台机器可以访问它的地方
  • 第二台机器(只有验证数据)定期轮询具有模型的位置,并检查新模型是否可用。在这种情况下,它运行新模型的推断并检查性能。因为在大多数情况下,验证数据明显小于训练数据,所以您甚至可以将其全部存储在内存中

  • 很少有人赞成这种方法。培训/验证数据是分开的,你不能把它们弄乱。您可以使用一台较弱的机器进行验证,因为即使验证落后于培训(不太可能的情况),这也不是问题,因为它们是独立的

    谢谢sygi,是的,我更愿意为当前项目移开占位符。我正在处理各种形状和大小的图像文件,因此我无法轻松地将它们导入numpy数组。我必须对它们进行数据预处理和调整大小。使用队列和tensorflows图像预处理函数预取图像使这更易于管理。由于某种原因,我一直无法使
    tf.cond()
    方法对我有效。虽然我确信这在我的代码中是一个愚蠢的错误。我肯定会研究使用共享权重的方法,尽管将代码的其余部分更改为正确使用共享权重可能会打开一个全新的蠕虫罐,我目前还没有准备好处理这些蠕虫。目前,我已经找到了一个使用
    QueueBase.from_list()
    的解决方案,尽管我怀疑您使用共享权重的建议可能是一个更好的解决方案。op,您是否找到了最佳解决方案?我一直被困住了
    import tensorflow as tf
    
    # DATA
    train_items = ["train_file_{}".format(i) for i in range(6)]
    valid_items = ["valid_file_{}".format(i) for i in range(3)]
    
    # SETTINGS
    batch_size = 3
    batches_per_epoch = 2
    epochs = 2
    
    # ------------------------------------------------
    #                                            GRAPH
    # ------------------------------------------------
    graph = tf.Graph()
    with graph.as_default():
        # TRAIN QUEUE
        train_q = tf.train.string_input_producer(train_items, shuffle=False)
    
        # VALID/TEST QUEUE
        test_q = tf.train.string_input_producer(valid_items, shuffle=False)
    
        # SELECT QUEUE
        is_training = tf.placeholder(tf.bool, shape=None, name="is_training")
        q_selector = tf.cond(is_training,
                             lambda: tf.constant(0),
                             lambda: tf.constant(1))
    
        # select_q = tf.placeholder(tf.int32, [])
        q = tf.QueueBase.from_list(q_selector, [train_q, test_q])
    
        # # Create batch of items.
        data = q.dequeue_many(batch_size)
    
    
    # ------------------------------------------------
    #                                          SESSION
    # ------------------------------------------------
    with tf.Session(graph=graph) as sess:
        # Initialize variables
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
    
        # Start populating the queue.
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    
    
        try:
            for epoch in range(epochs):
                print("-" * 60)
                # TRAIN
                for step in range(batches_per_epoch):
                    if coord.should_stop():
                        break
                    print("TRAIN.dequeue = " + str(sess.run(data, {is_training: True})))
    
                # VALIDATION
                print "\nVALID.dequeue = " + str(sess.run(data, {is_training: False}))
    
        except Exception, e:
            coord.request_stop(e)
    
        finally:
            coord.request_stop()
            coord.join(threads)
    
    ------------------------------------------------------------
    TRAIN.dequeue = ['train_file_0' 'train_file_1' 'train_file_2']
    TRAIN.dequeue = ['train_file_3' 'train_file_4' 'train_file_5']
    
    VALID.dequeue = ['valid_file_0' 'valid_file_1' 'valid_file_2']
    ------------------------------------------------------------
    TRAIN.dequeue = ['train_file_0' 'train_file_1' 'train_file_2']
    TRAIN.dequeue = ['train_file_3' 'train_file_4' 'train_file_5']
    
    VALID.dequeue = ['valid_file_0' 'valid_file_1' 'valid_file_2']