Tensorflow:是否可以修改检查点中的全局步骤

时间:2018-01-29 03:24:51

标签: python tensorflow machine-learning

我正在尝试修改检查点中的global_step,以便我可以将训练从一台机器移动到另一台机器。

假设我在机器A上进行了几天的培训。现在我买了一台带有更好图形卡和更多GPU内存的新机器B,并希望将培训从机器A转移到机器B.

为了恢复机器B中的检查点,我之前在机器A的global_step中指定了Saver.save,但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。< / p>

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的数量减少而产生错误的sub_iterations在机器B中。

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

我们将从新的ij开始迭代。请随意对此发表评论,因为这可能不是恢复检查点并继续从加载检查点进行培训的好方法。

编辑2

在机器A中,假设iterations为10,000,sub_iterations为500,batch_size为10.因此,我们打算训练的批次总数为10000x500x10 = 50,000,000。假设我们已经培训了好几天,global_step变成了501。因此,培训的批次总数为501x10 = 5010.未经培训的剩余批次数为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,并调整{{ 1}}到50但将sub_iterations保留为10000.要训练的批次总数仍为50,000,000。问题来了,我们如何开始和训练批次从5011到50,000,000并且不再为第一批5010样品进行培训?

为了从机器B中的5011启动和训练批次,我们应该将iterations设置为1并将i设置为0,因为它已经训练的总批次将是(1 * 50 + 0) )* 100 = 5,000接近5,010(因为机器B中j为100而机器A中为10,我们无法从5,010开始,我们可以选择5,000或5,100)。

如果我们不调整batch_size(由@ coder3101建议),并在机器B中使用global_step,则i, j = int(gstep/ sub_iterations), numpy.mod(gstep, sub_iterations)将变为501/50 = 10且{{1将变为501%50 = 1。因此,我们将从批次50,100(= 501 * i = 501 * 100)开始并进行训练,这是不正确的(不接近5010)。

引入此公式j是因为如果我们在一个点停止机器A的训练,我们可以使用此公式恢复检查点并继续在机器A中进行训练。然而,当我们将训练从机器A移动到机器B时,似乎这个公式似乎不适用。因此,我希望修改检查点中的batch_size来处理这种情况,并想知道这是否可行。

2 个答案:

答案 0 :(得分:4)

是。这是可能的。

要修改机器B中的global_step,您必须执行以下步骤:

计算相应的global_step

在上面的例子中,机器A中的global_step是501,训练批次的总数是501x10 = 5010。因此机器B中相应的global_step为5010/100 = 50。

修改检查点文件名

修改model_checkpoint_pathall_model_checkpoint_paths值的后缀,以在/ checkpoint中使用正确的步骤编号(例如上例中的50)。

修改检查点的索引,元数据和数据的文件名,以使用正确的步骤编号。

恢复检查点后覆盖global_step

saver.restore(session, model_checkpoint_path)
initial_global_step = global_step.assign(50)
session.run(initial_global_step)
...
# do the training

现在,如果您恢复检查点(包括global_step)并覆盖global_step,则培训将使用更新后的global_step并调整ij以及learning_rate正确。

答案 1 :(得分:1)

如果你想让机器B上的衰减学习率与A上的相同,你可以调整函数tf.train.exponential_dacay的其他参数。例如,您可以更改新计算机上的衰减率。

为了找到decay_rate您需要知道如何计算exponential_decay

  

decay_learning_rate = learning_rate * decay_rate ^   (global_step / decay_steps)

如果阶梯==真

global_step/decay_step会产生一个纯整数

decay_stepssub_iteration,而global_step来自机器A.

您可以更改decay_rate,使机器B上的新学习率与global_step处机器A的学习率相同或接近。

此外,您可以更改机器B的初始学习率,以实现从机器A到B的均匀指数速率衰减。

因此,在从A导入B到B时,您已经更改了1个变量(sub_iteration),并保持global_step相同。您可以调整exponential_decay(..)的其他2个变量,使得函数的输出学习速率与您在global_step处的机器A的预期相同。