介绍

在大型数据集上训练的现代神经网络架构可以在各种领域获得令人印象深刻的性能表现,从语音和图像识别,到自然语言处理,再到欺诈检测和推荐系统等行业关注的应用。 但是训练这些神经网络模型在计算上要求很高。 虽然近年来在GPU硬件、网络架构和训练方法方面取得了重大进展,但事实仍然是网络训练在单个机器上可能花费很长时间。 幸运的是,我们并不局限于一台机器:已经开展了大量的工作和研究,以实现神经网络的高效分布式训练。

我们首先考虑两种并行/分布训练计算的方法。

分布式神经网络多模态数据_数据

模型并行(model parallelism)中,分布式系统中的不同机器负责单个网络的不同部分的计算 - 例如,神经网络中的每个层可以被分配给不同的机器。

数据并行(data parallelism)中,不同的机器具有完整的模型副本; 每台机器只是获取数据的不同部分,并且每个机器的结果以某种方式组合。

当然,这些方法并不相互排斥。 考虑一组多GPU的系统,我们可以为每台机器使用模型并行(模型跨GPU分割),并在机器之间使用数据并行。

分布式神经网络多模态数据_神经网络分布式_02


虽然模型并行在实践中可以很好地工作,但数据并行可以说是分布式系统的首选方法,并且一直是更多研究的重点。 一方面,数据并行比模型并行性更容易实现,在容错和集群利用率上也容易。 分布式系统环境中的模型并行很有趣,并且确实具有一些优点(例如大型模型的可扩展性),但在这里我们将关注数据并行。

数据并行

分布式训练的数据并行方法在每个工作机器上保留整个模型的副本,在每个工作机器上处理训练数据集的不同子集。 数据并行训练方法都需要一些组合结果和在每个worker之间同步模型参数的方法,文献中讨论了许多不同的方法,方法之间的主要区别是:

  • 参数平均方法 vs 基于更新(梯度)的方法
  • 同步方法 vs 异步方法
  • 中心化同步 vs 分布式同步

Deeplearning4j的当前Spark实现是一个同步参数平均,其中Spark driver和reduction操作取代了参数服务器。

参数平均

Parameter Averaging
参数平均是概念上最简单的数据并行方法。 通过参数平均,训练如下进行处理:

  1. 根据模型配置随机初始化网络参数;
  2. 把当前参数分发到每个worker;
  3. 在数据子集上训练每个worker;
  4. 把全局参数设置为每个worker上参数的均值;
  5. 如果还有数据处理,回到第二步;

第二步到第四步通过下图展示,在途中,W代表神经网络中参数(weights, biases),下标用于做随着时间参数版本的索引,必要时为每个机器确定下标。

分布式神经网络多模态数据_分布式神经网络多模态数据_03


实际上,可以直接证明参数平均的受限版本在数学上与单个机器上的训练相同; 这些重组是每个小批量后的参数平均值,没有更新(即没有动量momentum等 - 只是乘以学习率),以及每个worker处理的相同数量的样本。 证明如下。

In fact, it’s straightforward to prove that a restricted version of parameter averaging is mathematically identical to training on a single machine; these restructions are parameter averaging after each minibatch, no updater (i.e., no momentum etc - just multiplication by learning rate), and an identical number of examples processed by each worker.考虑具有n个worker的集群的情况,其中每个worker处理m个示例,对于在平均值之间处理的总共分布式神经网络多模态数据_神经网络分布式_04个样本。 如果我们在用学习率α的单台机器上处理所有nm个样本,我们的权重更新规则由下式给出:

分布式神经网络多模态数据_分布式机器学习_05

如果我们改为在n个worker每个中学习m个样本(其中worker1得到样本分布式神经网络多模态数据_数据_06,worker2得到样本分布式神经网络多模态数据_神经网络分布式_07等等),我们有:

分布式神经网络多模态数据_神经网络分布式_08

当然,这个结果在实践中并不成立(每个小批量的平均并且不使用诸如动量或RMSProp之类的updater都是不明智的,出于性能和收敛的原因),但它确实让我们对参数平均为什么工作很好有个直观感觉,特别是当参数频繁平均时。

现在,参数平均在概念上很简单,但是我们已经掩盖了一些并发症。

首先,我们应该如何实现平均? 简单的方法是在每次迭代后简单地取参数平均值。 虽然这可行,但我们可能会发现这样做的开销不切实际; 网络通信同步成本可能会超过从额外机器获得的好处。 因此,参数平均通常在平均周期(根据worker的minibatch数量)大于1的情况下实施。但是,如果我们平均太不频繁,则每个worker的局部参数可能会发生过大的偏离,导致平均后的模型很差。 这里的直觉是N个不同的局部最小值的平均值不能保证是局部最小值:

分布式神经网络多模态数据_分布式机器学习_09

什么平均时期才是太高了? 这个问题尚未得到最终解答,并且通过与其他超参数的交互变得更加复杂,例如学习率、minibatch大小和worker数量。 关于该主题的一些初步研究(如[8])表明,每10至20个minibatch(每个worker)一次的平均周期仍然表现地很好。 随着平均周期的增加,模型精度当然会降低。

与adagrad,动量和RMSProp等优化方法相关的额外复杂性。 这些优化方法(在Deeplearning4j中称为“updaters”)已经被证明可以显着改善神经网络训练期间的收敛性。 但是,这些updaters具有内部状态(每个网络参数通常为1或2个状态值) - 我们是否应该对这些状态算平均值? 在每个worker里算内部updater状态平均值应该能导致更快地收敛,代价是双倍或者更多的网络传输的总大小。 一些工作还考虑在参数服务器级别应用类似的“updater”机制,而不仅仅是在每个worker([1])中。

异步随机梯度下降

Asynchronous Stochastic Gradient Descent

概念上类似于参数平均的方法是我们可以称之为“基于更新(update based)”的数据并行。 两者之间的主要区别在于,我们不是将参数从worker传递到参数服务器,而是传递update(即,学习率和动量的梯度等)。 这里提供了update的方式:
分布式神经网络多模态数据_神经网络分布式_10
其中分布式神经网络多模态数据_分布式机器学习_11是缩放因子(类似于learning rate超参)

架构上,看起来和parameter averaging很像:

分布式神经网络多模态数据_数据_12


熟悉训练神经网络数学的读者可能已经注意到参数平均和基于更新的方法之间存在直接的相似性。 如果我们再次将我们的损失函数定义为L,那么对于具有学习率α的简单SGD训练,在迭代分布式神经网络多模态数据_数据_13处的参数向量W通过以下方式获得(假设n个参数):

分布式神经网络多模态数据_分布式机器学习_14

其中:

分布式神经网络多模态数据_分布式神经网络多模态数据_15如果我们采取上面的更新规则,并对n个executor令分布式神经网络多模态数据_参数更新_16,为简介起见,再次使用只有学习率α的SGD,则更新为分布式神经网络多模态数据_参数更新_17,然后可以得到:

分布式神经网络多模态数据_参数更新_18


因此,当参数同步更新时(这一部分是关键),参数平均和基于更新的数据并行之间存在等价关系。 这种等价性也适用于多个平均step和其他updater(不仅仅是简单的SGD)。

当我们放松同步更新要求时,基于更新的数据并行变得更有趣(并可以说更有用)。也就是说,通过允许更新分布式神经网络多模态数据_数据_19一旦被计算就应用于参数向量(而不是等待所有worker的N≥1次迭代),我们获得异步随机梯度下降算法Async SGD有两个主要好处:

  • 首先,我们可以在分布式系统中获得更高的吞吐量:worker可以花更多的时间执行有用的计算,而不是等待参数平均步骤完成。
  • 其次,worker可能比使用同步(每N步)更新时更快地合并来自其他worker的信息(参数更新)。

然而,这些好处并非没有代价。 通过向参数向量引入异步更新,我们引入了一个新问题,称为陈旧梯度问题(stale gradient problem)。 陈旧的梯度问题非常简单:梯度(更新)的计算需要时间。 当worker完成这些计算并将结果应用于全局参数向量时,参数可能已经多次更新。 这个问题如下图所示。

分布式神经网络多模态数据_分布式机器学习_20


异步SGD的简单实现可能导致梯度的非常高的陈旧值。 例如,引用 [3]中表明平均梯度陈旧度等于worker的数量。 对于N个执行器,这意味着在将梯度应用于全局参数向量时,梯度将平均过时N步。 这具有现实世界的影响:高梯度过时会显著降低网络收敛速度,甚至会阻止某些配置收敛。 早期的异步SGD实现(例如Google的DistBelief系统[2])没有考虑到这种影响,因此学习效率远远低于原本应有水平。

异步随机梯度下降的大多数变体保持相同的基本方法,但应用各种策略来最小化陈旧梯度的影响,同时尝试维持高集群利用率。 应当注意,由于算法的同步性质,参数平均不受陈旧梯度问题的影响。

一些处理陈旧梯度的方法包括:

  • 基于梯度的陈旧性,针对每次更新分布式神经网络多模态数据_分布式神经网络多模态数据_21分别缩放值λ;
  • 实现‘软’同步协议(引用[9]);
  • 使用同步来绑定陈旧性(Use synchronization to bound staleness.)。 例如,引用[4]的系统在必要时延迟更快的worker,以确保最大陈旧度低于某个阈值;

所有这些方法都被证明可以改善原始异步SGD算法的收敛性。 值得注意的是前两个:基于陈旧性的缩放更新(陈旧的梯度对参数向量的影响较小)和软同步。 软同步(引用[9])非常简单:参数服务器不是立即更新全局参数向量,而是等待从n个learner中的(其中分布式神经网络多模态数据_神经网络分布式_22)收集数量s个更新分布式神经网络多模态数据_数据_23。 然后根据以下方式更新参数:
分布式神经网络多模态数据_神经网络分布式_24
其中分布式神经网络多模态数据_数据_25是标量的陈旧依赖缩放因子(staleness-dependent scaling factor),引用[9]提出分布式神经网络多模态数据_参数更新_26,其中分布式神经网络多模态数据_神经网络分布式_27是基于参数陈旧性的整数,但其他方法也是可能的(参见引用[6])。 soft sync和与staleness-dependent scaling 的组合比单独使用它们更好。

注意,通过设置分布式神经网络多模态数据_参数更新_28分布式神经网络多模态数据_分布式神经网络多模态数据_29常数,我们获得了原始异步SGD算法(如[2]所述); 类似地,通过设置分布式神经网络多模态数据_分布式机器学习_30,我们获得与同步参数平均相似(但不相同)的算法。

分散的异步随机梯度下降

decentralized asychronous stochastic gradient descent

引用[7]提出了一种用于执行神经网络分布式训练的更有趣的替代架构。 我将这种方法称为分散的同步随机梯度下降(尽管作者没有使用这个术语)。 这篇论文很有趣,主要有两个原因:

  • 系统中不存在集中式参数服务器(相反,点对点peer to peer通信用于在worker之间传输模型更新)。
  • 更新被大量压缩,导致网络通信的大小减少了大约3个数量级。

分布式神经网络多模态数据_参数更新_31

在标准数据并行实现中(使用参数平均或异步SGD),网络传输的大小等于参数向量大小(因为我们传输参数向量的副本,或每个参数一个梯度值)。 虽然压缩参数或更新的想法并不是全新的,但实现方式远远超出了其他简单的压缩机制(例如应用压缩编解码器或转换为16位浮点表示)。

这个设计的巧妙之处在于更新向量分布式神经网络多模态数据_参数更新_32是:

  • 稀疏:在每个向量中只传递一些梯度分布式神经网络多模态数据_神经网络分布式_33(假设其余的为0) - 使用整数索引对稀疏项进行编码;
  • 量化为单个bit:稀疏更新向量的每个元素取值分布式神经网络多模态数据_参数更新_34分布式神经网络多模态数据_分布式机器学习_35。该分布式神经网络多模态数据_分布式神经网络多模态数据_36值对于向量的所有元素是相同的,因此仅需要一个比特来区分两个选项;
  • 整数索引(用于标识稀疏数组中的项)可选地使用熵编码(entropy coding)进行压缩,以进一步减少更新大小(作者引用额外计算成本进一步降低3倍大小,但这种好处可能不值得额外成本);

此外,为了解释压缩方法有损的事实,原始更新向量分布式神经网络多模态数据_数据_19与压缩/量化的更新向量分布式神经网络多模态数据_分布式神经网络多模态数据_38之间的差被存储在每个执行器j上的所谓的残差向量分布式神经网络多模态数据_分布式神经网络多模态数据_39中,而不是简单地被丢弃。 将残差向量加到原始更新中:即我们在每个步骤中量化并发送分布式神经网络多模态数据_神经网络分布式_40的压缩版本,适当地更新分布式神经网络多模态数据_分布式神经网络多模态数据_39。 得到的效果是来自原始更新向量分布式神经网络多模态数据_分布式神经网络多模态数据_42,j的全部信息仅被延迟而不会丢失。 换句话说,大的更新(每个参数)以比小更新以更高的速率动态传输。

这里出现两个问题:(a)这对减少网络传输有多大帮助? (b)这如何影响准确性?答案比你想象的要少。

以Strom的论文中所报告的为例,1460万个参数:

Compression	               Update Size       Reduction
        None (32-bit floating point)	58.4 MB	           -
        16-bit floating point	        29.2 MB	       50%
        Quantized, \(\tau=2\)	        0.21 MB	       99.6%

可以使用更大的分布式神经网络多模态数据_分布式神经网络多模态数据_43值,并且导致更大的压缩(例如,分布式神经网络多模态数据_神经网络分布式_44时每个小批量的更新大小仅为4.5 KB!)但是随着分布式神经网络多模态数据_分布式神经网络多模态数据_43增加,模型精度明显受损。

结果令人印象深刻,这种方法似乎有三个主要缺点。

  • Strom报告说,在训练的早期阶段收敛会受到影响(在一个epoch的一小部分使用较少的计算节点似乎有帮助)
  • 压缩和量化不是无代价的:这些过程导致每个小批量的额外计算时间,以及每个执行器的少量内存开销
  • 该过程引入了两个额外的超参数:分布式神经网络多模态数据_分布式神经网络多模态数据_36的值以及是否对更新使用熵编码(尽管参数平均和异步SGD都引入了额外的超参数)

最后,(以作者的知识)没有异步SGD和分散异步SGD的任何实验比较。

分布式神经网络训练:哪种方法最好?

我们已经看到有多种方法来训练分布式神经网络,每种类型都有多种变体。 那么我们应该在实践中选择哪一个呢? 不幸的是,这个问题没有一个简单的答案。 首先,我们可以根据以下任何标准定义不同的方法:

  • 最快的训练速度(每秒最高训练样本数,或每个epoch最短时间)
  • 最大可达到的准确度为nepochs→∞
  • 给定数量的挂钟时间的最大可达精度
  • 给定数量的epoch可达到的最大精度

此外,这些问题的答案可能取决于许多因素,例如神经网络的类型和大小,群集硬件,压缩等功能的使用,以及训练方法的具体实施和配置。

分布式神经网络多模态数据_数据_47

也就是说,我们可以从研究中得出一些结论:
同步参数平均(或等效的,基于同步更新的)方法在每个epoch的准确度和总体可达到的准确度方面胜出,尤其是在小的平均更新周期时。 例如,参见[9]中的’hardsync’结果,或者N = 1平均周期的同步平均最接近单机训练的事实。 然而,额外的同步成本意味着这种方法每个epoch必然更慢; 也就是说,InfiniBand等快速网络互连可以在很大程度上保持同步方法的竞争力(参见示例[5])。 但是,即使在商用硬件上,我们也看到DL4J的同步参数平均实现在实践中具有良好的集群利用率。 添加压缩应该进一步有助于减少网络通信开销。