混合精度训练fp16用于神经网络训练和预测
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
混合精度训练fp16⽤于神经⽹络训练和预测
混合精度训练
混合精度训练是在尽可能减少精度损失的情况下利⽤半精度浮点数加速训练。
它使⽤FP16即半精度浮点数存储权重和梯度。
在减少占⽤内存的同时起到了加速训练的效果。
IEEE标准中的FP16格式如下:
取值范围是5.96× 10−8 ~ 65504,⽽FP32则是1.4×10-45 ~ 3.4×1038。
从FP16的范围可以看出,⽤FP16代替原FP32神经⽹络计算的最⼤问题就是精度损失。
float : 1个符号位、8个指数位和23个尾数位
利⽤fp16 代替 fp32
优点:
1)TensorRT的FP16与FP32相⽐能有接近⼀倍的速度提升,前提是GPU⽀持FP16(如最新的2070,2080,2080ti等)
2)减少显存。
缺点:
1)会造成溢出
因此,在⽇常使⽤过程中,常使⽤双混合精度训练。
如图:
此过程中的技术:
1) Loss scaling :会存在很多梯度在FP16表达范围外,我们为了让其落⼊半精度范围内,会给其进⾏等⽐放⼤后缩⼩。
流程:
对百度&英伟达相关论⽂的解读
⽂中提出了三种避免损失的⽅法:
1.1. 为每个权重保留⼀份FP32的副本
在前向和反向时使⽤FP16,整个过程变成:权重从FP32转成FP16进⾏前向计算,得到loss之后,⽤FP16计算梯度,再转成FP32更新到FP32的权重上。
这⾥注意得到的loss也是FP32,因为涉及到累加计算(参见下⽂)。
⽤FP32保存权重主要是为了避免溢出,FP16⽆法表⽰2e-24以下的值,⼀种是梯度的更新值太⼩,FP16直接变为了0;⼆是FP16表⽰权重的话,和梯度的计算结果也有可能变成0。
实验表明,⽤FP16保存权重会造成80%的精度损失。
1.2. Loss-scaling
得到FP32的loss后,放⼤并保存为FP16格式,进⾏反向传播,更新时转为FP32缩放回来。
下图可以看到,很多激活值⽐较⼩,⽆法⽤FP16表⽰。
因此在前向传播后对loss进⾏扩⼤(固定值或动态值),这样在反响传播时所有的值也都扩⼤了相同的倍数。
在更新FP32的权重之前unscale回去。
1.3. 改进算数⽅法:FP16 * FP16 + FP32。
经过实验,作者发现将FP16的矩阵相乘后和FP32的矩阵进⾏加法运算,写⼊内存时再转回FP16可以获得较好的精度。
英伟达V系列GPU卡中的Tensor Core(上图)也很⽀持这种操作。
因此,在进⾏⼤型累加时(batch-norm、softmax),为防⽌溢出都需要⽤FP32进⾏计算,且加法主要被内存带宽限制,对运算速度不敏感,因此不会降低训练速度。
另外,在进⾏Point-wise乘法时,受内存带宽限制。
由于算术精度不会影响这些运算的速度,⽤FP16或者FP32都可以。
2. 实验结果
从下图的Accuracy结果可以看到,混合精度基本没有精度损失:
Loss scale的效果:
3. 如何应⽤MP
Pytorch可以使⽤英伟达的开源框架,⽀持混合进度和分布式训练:
model, optimizer = amp.initialize(model, optimizer, opt_level="O1") with amp.scale_loss(loss, optimizer) as scaled_loss:
scaled_loss.backward()
Tensorflow就更简单了,已经有官⽅⽀持,只需要训练前加⼀句:export TF_ENABLE_AUTO_MIXED_PRECISION=1
# 或者
import os
os.environ['TF_ENABLE_AUTO_MIXED_PRECISION'] = '1'
参考:。