tf.estimator 的分布式训练导致更多的训练步骤

Distributed Training with tf.estimator resulting in more training steps

我正在 Cloud ML Engine 上试验分布式训练选项,我观察到一些奇怪的结果。我基本上更改了人口普查自定义估算器示例以包含稍微不同的模型,并将我的损失函数更改为 AdamOptimizer 作为唯一真正的更改。基于这个 ,我的理解是任何分布式训练都应该是数据并行异步训练,这表明 "If you distribute 10,000 batches among 10 worker nodes, each node works on roughly 1,000 batches." 在我的实验中,我有 ~650k 个训练样本,我是 运行以下实验针对 1 个批次大小为 128 的时期。给定 650k 训练示例和批次大小为 128,我预计一个时期会有 ~5.1k 步。这是我看到的不同 --scale-tier

的表现

未分发

分布式

我的期望是,基于这篇文章的数据并行是分布式训练会在所有工人之间拆分批次,所以如果我有 5 名工人处理 ~5k 批次,那么每个工人将执行 ~1,000批次。然而,我观察到的实际行为是,它似乎更接近 5 名工人中的每一个自己执行 1 个时期。在分布式设置中训练时,一个时期采取的步骤是训练示例的 6 倍——我知道每次梯度更新时步骤的真正定义,但我对数据并行训练的理解是这只会拆分批次,因此应该有相同数量的梯度更新——有什么理由可以预期这种行为吗?在数据并行异步训练分布式环境中需要更多训练步骤是否有意义?谁能解释我观察到的行为?

有两种类型的服务器:

  • Workers:执行图形计算
  • 参数服务器:存储参数,所有worker都可以共享和更新参数

参数服务器可能存在瓶颈。如果模型非常大并且参数服务器很少,则需要在工作人员和参数服务器之间进行更多通信。例如,如果您有 2 个参数服务器,您将在一个服务器中拥有一半的模型参数,另一半在另一个服务器中。如果你有很多工人,他们将不得不获取和发送大量参数给不同的工人,工人会有很大的滞后。如果增加参数服务器的数量,延迟将会减少,因为每个参数服务器与工作人员之间的通信较少。

因为你的batch size是128(相当大)而且你每秒只能执行8步 CPU 我认为你的模型太快了以至于需要更多的时间来共享服务器的参数比 运行 一次迭代。所以你也可以尝试增加批量大小。

前面的回答很好地解释了性能瓶颈。让我解释一下 "epochs" 以及 TensorFlow 如何处理数据集。

TensorFlow 中分布式训练的工作方式是每个工作人员独立迭代整个数据集。一个常见的误解是训练集是在工人之间划分的,但事实并非如此。

在典型的队列设置中(参见 this tutorial),每个工作人员都会创建自己的队列。该队列中充满了所有训练文件的所有文件名的列表(通常该列表会被打乱,每次队列用完时,它都会重新填充并重新打乱)。每个文件都逐个实例地读取,数据被解析、预处理,然后被送入另一个队列,在该队列中对实例进行洗牌和批处理。一旦读取了任何文件的最后一个实例,下一个文件名就会从文件名队列中弹出。如果没有更多文件要弹出,则 "epoch" 已完成。

这里的要点是所有这些队列在默认情况下都是 local -- 不共享。因此,每个工作人员都在独立地重复相同的工作——创建包含所有文件的队列并遍历整个数据集。那么,一个完整的 epoch 大致等于完整数据集中的实例数 * 工人数。 (我不确定你的 standard_1 结果,但是 CUSTOM 上的结果意味着你有你的主人 + 5 个工人 = 6 个工人 * 650K 个例子 *(1 个批次/128 个例子)= 31K 个步骤)。

仅供参考,不鼓励使用 epochs 来参数化分布式训练,因为它太混乱了,而且通常甚至可能存在问题。坚持 max_steps.

请注意,由于 TensorFlow 的设计,"batch size" 表示每个工人的批量大小 。但是每个工作人员将以大致相同的速率向参数服务器发送更新,因此在大致相当于处理一个 "batch" 所需时间的时间段内,参数发生的更新次数大致为batch_size * num_workers。这就是我们所说的 effective 批量大小。这反过来又会产生一些实际后果:

  1. 您倾向于使用较小的 batch_sizes,尤其是当您有大量工作人员时,这样 有效 批量大小保持合理。
  2. 随着工作人员数量的增加,有效批次大小也会增加,因此您需要降低学习率,至少在使用 "vanilla" 随机梯度下降时如此。具有自适应学习率的优化器(例如 Adagrad、Adam 等)往往对初始学习率具有鲁棒性,但如果添加足够的 worker,您仍然可能需要调整学习率。

您可能想知道为什么 TensorFlow 以这种方式处理训练数据。这是因为在分布式系统中,您不能指望机器具有相同的速度,甚至根本不可靠。如果您将训练数据划分为不相交的集合,发送给每个工作人员,然后一台或多台机器相对于另一台机器速度较慢,或者网络在一台机器上出现故障,等等,您的训练过程将看到来自 "fast"/可靠的工人比"slow"/不可靠的工人更频繁。这会使结果偏向那些实例(或者在极端情况下,将它们全部忽略)。