DGC包括:动量校正、局部梯度剪切、动量因子掩蔽和热身训练。
目录
一、梯度稀疏化 Gradient sparsification
二、改善局部梯度积累 improving the local gradient accumulation
一、梯度稀疏化 Gradient sparsification
只发送重要的梯度(稀疏更新)来减少通信带宽:只有大于阈值的梯度被传输。为了避免丢失信息,我们在局部累积其余的梯度。最终,这些梯度变得足够大,可以被传播。因此,我们会立即发送较大的梯度,但最终会随着时间的推移发送所有的梯度.
其中,x为数据集,N为处理的批次数量,大小为b,权值参数更新的式子如上右所示。在经过T次迭代之后,则权证更新公式变为了:
局部梯度积累可以看作是将批处理大小从Nb增加到NbT,其中T是发送w (i)梯度的两次迭代之间的稀疏更新间隔的长度。
二、改善局部梯度积累 improving the local gradient accumulation
当稀疏度极高时,稀疏更新将极大地损害收敛性。
1.动量修正 momentum correction
这儿使用了vanilla SGD+momentum:
m是动量因子,Ut是速度,N是训练节点数,旁边的
旁边的式子则是对第一项进行vanilla SGD。
这个式子我上一篇博客中有提到:【SGD深入理解】vanilia SGD&momentum SGD这样做的会给梯度下降增加一个“惯性”,使之很快的收敛。
经过T iteration后,权值更新公式为:
从上面的式子中,我们可以清晰地看到1~T的iteration内的梯度都被积累(中括号里面的一坨)。
PS:此时我们需要注意到中括号里的一坨中节点对应的梯度都和一个相乘求和
上面说过,这个m就是动量因子,给整个梯度下降加上“重量”或者是“惯性”。而这个式子叫做discounting factor。
但不能将添加了momentum的vanilla SGD直接运用到稀疏化后的梯度里面,故需要设置如下:
这儿表示再K节点上的局部梯度更新,一旦Vk,t的结果大于某个阈值则会通过
被网络发送,参与权值参数更新(项三)。
故我们得到稀疏梯度更新之后的式子:
而此时,发现式子与前面的原本的式子丢失了
这会导致原本收敛性较差的稀疏梯度收敛性能变得更差。
故需要在下式子上做出修正:
将ut视为“梯度”,那么原始momentum+vanilla的第二项(
)可以看作是“梯度”ut的vanilla SGD.(PS:相当于将加了动量的速度表示变成了梯度,而真正的梯度成为加了动量的速度表示再进行vanilla SGD)
前两项为修正后的局部梯度积累,积累结果Vk,t用于后续的稀疏化和通信.
动量修正个人总结:一句话,加了momentum 的vanilla SGD解决不了梯度稀疏化后带来的收敛性低下问题,故通过将速度公式替换成“梯度”来累计,最后再将累积的梯度进行vanilla SGD。(希望看到的小伙伴能指出错误)
三、梯度裁剪
因为我们在每个节点上独立地通过迭代累积梯度,所以我们在将当前的梯度Gt添加到之前的累积中之前,在局部执行梯度裁剪。
当前节点视为梯度乘以系数进行规范化:
四、动量因子遮蔽
由于小梯度被积累到后面才进行迭代,故是被延迟更新的。其会减慢模型的收敛速度并削弱模型的表现。引入动量因子遮蔽来减轻陈旧梯度的影响。这个掩模阻止了延迟梯度的动量,阻止了陈旧的动量向错误的方向训练权重。
在上面公式中,对高于原始梯度的Vk,t 和Uk,t进行Mask,而我们回到前面动量修正部分会发现:Uk,t作为速度表示被看成“梯度”,Vk,t则是对“梯度Uk,t”的一个积累,而后面的第三项是对梯度“Uk,t”进行一个普通的SGD操作。
那进行Mask操作的目的就不言而喻了:为了减少“陈旧”的积累梯度对于当前梯度的误导性,而对其速度表示和积累同时进行屏蔽,这个掩模阻止了延迟梯度的动量,阻止了陈旧的动量向错误的方向训练权重。
五、热身训练
稀疏梯度限制了模型的变化范围,从而延长了网络显著变化的时间。与此同时,早期剩余的梯度在下一次更新之前累积,因此它们可能超过最新的梯度,误导优化方向。故加入热身训练,在进行warm-up训练时,使用较小的学习率来减慢模型最开始的更新速度并减少有效梯度的稀疏化。在最开始的几个epoch中,将梯度稀疏化率由一个较小的值通过指数化增长到最终值。
本人理解:梯度稀疏性越大,模型的迭代和收敛越慢。故在开始训练前选择一个较小的学习率并且让阈值过滤后积累的梯度越小(传递梯度的稀疏性越小)进行热身训练,来保证以后训练时积累的梯度不会影响最新的梯度。