【发布时间】:2018-01-29 03:24:50
【问题描述】:
我正在尝试修改检查点中的global_step,以便将训练从一台机器转移到另一台机器。
假设我在机器 A 上训练了几天。现在我买了一台新机器 B,它有更好的显卡和更多的 GPU 内存,想把训练从机器 A 转移到机器 B。
为了恢复机器B中的检查点,我之前在机器A的Saver.save中指定了global_step,但batch_size更小,sub_iterations更大。
batch_size=10
sub_iterations=500
for (...)
for i in range(sub_iterations):
inputs, labels = next_batch(batch_size)
session.run(optimizer, feed_dict={inputs: inputs, labels: labels})
saver = tf.train.Saver()
saver.save(session, checkpoints_path, global_step)
现在我将包括检查点在内的所有文件从机器 A 复制到机器 B。由于机器 B 有更多 GPU 内存,我可以将 batch_size 修改为更大的值,但使用更少的 sub_iterations。
batch_size=100
sub_iterations=50 # = 500 / (100/10)
for (...)
for i in range(sub_iterations):
inputs, labels = next_batch(batch_size)
session.run(optimizer, feed_dict={inputs: inputs, labels: labels})
但是我们不能直接恢复复制的检查点,因为global_step在机器B中是不同的。例如,tf.train.exponential_decay将产生不正确的learning_rate,因为机器B中sub_iterations的数量减少了。
learning_rate = tf.train.exponential_decay(..., global_step, sub_iterations, decay_rate, staircase=True)
是否可以修改检查点中的global_step?还是有其他更合适的方法来处理这种情况?
编辑 1
除了计算learning_rate之外,我还使用了global_step来计算和减少迭代次数。
while i < iterations:
j = 0
while j < sub_iterations:
inputs, labels = next_batch(batch_size)
feed_dict_train = {inputs: inputs, labels: labels}
_, gstep = session.run([optimizer, global_step], feed_dict=feed_dict_train)
if (i == 0) and (j == 0):
i, j = int(gstep/ sub_iterations), numpy.mod(gstep, sub_iterations)
j = j + 1
i = i + 1
我们将从新的i 和j 开始迭代。请随时对此发表评论,因为这可能不是恢复检查点并从加载的检查点继续训练的好方法。
编辑 2
在机器 A 中,假设 iterations 是 10,000,sub_iterations 是 500,batch_size 是 10。所以我们要训练的批次总数是 10000x500x10 = 50,000,000。假设我们已经训练了几天,global_step 变成了501。所以训练的batch总数为501x10 = 5010。剩余未训练的batch数量为5011到50,000,000。如果我们应用i, j = int(gstep/ sub_iterations), numpy.mod(gstep, sub_iterations),i 的最后训练值是 501/500=1,j 是 501%500=1。
现在您已将包括检查点在内的所有文件复制到机器 B。由于 B 具有更多 GPU 内存,我们可以为一个子迭代训练更多批次,我们将 batch_size 设置为 100,并将 sub_iterations 调整为50 但将iterations 保留为 10000。要训练的总批次数仍然是 50,000,000。那么问题来了,我们如何才能开始训练从 5011 到 50,000,000 的批次,并且不对前 5010 个样本再次进行训练?
为了在机器 B 中从 5011 开始和训练批次,我们应该将 i 设置为 1 并将 j 设置为 0,因为它已训练的总批次将是 (1*50+0)*100 = 5,000 接近 5,010(因为 batch_size 在机器 B 中是 100 而在机器 A 中是 10,所以我们不能完全从 5,010 开始,我们可以选择 5,000 或 5,100)。
如果我们不调整global_step(如@coder3101所建议的那样),并在机器B中使用回i, j = int(gstep/ sub_iterations), numpy.mod(gstep, sub_iterations),i将变为501/50=10,j将变为501%50= 1.所以我们将从不正确的批次 50,100 (=501*batch_size=501*100) 开始训练。
之所以引入这个公式i, j = int(gstep/ sub_iterations), numpy.mod(gstep, sub_iterations)是因为如果我们停止机器A的训练,我们可以恢复检查点并使用这个公式继续机器A的训练。但是,当我们将训练从机器 A 转移到机器 B 时,似乎这个公式不适用。因此我希望修改检查点中的 global_step 来处理这种情况,并想知道这是否可能。
【问题讨论】:
-
您的编辑包含可能引发 ZeroDivisionError @ int (gstep/iterations) 的代码。执行此操作时,您会看到迭代次数为零。另外,我无法通过您的 EDIT 获得您想要传达的内容。请简要说明。
-
@coder3101 很抱歉我打错字了,我的意思是分割/修改
sub_iterations。请查看我更新的代码,其中解释了我使用了从检查点恢复的gstep,并设置了i和j,它们有效地从上次训练的上一次迭代开始。
标签: python tensorflow machine-learning