sagemaker 水平缩放 tensorflow (keras) 模型

sagemaker horizontally scaling tensorflow (keras) model

我大致按照这个脚本fashion-MNIST-sagemaker

我在笔记本上看到了

from sagemaker.tensorflow import TensorFlow

tf_estimator = TensorFlow(entry_point='mnist_keras_tf.py', 
                          role=role,
                          train_instance_count=1, 
                          train_instance_type='local',
                          framework_version='1.12', 
                          py_version='py3',
                          script_mode=True,
                          hyperparameters={'epochs': 1}
                         )

我想知道我可以并且应该在多大程度上使用 train_instance_count 参数。它会自动沿着某个维度分配训练吗,如果是 - 维度是什么?

此外,在基于 keras(使用 tensorflow)的设置中水平分布训练通常有意义吗?

分布式训练是特定于模型和框架的。并非所有模型都易于分发,从 ML 框架到 ML 框架的事情也并非同样容易。 它很少是自动的,对于 TensorFlow 和 Keras 更是如此。

神经网络在概念上很容易在数据并行范式下分布,由此给定的小批量的梯度计算在工作人员之间分配,工作人员可以是同一主机(多设备)中的多个设备或多个每个主机都有多个设备(多设备多主机)。 D2L.ai 课程深入介绍了神经网络的分布方式 here and here

Keras 曾经很容易通过 multi_gpu_model, which will sadly get deprecated in 4 months. In your case, you seem to refer to multi-host model (more than one machine), and that requires writing ad-hoc synchronization code such as the one seen in this official tutorial 以多设备、单主机方式分发。

现在让我们看看这与 SageMaker 有什么关系。

SageMaker 带有 3 个算法开发选项。根据您选择的选项,使用分布式训练可能需要不同数量的自定义工作:

  1. 内置算法是一个包含 18 种预写算法的库。很多都是写成分布在单主机多GPU或者多GPU多主机。使用第一个选项,除了设置 train_instance_count > 1 以分布在多个实例

  2. 之外,您无需做任何事情
  3. 框架容器(您正在使用的选项)是为流行框架(TensorFlow、PyTorch、Sklearn、MXNet)开发的容器,并提供预先编写的docker 可以编写任意代码的环境。在此选项中,某些容器将支持一键创建临时训练集群以进行分布式训练,但是使用大于 1 的 train_instance_count 不足以分布式训练您的模型。它只会 运行 您在多台机器上的脚本。为了分发您的训练,您必须在 mnist_keras_tf.py 脚本中编写适当的分发和同步代码。 对于某些框架,此类代码修改将非常简单,例如对于 TensorFlow 和 Keras,SageMaker 自带预装 Horovod。 Horovod 是一种点对点环形通信机制,需要极少的代码修改并且具有高度可扩展性 (initial annoucement from Uber, SageMaker doc, SageMaker example, SageMaker blog post)。我的建议是尝试使用 Horovod 来分发您的代码。同样,在 Apache MXNet 中,您可以轻松创建参数存储以分布式方式托管模型参数并从多个节点与它们同步。 MXNet 的可扩展性和易于分发是亚马逊喜欢它的原因之一。

  4. Bring-Your-Own Container 要求您同时编写 docker 容器和算法代码。在这种情况下,你当然可以将你的训练分布在多台机器上,但你也必须编写机器对机器的通信代码

对于您的具体情况,我的建议是首先在具有多个 GPU 的单个节点中水平扩展,而不是越来越大的机器类型,因为当您从单主机切换到多主机上下文时,延迟和复杂性会急剧增加。如果确实有必要,请使用多节点上下文,如果使用 Horovod 完成,事情可能会更容易。 在任何情况下,使用 SageMaker 做事情仍然容易得多,因为它管理临时的、按秒计费的集群的创建,具有内置的日志记录和元数据以及工件持久性,并且还处理从 s3 快速加载训练数据,在训练中分片节点。

关于分布式训练相关性的说明:请记住,当您在 N 台设备上分发一个在一台设备上 运行 正常的模型时,您通常将批量大小增加 N,以便每个设备的批量大小保持不变,并且每个设备都保持忙碌。这会扰乱您的模型收敛,因为更大的批次意味着更小的 SGD 噪声。一种常见的启发式方法是将学习率提高 N(更多信息见 this great paper from Priya Goyal et al),但另一方面这会在前几个时期引起不稳定,因此有时它与学习率预热有关。扩展 SGD 以适用于非常大的批次仍然是一个活跃的研究问题,新想法经常出现。使用非常大的批次达到良好的模型性能有时需要特别研究和大量的参数调整,有时需要花费额外的钱来寻找如何很好地分配,从而抵消你最终设法实现的更快训练的好处 运行。分布式训练有意义的情况是当单个记录代表太多计算而无法在设备上形成足够大的物理批次时,这种情况出现在大输入尺寸(例如高清图片上的视觉)或大参数计数(例如 BERT)上。话虽这么说,对于那些需要非常大的逻辑批次的模型,您不一定必须物理分配东西:您可以 运行 通过单个 GPU 按顺序进行 N 个批次,并在进行梯度平均之前等待每个设备的 N 个批次,并且参数更新以模拟具有 N 倍大的 GPU。 (有时称为 梯度累积 的巧妙技巧)