神经网络的参数是用浮点精度表示的, 浮点精度的标准是IEEE 754 – Wikipedia,以下是一个FP16数值在内存中存储格式。
跟着神经网络模型规划越来越大,怎么削减模型占用的内存而且缩短练习时刻成为亟需处理的问题,混合精度练习便是其中之一的处理方案,而且简直不会影响模型练习的作用。
混合精度原理
幻想一下,如果模型参数+loss+gradient都是用fp16保存的,fp16的最小值是6.110−56.1\times 10^{-5},小于最小值的gradient都会变成0,相当于浪费了一次梯度传达。或许小的gradient并没有很重要,可是堆集屡次就会变得不行疏忽。当时大模型普遍较低的学习率也会加重这个问题的影响。
因此为了处理这个问题,就需求用更高精度fp32保存一份参数,在正常前向推理和反向传达时都用fp16,核算好得梯度先转换为fp32,再乘以学习率,然后更新到fp32存储得参数上,最终将fp32参数转换成fp16更新模型参数。
整个流程如下如:
这种用fp16和fp32共同练习模型得技术就叫做混合精度练习(MP, Mixed-Precision training),明显MP并不能节省模型加载需求的内存,由于需求多存储一份fp16的参数和梯度,可是用fp16进行模型前向和后向核算,可以削减中心核算值存储需求的内存,这部分内存会跟着sequence length和batch size增大而增大,所以只要在这部分中心值占用内存比重较高时才干带来一定的内存节省。
虽然核算时刻的影响不大,可是fp16练习时刻的确会大大削减,通常是削减1.5~5.5倍。
更多资料:
fastai – Mixed precision training
Understanding Mixed Precision Training | by Jonathan Davis | Towards Data Science
Loss Scale
是不是混合精度练习就完全没有梯度丢掉了呢,并不是,在反向传达过程中其实已经有部分梯度由于精度原因丢掉了(由于正常模型梯度都不会太大,所以我们首要考虑下溢出)。那么怎么处理这部分问题呢,就要用到Loss Scale。
原理是将Loss乘以一个比较大的数scale,由于Loss是用fp32存储的,所以scale的选值范围是比较大的。这样由于反向传达链式法则原理,梯度也会扩大很多倍,原本下溢出的值也会保存下来。然后在梯度转换成fp32后除以scale,最后更新就与正常混合精度练习共同了。
流程如下:
一般在开端练习时scale会设定成一个比较大的值,如果核算过程中fp16梯度产生上溢出,会跳过当时步的参数更新,并将scale下调。练习log中会输出如下音讯:
⚠️ Gradient overflow. Skipping step, loss scaler 0 reducing loss scale to…