我正在尝试使用队列从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_epochs
如果我将num_epochs
中的tf.train.string_input_producer()
参数设置为
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
中的tf.train.string_input_producer()
参数设置为2
它给出了以下输出,
这表明它甚至根本没有运行完整的两批
(并且评估仍在使用培训数据)
------------------------------------------------------------
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']
如果我将num_epochs
中的tf.train.string_input_producer()
参数设置为1
希望它会冲出来
来自队列的任何附加训练数据,以便它可以使用验证
数据,我得到以下输出,这表明它一直在终止
它经历了一个训练数据的时代,并没有通过
加载评估数据。
------------------------------------------------------------
TRAIN_BATCH: ['train_file_0' 'train_file_1' 'train_file_2']
TRAIN_BATCH: ['train_file_3' 'train_file_4' 'train_file_5']
capacity
参数设置为各种值我也尝试过设置capacity
参数
tf.train.string_input_producer()
为小值,例如3和1.但是这些
对结果没有影响。
我可以采取哪种其他方法来切换培训和验证数据? 我是否必须创建单独的队列?我不知道如何做到这一点 工作。我是否还需要创建其他协调员和队列运行器?
答案 0 :(得分:9)
我正在编制一份可能解决此问题的潜在方法列表。其中大多数只是模糊的建议,没有实际的代码示例来展示如何使用它们。
建议here
建议here
sygi也建议在这个非常stackoverflow线程上。 link
建议here
。这可能与make_template()方法相同。
建议的here示例代码here 代码在这个帖子上适应了我的问题。 link
建议here
答案 1 :(得分:8)
首先,您可以手动阅读代码中的示例(到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})
如果您需要使用队列,您可以尝试有条件地更改队列#34; training"到"测试"之一:
train_filenames = tf.string_input_producer(["training_file"])
train_q = some_reader(train_filenames)
test_filenames = tf.string_input_producer(["testing_file"])
test_q = some_reader(test_filenames)
am_testing = tf.placeholder(dtype=bool,shape=())
data = tf.cond(am_testing, lambda:test_q, lambda:train_q)
train_op, accuracy = model(data)
for _ in xrange(num_epochs):
sess.run(train_op, feed_dict={am_testing: False})
sess.run(accuracy, feed_dict={am_testing: True})
第二种方法是considered unsafe - 在这篇文章中,我们鼓励为培训和测试(共享权重)构建两个单独的图表,这是达到你想要的另一种方式。
答案 2 :(得分:3)
好的,所以我有一个适合我的解决方案。它基于在tensorflow github问题部分中从this post获取的代码。它使用QueueBase.from_list()
函数。感觉非常hacky,我对此并不完全满意,但至少我正在努力工作。
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']
我打开这个主题,希望有一个更好的解决方案。
答案 3 :(得分:2)
创建两个不同的队列是discouraged。
如果您有两台不同的机器,我建议您使用单独的机器进行培训和验证(如果没有,您可以使用两种不同的流程)。对于2个机器案例:
model_iteration
)保存在第二台机器可以访问它的地方。这种方法很少有优点。培训/验证数据是分开的,您不能搞砸它们。您可以使用弱机器进行验证,因为即使验证滞后于培训(不太可能的情况),也不是问题,因为它们是独立的