混合精度训练

减少所需显存。减少了IO.

  • 深度学习训练使用16bit表示/运算正逐渐成为主流。
  • 低精度带来了性能、功耗优势,但需要解决量化误差(溢出、舍入)。
  • 常见的避免量化误差的方法:为权重保持高精度(fp32)备份;损失放大,避免梯度的下溢出;一些特殊层(如BatchNorm)仍使用fp32运算。



“仅仅在权重更新的时候使用fp32,耗时的前向和后向运算都使用fp16”。在反向计算开始前,将dloss乘上一个scale,人为变大;权重更新前,除去scale,恢复正常值。目的是为了减小激活gradient下溢出的风险。

动态loss_scale:

基本思想是先选择一个较大的loss_scale初始值,如果梯度发生溢出(grads中有Inf或NaN)则跳过本次更新,并将loss_scale减小;如果没有发生溢出,则正常进行梯度更新,若连续N次迭代中梯度没有Inf或NaN,将loss_scale值增大。

混合精度训练过程如下:

  1. 使用FP16的输入;

  2. 前向计算:该场景中使用统一的FP32格式的初始化权重,训练时恢复checkpoint中的变量进行训练;将恢复的FP32参数转化为FP16供给前向运算;

  3. Loss计算:该场景中loss计算复杂,涉及到许多exp, log等可能会发生FP16溢出的不稳定操作,因此loss计算在FP32精度下进行;

  4. loss scale:将计算出来的loss乘以一个比例因子 scaled_loss = loss * loss_scale;

  5. 反向计算:grads = tf.gradients(scaled_loss , params,aggregation_method=aggmeth)

  6. 梯度计算完成后再将各梯度缩小相应的倍数:unscaled_grads = [(grad * (1. / loss_scale)) for grad in grads];

  7. 梯度规约:累加很多FP16数值容易造成数据溢出,选择在FP32下规约;

  8. 参数更新:根据梯度是否溢出选择是否进行参数更新并动态调整 loss_scale,若更新,直接在FP32精度的参数上进行参数更新。由于该场景中就是使用PF32的参数,更新时直接应用于该参数即可。

https://blog.csdn.net/qq_35209694/article/details/108541032

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容