[论文总结]:Mixed Precision Training 混合精度训练 百度和英伟达联合发表 ICLR 2018

论文:Mixed Precision Training(混合精度训练)

作者:百度和nvidia联合发表

来源:

论文链接:https://arxiv.org/abs/1710.03740

github链接:无

1论文概述

深度学习模型的计算任务分为训练和推理训练往往是放在云端或者超算集群中,利用GPU强大的浮点计算能力,来完成网络模型参数的学习过程。 一般来说训练时,计算资源往往非常充足,基本上受限于显存资源、多节点扩展、通讯效率的问题。相对于训练过程,推理往往被应用于终端设备,如手机,计算资源、功耗都收到严格的限制,为了解决这样的问题,提出了很多不同的方法来减少模型的大小(即模型压缩)以及所需的计算资源、存储资源。模型压缩除了剪枝以外,还有一个方法就是降低模型参数的数值精度。 随着网络深度的加大,带来的参数数量也呈现指数级增长,如何将最终学习好的网络模型塞入到终端设备有限的空间中是目前很多性能优良的网络真正应用到日常生活中的一大阻碍。

本文主要讨论如何降低模型训练时的数值精度来加速训练过程。现在的模型训练过程基本上使用单精度和双精度,如果网络模型很大,那么受限于显存空间(最新的Volta100是16G),batch size就会非常小。batch size太小容易导致网络学习过程不稳定,影响模型的精度,详细的关于batch size对网络模型训练的影响分析会在其他文章中介绍。

Nvidia的Pascal和Volta系列显卡除了支持标准的单精度计算外,也支持了低精度的计算,比如最新的Tesla V100硬件支持了FP16的计算加速,P4和P40支持INT8的计算加速,而且低精度计算的峰值要远高于单精浮点的计算峰值。

为了加速训练过程以及减少显存开销Baidu Research和Nvidia在这篇论文中合作提出了一种FP16和FP32混合精度训练的方法,并且在CNN分类和检测、语音识别和语言模型任务上进行了验证,实验过程中使用的GPU就是Tesla V100(目前这么不是民用卡,太贵了)。

训练过程中每层的权重都存成FP32格式(Master-Weights),每次训练时都会将FP32的权重降精度至FP16( a master copy),前向输出和后向梯度都使用FP16进行计算,更新时将FP16的梯度累加到FP32的Master-Weight上。

2 Half Precision Format

半精度(也被称为FP16)对比高精度的FP32与FP64降低了神经网络的显存占用,使得我们可以训练部署更大的网络,并且FP16在数据转换时比FP32或者FP64更节省时间。
单精度(也被称为32-bit)是通用的浮点数格式(在C扩展语言中表示为float),64-bit被称为双精度(double)。

IEEE 754标准定义了如下16bit半精度浮点数格式:
1个符号(sign)bit,5个指数(exponent)bit,10个小数(fractional)bit。

指数范围在[-14,15]间(两个指数值,从0到31,保留用于特殊情况)。一个隐藏的1bit作为正则化值,正如IEEE浮点数格式定义的那样。

半精度格式有如下动态范围与精度:
正则化(归一化)值(Normalizedvalues)
2 − 14 2^{-14} 214 2 15 2^{15} 215,11bits有效位。

非正则化(归一化)值(Denormalvalues)
2 − 14 2^{-14} 214 2 − 15 2^{-15} 215,随着指数值变小,有效位数减少。指数在[-24,-15]范围内k的有效精度范围是(25-k)bit。

一些例子量级:
最大归一化值(Maximumnormalized) 65504
最小归一化值(Minimumnormalized) 2 − 14 = ∼ 6.10 e − 5 2^{-14}=\sim 6.10e-5 214=6.10e5
最小非归一化值(Minimundenormal) 2 − 14 = ∼ 5.96 e − 8 2^{-14}=\sim 5.96e-8 214=5.96e8
半精度包括非归一化动态范围,为2的40次幂。对比来看,单精度包括非归一化动态范围为2的264次幂。

2 混合精度的解释

采用FP16的优势
  • 减少所需的内存使用量。半精度浮点格式(FP16)使用16位,而单精度(FP32)则为32位。降低所需的内存可以训练更大的模型。
  • 缩短训练和推理时间
为什么需要FP32

为什么要用混合精度,而不是直接改成FP16呢?这要从神经网络中的通用矩阵乘法运算说起。

深度学习模型中包含各种层,比如全连接层、卷积层、循环层等等,其中每一层都能用通用矩阵乘法(GEMM)运算来实现。在训练过程中,GEMM占据了大部分计算。

如下图所示,GEMM可以分个成几个乘法运算,在加上加法运算。

当使用FP16表示神经网络中的数时,GEMM运算的输入矩阵由16 bit的数字构成,我们需要能执行16 bit计算来做乘法的硬件,同时还需要用32 bit计算和存储来做加法。没有32 bit来完成加法运算,训练大型深度神经网络就会非常困难。

于是,研究员们对训练流程进行了一些修改。模型中的输入、权重、梯度和激活以FP16表示。

但只是简单地更改存储格式,有些模型无法达到与FP32基准相同的准确率。

  • 有些梯度太小,在FP16就变成0,大约有5%的数据被忽略成0(感觉不是很合理,毕竟2^-24太小了影响不大)
  • 有些数太大,即使在FP16下可以表示,当加法右移操作使它二进制点对齐时,仍然可能变为0

由于FP16所能表示的subnormal最小正数是 2 − 24 2^{−24} 224。也就是说指数位小于-24的数使用FP16表示时都会变成0。在一个普通话识别的模型训练中,有将近5%的权重梯度的指数位小于-24,如果更新时也用FP16计算,那么这些数在乘以学习率后都将变成0,从而对最终模型效果产生负面影响,使用混合精度训练的方式可以避免这种问题。

为了解决这个挑战,控制精度损失,百度和英伟达联手提出了两项技术。

  • 维护一个FP32格式的权重的主副本
  • 损失缩放(loss-scaling)

百度这篇文章主要是利用cuda中原生支持的fp16数据类型,也就是所谓的半精度,nvidia的GPU其实在很早的架构就提供了这个精度的数值表示,只是没有提供专门的硬件计算单元。fp16占用的空间是单精度的一半,双精度的1/4。在此之前,其实也有很多做模型量化研究的文章,但是或多或少都会影响模型最终的训练精度,所以并不使用。百度和nvidia的这次合作解决了这个问题,即降低了模型训练的显存占用,也保证了模型最终的精度。由于使用到更大的batch size模型最终学习的到参数泛化能力更强,个别网络甚至于获得更高的精度.混合精度的概念就是针对使用fp16进行模型的训练过程,同时保证和fp32同样的精度所提出的,也可以认为是使用到trick。 后面会了解到,nvidia为了加速训练过程,在最新的架构中还增加了特殊的fp16矩阵运算单元。

3 控制半精度的信息损失的方法

accumulating FP16 products into FP32

NVIDIA Volta GPU架构引入了Tensor Core指令,它将半精度矩阵相乘,将结果累加到单精度或半精度输出中。我们发现,累积到单一精度对于获得良好的训练结果至关重要。在写入存储器之前,累计值将转换为半精度。cuDNN和CUBLAS库提供了各种依赖Tensor Cores进行算术运算的函数。

FP32 Master Copy of Weights

保存一个单精度浮点的权值备份。在训练过程中舍入到半精度,FP16在硬件实现中更快。(加速训练、减少硬件开销、存储的参数量增加了50%,但是由于减少了过程中的activation,所以总体来说还是减少了memory的消耗)。
假如单纯的使用FP16训练,精度降低了80%,所以要使用32位量化训练,但是参数更新过程使用16位。

意思是使用fp16进行训练,同时有一份fp32的参数主副本用于参数更新。那么实现上其实就很简单,只需要在每次迭代之前,将每个layer或者op的参数输入都确保是从fp32拉取到的,然后转换成fp16输入;而最后将计算得到梯度,则是更新到fp32的主副本上面,直到模型收敛。这样做的好处在于可以避免两种情况下的溢出,第一次就是当梯度特别小,超出fp16表达范围后,就变成了0,进而导致参数无法学习。另外一种情况就是梯度特别大,同样超出fp16可表达的最大值,那么更新后进一步导致参数不正确。而如果将更新到fp32的主副本,那么更新采用fp32,即使再小的梯度,也能够表示。

Loss scaling

引入了损失缩放(loss-scaling)技术,损失缩放能恢复一些小的重要梯度,对恢复某些模型的准确率损失来说很有必要。

在训练期间,一些权重梯度指数很小,在FP16格式下会变成0。在一些网络中(比如SSD),梯度大部分都在FP16的表示范围之外。为了解决这个问题,需要将梯度平移到FP16的表示范围内,平移实际上就是对梯度值乘以一个系数(等于2^n,n为平移的位数),研究团队在反向传播开始时引入一个换算系数,来缩放损失,后向传导时,梯度也通过链式法则同时逐渐扩大,都会被乘以相同的scale,并能在FP16中表示出来。权重更新时需要将移位后的梯度除以scale后,再更新到权重上。

这个操作原理是借助求导的连式法则,通过放大loss,进而放大整个反向传播过程的参数梯度,最后在更新时候再缩放回来。这个参数可以固定,也可以根据网络的学习的状态自适应的进行调整。 对于scale的选择,论文没有统一的方法,只是提到scale并没有下界,只要选择的scale不会在后向计算时导致溢出就行。

论文中提到他们在实验过程中使用的scale是8-32K,最终取得了与FP32一致的收敛结果。

BN处理
其实在实现前面两个之后我们会发现有些操作还是没法正常训练,因为一些中间结果超出了FP32所表达的范围,那么针对这样的操作,我们则需要单独进 行处理,直接使用FP32的参数,将计算过程强制使用FP32。

以上是论文所提到的两个主要trick, 来避免由于梯度过大或者过小导致的信息丢失而影响精度。另外还对单纯使用fp16进行模型训练,分析了个别网络无法学习或者出现模型精度下降的原因。

请注意,并非所有网络都需要使用所有这些技术进行训练。

总结:训练步骤

上面介绍的三种技术可以组合成每个训练迭代的以下步骤序列。对传统迭代过程的补充以粗体显示。

  • 制作权重的FP16副本
  • 使用FP16权重和激活向前传播
  • 将得到的损失乘以比例因子S
  • 使用FP16权重,激活和它们的渐变向后传播
  • 将权重梯度乘以1/S
  • 可选择处理权重梯度(梯度削减,权重衰减等)
  • 更新FP32中的权重主副本

有关如何将混合精确训练步骤添加到各种DNN训练框架的脚本的示例,可以参阅“ 使用混合精度用户训练指南”。

实验结果

实验过程很完善,在ILSVRC、Detection CNN、Speech Recognition、Machine Translation、Language Modeling、DCGAN都做了实验。

语音识别 Speech Recongnition

百度在DeepSpeech 2模型上对论文方法进行了测试。对英语和汉语数据集进行语音数据的混合精度训练,进行语音识别。在使用同样模型架构和超参数的情况下,混合精度模型在英语和普通话数据集上,都达到了与FP32模型同样的准确率

图像分类

英伟达在博客上还介绍了混合精度训练在图像分类、对象检测等任务上的性能。

如上图所示,混合精度训练的各种深度神经网络模型在图像分类上,不需要损失缩放就能达到与单精度训练差不多的准确率。

物体检测 Detection CNNs

而在对象检测任务上,混合精度训练实现的准确率甚至略高于FP32基准。

机器翻译 Machine Trainslation

对于语言翻译,我们在英语到法语翻译(Google)的TensorFlow教程中训练了该模型的几个变体。该模型使用单词词汇表英语和法语分别为100K和40K条目。我们训练的网络在编码器和解码器中各有3到5层。在这两种情况下,一个层由1024个LSTM单元组成。使用SGD优化器对WMT15数据集进行训练。在相同的设置下,不同的训练session的准确性有明显的差异。例如,请参见图4中的三条fp32曲线,其中显示了三层模型。有损失缩放的混合精度和fp32对比结果,无损失缩放导致结果略有下降。5层模型具有相同的训练行为。

语言模型

我们在10亿字的数据集上训练了英语语言模型,命名为bigLSTM(Jozefowicz等人,2016年)。该模型由两层8192 LSTM单元组成,投影到1024维embedding。该模型使用adagrad优化器对50个epoch进行了训练,词汇量为793K个单词。在训练过程中,我们使用一个带有8K负样本的SoftMax层。为了使fp32的复杂度训练与fp16相匹配,这个网络需要进行损失缩放,如图5所示。与baseline(FP32)相比较,在没有损失缩放下,经过300k迭代后,fp16训练的训练复杂度曲线与fp32训练相比出现发散,scale因子为128的恢复了所有相关的梯度值和fp16训练的精度。

参考

资料下载

混合精度训练官方PPT

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值