INTERSPEECH 2014 | 1-Bit Stochastic Gradient Descent and its Application to Data-Parallel Distribute

这篇文章以前也读过,不过读的不太仔细,论文中的一些细节并无注意到。最近为了写开题报告,又把这篇论文细读了一遍。据笔者了解,这篇论文应该是梯度量化领域的开山之做,首次使用了梯度量化技术来下降分布式神经网络训练的通讯开销。除此以外,这篇文章还提出了偏差补偿机制,这种机制能够缓解梯度量化的负面影响,下降信息丢失所带来的模型精度损失。算法

对于数据并行式训练来讲,最佳节点数量\(\hat{K}\)可以使得节点中计算和数据通讯彻底重叠,即同时使通讯和计算资源饱和:服务器

\[T_{calc}(\hat{K}) = T_{comm}(\hat{K}) \]

\(T_{calc}\)\(T_{comm}\)分别是节点上每一个minibatch所须要的计算和通讯时间。若是咱们将计算和通讯开销细分,就可以求出最优节点数量:网络

\[\hat{K} = \frac{\frac{N}{2} \cdot T_{calc}^{frm}+C\cdot T_{post}^{calc}}{\frac{1}{Z}\cdot T^{float}_{comm}-T_{upd}^{calc}} \]

符号 含义 与参数量\(M\)的关系
\(T_{calc}^{frm}\) 处理数据的时间,这部分是能够并行的 \(\propto\frac{M}{\text{FLOPS}}\)
\(T_{calc}^{post}\) 对梯度后处理的时间,如momentum + AdaGrad操做 \(\propto\frac{M}{\text{RAM bindwidth}}\)
\(T_{comm}^{float}\) 传输梯度(由单精度浮点数表示)的时间 \(\propto\frac{M}{\text{Network bindwidth}}\)
\(T_{calc}^{upd}\) 模型更新时间,相对于\(K\)来讲是固定的 \(\propto\frac{M}{\text{RAM bindwidth}}\)

为了实现更高的并行度,做者提出了双缓冲(double buffering)的概念,即在每一个节点上把一个minibatch分红两部分,在交换其中一部分的梯度时进行另外一部分的计算。然而,双缓冲机制会引入额外的更新开销,当通讯开销小于更新开销(即\(T_{comm}^{float} \lt T_{calc}^{upd}\))时,上述公式就再也不成立,双缓冲机制也就失去了做用。架构

本文的核心思想就是将32位单精度浮点数压缩成1位,从而下降训练过程的数据交换开销。为了进一步下降通讯开销,做者设定在节点间只进行梯度的交换,不进行模型参数的交换。为了下降量化偏差带来的负面影响,做者使用了偏差补偿技术:每次量化时,把上一次迭代的量化偏差加到本次迭代的梯度上,而后再进行量化,接着求出本次量化操做的偏差。这种偏差补偿机制能够确保全部的梯度都会再必定程度上对模型更新产生做用,只不过这种做用分散在不一样的迭代中——相似于一种延迟更新的形式。做者指出,使用偏差补偿后,就能够在几乎不损失模型精度的状况下将梯度由32位量化成1位。分布式

\[\begin{aligned} \tilde{g}_t &= Q(g_t + \text{Err}_{t-1})\\ \text{Err}_{t} &= g_t - Q^{-1}(\tilde{g}_t) \end{aligned} \]

在具体实现上,一种比较简单(且有效)的方法是将大于0的梯度值编码位1,小于等于0的梯度值编码为0。在反量化(解码)时,将1解码为+1,将0解码为-1,再进行聚合与更新操做。post

本文做者并无使用参数服务器架构,而是使用了一种相似于AllReduce的梯度聚合方法。每一个节点负责聚合\(1/K\)的模型参数子集。也就是说,假设模型参数量为\(M\),那么每一个节点都从其余全部节点接收到\(M\times \frac{K-1}{K^2}\)个值。这些值被反量化后,在节点上进行聚合以及后处理(AdaGrad、momentum),而后进行第二次量化,再把量化后的梯度传给其余全部的节点并进行更新操做。学习

根据公式能够看出,有3种方法能够提升并行性:(1)增长batchsize,(2)增大压缩比率Z,(3)下降更新开销\(T_{calc}^{upd}\)。前面已经介绍如何对梯度进行压缩,这里主要介绍方法1和方法3。
对于方法1,一味地增长batchsize并不可取,由于这可能致使模型不收敛。为了解决较大batchsize下模型不收敛的问题,做者使用了较小的学习率和AdaGrad优化算法。可是通常来讲,当batchsize增大时,学习率应该按照必定的比例进行放大[1, 2],多是由于模型不一样的缘由,做者使用较小的学习率能够得到不错的效果。设置全局学习率以后,AdaGrad每次经过全局学习率逐参数地除以历史梯度平方和的平方根,使得每一个参数的学习率不一样。AdaGrad的做用是在参数空间较为平缓的方向学习率会较大(由于平缓,因此累加梯度平方和较小,对应学习降低的幅度较小);参数空间较为陡峭的方向学习率会较小,从而加快训练速度。做者指出,咱们能够在三个不一样的时间点应用AdaGrad:量化以前在每一个节点上本地使用(可能会有助于量化,但也有可能在节点之间引入不一致的风险);聚合后的数据交换期间(有可能引发量化干扰);动量平滑以后(节省内存和更新开销,但因为平滑了峰值会下降了AdaGrad的效果)。经过实验验证,做者选择在梯度聚合后应用AdaGrad算法,(一个可能的)缘由是量化操做将异常值分散在多个minibatch种,这样它们对标准差估计的影响较小。优化

对于方法3,做者使用了模型并行来下降更新开销。不过在做者的实验中,模型并行的效果貌似并非很好,因此这里就再也不讨论了。编码

参考资料
[1] Goyal P, Dollár P, Girshick R, et al. Accurate, large minibatch sgd: Training imagenet in 1 hour[J]. arXiv preprint arXiv:1706.02677, 2017.
[2] Krizhevsky A. One weird trick for parallelizing convolutional neural networks[J]. arXiv preprint arXiv:1404.5997, 2014.spa

相关文章
相关标签/搜索