【GiantPandaCV导语】混合精度是一个非常简单并且实用的技术,由百度和谷歌联合发表于ICLR2018,可以让模型以半精度的方式训练模型,既能够降低显存占用,又可以保持精度。这篇文章不是最先提出使用更低精度来进行训练,但是其影响力比较深远,很多现在的方案都是基于这篇文章设计的。
1. 摘要
提高网络模型的大小可以有效提升准确了,但是也增加了内存的压力和计算力的需求。本论文引入了半精度来训练深度神经网络,在不损失精度、不需要更改超参数的情况下,几乎可以减半内存占用。
权重、激活、梯度都是以IEEE半精度的方式存储的,由于半精度的表示范围要比单精度要小,本文提出了三种方法来防止关键信息的丢失。
- 推荐维护一个单精度版本的权重weights,用于累积梯度。
- 提出使用Loss scale来保证小的梯度值不会下溢出。
- 在加载到内存之前,就将模型转化到半精度来进行加速。
2. 介绍
大的模型往往需要更多的计算量、更多的内存资源来训练,如果想要降低使用的资源,可以通过降低精度的方法。通常情况下,一个程序运行速度的快慢主要取决于三个因素:
- 算法带宽
- 内存带宽
- 时延
使用半精度减少了一半bit,可以影响算法带宽和内存带宽,好处有:
- 由于是用更少的bit代替,占用空间会减小差不多一半
- 对于处理器来说也是一个好消息,使用半精度可以提高处理器吞吐量;在当时的GPU上,半精度的吞吐量可以达到单精度的2-8倍。
现在大部分深度学习训练系统使用单精度FP32的格式进行存储和训练。本文采用了IEEE的半精度格式(FP16)。但是由于FP16可以表示的范围要比FP32更为狭窄,所以引入了一些技术来规避模型的精度损失。
- 保留一份FP32的主备份。
- 使用loss scale来避免梯度过小。
- FP16计算但是用FP32进行累加。
3. 实现
下面详细讲解第二节提到的三种技术。
3.1 FP32的主备份
在混合精度训练中,权重、激活、梯度都采用的是半精度存储的。为了匹配单精度网络的精度,在优化的整个过程中,需要拷贝一份单精度模型FP32作为主备份,而训练过程中使用的是FP16进行计算。
这样做的原因有两个:
第一:溢出错误:更新的时候是学习率乘以梯度,这个值可能非常小,超过半精度最小范围(