【问题标题】:Tensorflow - properly (natively?) handling data batching overlaps (mini-batches?) for multiple epochsTensorflow - 正确(本机?)处理多个时期的数据批处理重叠(小批量?)
【发布时间】:2017-11-01 13:30:25
【问题描述】:

EDIT3:你不能在本地这样做,我标记了这样说的答案。但是,对于那些好奇的人,我在下面的另一个答案中发布了一个示例解决方案。

EDIT2:下面带有问题复制的简单代码。

编辑:这不是关于如何在多个时期排队/批处理的问题,这就是重复/建议的帖子所解释的,我特别问的是如何获得不完美的批处理尺寸工作正常。那篇文章只是提到“allow_smaller_final_batch=True”参数应该解释这种情况,但似乎没有(如下面的代码所示)。

在我的 TF 神经网络中,我使用 tf.train.slice_input_producertf.train.batch 在多个时期对我的数据进行批处理,当我的批处理大小是我的样本数量的完美倍数时,它可以完美地工作。

不幸的是,如果不是这样,一个纪元的最后一批会拖到下一个纪元(即没有真正的“纪元”划分),这最终意味着每个纪元都是不同的。示例:

2 Epochs * 12 个样本 = 24 个总值,Batch_size = 5,

什么是正确的:

第 1 阶段:[5 项]、[5 项]、[2 项]

第 2 纪元:[5 项]、[5 项]、[2 项]

实际操作:

第 1 阶段:[5 项]、[5 项]、[5 项]

第 2 阶段:[5 项]、[4 项]、[0 项:超出范围]

生成上述示例的代码(与我的 NN 实现非常相似):

import tensorflow as tf
import numpy as np

batch_size = 5
epochs = 2
Data = list(range(12))
iterations = int(np.ceil(len(Data)/batch_size)*epochs)
sess = tf.InteractiveSession()

x1 = tf.train.slice_input_producer([Data], num_epochs=epochs)
x2 = tf.train.batch(x1, batch_size=batch_size, allow_smaller_final_batch=True)

sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)

for i in range(iterations):
   temp_batch = sess.run(x2)
   print('\n' + str(temp_batch))
sess.close()

我知道这可能只是 tf.train.slice_input_producer 工作方式的副产品,我可能可以通过各种方式手动实现/避免这种情况,但是有没有办法通过切片本地区分一个时代的“结束”?

【问题讨论】:

  • 感谢 frankyjuang 的回复;这里的不同之处在于我的一般排队工作得很好(这更多是该帖子所要求的),但我没有得到该帖子中描述/暗示的重叠行为。
  • 你能提供能重现这个的最小代码吗?
  • 我已经在原帖中包含了代码,请看一下,谢谢=)
  • 在深入研究了一些 tf 代码之后,我得出了结论。请在我的回答中找到。

标签: python tensorflow


【解决方案1】:

迭代计算不正确

这就是你的迭代计算应该是的

iterations = int(np.ceil(1.0*len(Data)/batch_size*epochs))

当我在您的代码中更改该行时,我得到以下输出

[ 2  5  6 10  3]
[ 9  4  7  8 11]
[ 1  0 10  6  2]
[3 8 9 0 5]
[ 1  4 11  7]

您的计算包含 len(Data)/batch_size,它以整数数学计算并且已经被截断。通过将其乘以 1.0,您可以强制它为浮点数,并且您的数学运算有效。

【讨论】:

  • 馄饨馄饨,谢谢您的回复!尽管您进行了更改,但您得到的输出仍然与我得到的相同,这是我试图指出的问题。例如,使用您生成的相同“分布”,输出应该像这样分组 [2 5 6 10 3], [9 4 7 8 11], [1 0] ||||END BATCH 1||| | [10 6 2 3 8]、[9 0 5 1 4]、[11 7]。希望这是有道理的。
  • 啊,是的,我认为您的问题是 out of bounds 错误。我建议的代码更改修复了该问题并运行正确的迭代次数没有 try/catch 语句。
【解决方案2】:

不幸的是,没有办法以原生方式区分每个时代的结束。这是因为一般用法不需要​​将训练过程分成几个时期。例如,fully_connected_preloaded.py

如果你想在每个 epoch 结束时做一些事情,你必须手动处理它。如果没有,不用自己计算迭代,担心出错,可以使用coord.should_stop()处理:

try:
    while not coord.should_stop():
        temp_batch = sess.run(x2)
        print('\n' + str(temp_batch))
except tf.errors.OutOfRangeError:
    print("Done training, epoch limit reached.")
finally:
    coord.request_stop()    # Ask the threads to stop.

coord.join(threads)    # Wait for threads to stop.

【讨论】:

  • 感谢您的回复;不幸的是,我认为这最终会成为这种情况。很容易适应,但还是很伤心。感谢您对此进行调查并提供coord.should_stop() 的提示,非常感谢。
  • 使用 try/catch 而不是仅仅修复数学不是一个好方法。
  • 我继续做了一个简单的示例,如果您好奇,它可以按预期工作,并将其作为附加答案发布。
  • @wontonimo try/catch 方法其实就是Threading and Queues中提到的官方例子。
【解决方案3】:

如果有人想根据我的简单示例(不是本机示例)知道如何执行此操作:

import tensorflow as tf
import numpy as np

batch_size = 5
epochs = 2
Data = list(range(12))
iter_epoch = int(np.ceil(len(Data)/batch_size))
iterations = (iter_epoch)*epochs
mini_size = len(Data) % batch_size

def make_nparray(constant):
    return(np.array([np.int32(constant)]))

sess = tf.InteractiveSession()

batch_ph = tf.placeholder(dtype=np.int32,shape=(1,))
x1 = tf.train.slice_input_producer([Data], num_epochs=epochs)
x2 = tf.train.batch(x1, batch_size=batch_ph[0])

sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)

for i in range(iterations):
    not_mini = (i+1) % iter_epoch != 0
    if not_mini:
        temp_batch = sess.run(x2,feed_dict={batch_ph:make_nparray(batch_size)})
    else:
        temp_batch = sess.run(x2,feed_dict={batch_ph:make_nparray(mini_size)})
    print('\n' + str(temp_batch))
coord.request_stop()
sess.close()

【讨论】:

    【解决方案4】:

    就像 @Wanne-be Coder 所示,您只需要使用整数占位符来自己控制批量大小。相关部分是:

    batch_size = tf.placeholder(tf.int32, [])
    x2 = tf.train.batch(x1, batch_size=batch_size)
    batch1 = sess.run(x2, feed_dict={batch_size: 5}) # 5 items in batch1
    batch2 = sess.run(x2, feed_dict={batch_size: 5}) # 5 items in batch2
    batch3 = sess.run(x2, feed_dict={batch_size: 2}) # 2 items in batch3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 2011-08-03
      • 2019-08-22
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 2010-12-17
      相关资源
      最近更新 更多