混合精度Mixed Precision Training

神经网络的参数是用浮点精度表示的, 浮点精度的标准是IEEE 754 - Wikipedia,以下是一个FP16数值在内存中存储格式。

随着神经网络模型规模越来越大,如何减少模型占用的内存并且缩短训练时间成为亟需解决的问题,混合精度训练就是其中之一的解决方案,并且几乎不会影响模型训练的效果。

混合精度原理

想象一下,如果模型参数+loss+gradient都是用fp16保存的,fp16的最小值是 <math xmlns="http://www.w3.org/1998/Math/MathML"> 6.1 × 1 0 − 5 6.1\times 10^{-5} </math>6.1×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...

相关推荐
鬼先生_sir2 小时前
RabbitMQ 全面解析(完整版)
分布式·rabbitmq
Francek Chen5 小时前
【大数据存储与管理】分布式数据库HBase:06 HBase编程实践
大数据·数据库·hadoop·分布式·hbase
柒.梧.6 小时前
Redis架构演进:从主从到Cluster,读懂高可用与分布式核心
redis·分布式·架构
渔民小镇6 小时前
不用前端也能测试 —— 模拟客户端请求模块详解
java·服务器·前端·分布式·游戏
星辰_mya7 小时前
雪花算法:分布式世界的“身份证号”
分布式
AIminminHu8 小时前
OpenGL渲染与几何内核那点事-项目实践理论补充(一-2-(3)-当你的协同CAD服务器面临“千人同屏”时:从单机优化到分布式高并发)
运维·服务器·分布式
真上帝的左手9 小时前
12. 消息队列-RabbitMQ-高可用核心机制
分布式·rabbitmq·java-rabbitmq·mq
枫叶v.10 小时前
Kafka 怎么保证消息的顺序性
分布式·kafka
yitian_hm12 小时前
深入理解 Kafka Producer 核心源码:消息发送全链路解析
分布式·kafka·linq
Dylan~~~1 天前
深度解析Cassandra:分布式数据库的王者之路
数据库·分布式