【问题标题】:Passing a numpy array to a tensorflow Queue将 numpy 数组传递给 tensorflow 队列
【发布时间】:2016-08-21 19:47:25
【问题描述】:

我有一个 NumPy 数组,并希望使用 Queue 在 TensorFlow 的代码中读取它。我希望队列返回打乱后的整个数据,一些指定的时期数,然后抛出错误。如果我不需要硬编码示例的大小或示例的数量,那将是最好的。 我认为shuffle batch 就是为了达到这个目的。我试过如下使用它:

data = tf.constant(train_np) # train_np is my numpy array of shape (num_examples, example_size)
batch = tf.train.shuffle_batch([data], batch_size=5, capacity=52200, min_after_dequeue=10, num_threads=1, seed=None, enqueue_many=True)

sess.run(tf.initialize_all_variables())
tf.train.start_queue_runners(sess=sess)
batch.eval()

这种方法的问题是它连续读取所有数据,我无法指定它在一定数量的时期后完成。我知道我可以使用RandomShuffleQueue 并将数据插入其中几次,但是: a)我不想浪费内存的 epoch*data 和 b)它将允许队列在 epoch 之间洗牌。

有没有一种无需编写自己的队列就可以在 Tensorflow 中读取 epoch 中的混洗数据的好方法?

【问题讨论】:

    标签: python numpy tensorflow


    【解决方案1】:

    您可以创建另一个队列,将您的数据排入队列num_epoch 次,关闭它,然后将其连接到您的batch。为了节省内存,您可以使这个队列变小,并将项目并行排入队列。时代之间会有一些混合。为完全防止混合,您可以将下面的代码与num_epochs=1 一起调用,并将其称为num_epochs 次。

    tf.reset_default_graph()
    data = np.array([1, 2, 3, 4])
    num_epochs = 5
    queue1_input = tf.placeholder(tf.int32)
    queue1 = tf.FIFOQueue(capacity=10, dtypes=[tf.int32], shapes=[()])
    
    def create_session():
        config = tf.ConfigProto()
        config.operation_timeout_in_ms=20000
        return tf.InteractiveSession(config=config)
    
    enqueue_op = queue1.enqueue_many(queue1_input)
    close_op = queue1.close()
    dequeue_op = queue1.dequeue()
    batch = tf.train.shuffle_batch([dequeue_op], batch_size=4, capacity=5, min_after_dequeue=4)
    
    sess = create_session()
    
    def fill_queue():
        for i in range(num_epochs):
            sess.run(enqueue_op, feed_dict={queue1_input: data})
        sess.run(close_op)
    
    fill_thread = threading.Thread(target=fill_queue, args=())
    fill_thread.start()
    
    # read the data from queue shuffled
    tf.train.start_queue_runners()
    try:
        while True:
            print batch.eval()
    except tf.errors.OutOfRangeError:
        print "Done"
    

    顺便说一句,当队列不足以将整个 numpy 数据集加载到其中时,上面的enqueue_many 模式将挂起。您可以通过按如下块加载数据来灵活地拥有更小的队列。

    tf.reset_default_graph()
    data = np.array([1, 2, 3, 4])
    queue1_capacity = 2
    num_epochs = 2
    queue1_input = tf.placeholder(tf.int32)
    queue1 = tf.FIFOQueue(capacity=queue1_capacity, dtypes=[tf.int32], shapes=[()])
    
    enqueue_op = queue1.enqueue_many(queue1_input)
    close_op = queue1.close()
    dequeue_op = queue1.dequeue()
    
    def dequeue():
        try:
            while True:
                print sess.run(dequeue_op)
        except:
            return 
    
    def enqueue():
        for i in range(num_epochs):
            start_pos = 0
            while start_pos < len(data):
                end_pos = start_pos+queue1_capacity
                data_chunk = data[start_pos: end_pos]
                sess.run(enqueue_op, feed_dict={queue1_input: data_chunk})
                start_pos += queue1_capacity
        sess.run(close_op)
    
    sess = create_session()
    
    enqueue_thread = threading.Thread(target=enqueue, args=())
    enqueue_thread.start()
    
    dequeue_thread = threading.Thread(target=dequeue, args=())
    dequeue_thread.start()
    

    【讨论】:

    • 您能否详细说明它是如何工作的(可能指向文档)?特别是:为什么创建一个单独的线程并将所有元素排入队列num_epochs 时间不会使用太多内存?并且:如果您多次将数据排入 FIFO 队列,为什么会有元素混合?只有当一个时代结束而另一个时代开始时?此外,调用整个代码num_epochs 次远非“读取数据的好方法”:P
    • 如果您的队列容量为 10,那么它在任何时候只需要 10 个示例的空间,并且异步队列加载会在消耗之前的示例时添加更多示例。 (shuffle_batch) 创建的第二个队列不知道 epoch 在哪里结束,因此一个 epoch 的最后一批可能也有来自下一个 epoch 的条目。
    • 队列的文档是here,here 是我在他们的演讲中的幻灯片
    • 你可能知道为什么我只有在指定操作超时时才会出现以下错误? CancelledError: Dequeue operation was cancelled [[Node: shuffle_batch = QueueDequeueMany[_class=["loc:@shuffle_batch/random_shuffle_queue"], component_types=[DT_INT32], timeout_ms=-1, _device="/job:localhost/replica:0/task:0/cpu:0"](shuffle_batch/random_shuffle_queue, shuffle_batch/n)]]
    • 我喜欢指定超时,因为默认超时是无限的,谁有时间等这么久?在实践中,您可以使用更大的值,例如 120 秒(第一次加载 cuda 内容可能需要 60 秒)。当有落后者时,您可以收到类似上面的消息——即,也许没有足够的项目来填充最后一批,所以它想永远等待,超时终止等待。你可以改用dequeue_up_to
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多