标签:oss 图片 googl 跳过 google 就会 weight 溢出 解决
【GiantPandaCV导语】混合精度是一个非常简单并且实用的技术,由百度和谷歌联合发表于ICLR2018,可以让模型以半精度的方式训练模型,既能够降低显存占用,又可以保持精度。这篇文章不是最先提出使用更低精度来进行训练,但是其影响力比较深远,很多现在的方案都是基于这篇文章设计的。
提高网络模型的大小可以有效提升准确了,但是也增加了内存的压力和计算力的需求。本论文引入了半精度来训练深度神经网络,在不损失精度、不需要更改超参数的情况下,几乎可以减半内存占用。
权重、激活、梯度都是以IEEE半精度的方式存储的,由于半精度的表示范围要比单精度要小,本文提出了三种方法来防止关键信息的丢失。
大的模型往往需要更多的计算量、更多的内存资源来训练,如果想要降低使用的资源,可以通过降低精度的方法。通常情况下,一个程序运行速度的快慢主要取决于三个因素:
使用半精度减少了一半bit,可以影响算法带宽和内存带宽,好处有:
现在大部分深度学习训练系统使用单精度FP32的格式进行存储和训练。本文采用了IEEE的半精度格式(FP16)。但是由于FP16可以表示的范围要比FP32更为狭窄,所以引入了一些技术来规避模型的精度损失。
下面详细讲解第二节提到的三种技术。
在混合精度训练中,权重、激活、梯度都采用的是半精度存储的。为了匹配单精度网络的精度,在优化的整个过程中,需要拷贝一份单精度模型FP32作为主备份,而训练过程中使用的是FP16进行计算。
这样做的原因有两个:
第一:溢出错误:更新的时候是学习率乘以梯度,这个值可能非常小,超过半精度最小范围(\(2^{-24}\)),就会导致下溢出。如下图展示了梯度和FP16的表示范围,大约有5%的梯度已经下溢出,如果直接对半精度表示的模型更新,这样模型的精度肯定有所损失;而对单精度的模型进行更新,就就可以规避下溢出的问题。
下图展示的是激活值的范围和FP16表示范围之间的差异,50%以上的值都集中在不可表示的范围中,而右侧FP16可表示范围却空荡荡的,那么一个简单的想法就是向右平移,将激活平移到FP16可表示范围内。比如说可以将激活乘以8,这样可以平移3位,这样表示最低范围就从\(2^{-24}\)到了\(2^{-27}\), 因为激活值低于\(2^{-27}\)的部分对模型训练来说不重要,所以这样操作就可以达到FP32的精度。
那实际上是如何实现平移呢?很简单,就是在loss基础上乘以一个很大的系数loss scale, 那么由于链式法则,可以确保梯度更新的时候也采用相同的尺度进行缩放,最后在更新梯度之前再除以loss scale, 对FP32的单精度备份进行更新,就完成了。
还有一个问题,就是loss scale值的选取,最简单的方法就是选择一个固定值作为loss scale,可以训练一系列网络缩放因子的设置可以从8到32k。固定的放缩因子选取是需要一定经验的,如果梯度的数据可以获取,那就选取一个值可以让其梯度的值小于65504(FP16可以表示的最大值)。如果选取loss scale值过大,可能会上溢出,这种情况可以通过检查梯度来判断,如果发生溢出,跳过权重更新,进行下一次迭代。
在神经网络中的运算可以划分为三类:向量点乘(dot-products)、reduction和逐点操作。这三种操作在遇到半精度的时候,会有不同的处理方法。
为了保持模型精度,需要将向量点乘的部分乘积累加为FP32,然后再转换为FP16。如果直接用FP16会导致精度损失,不能达到和原来一样的精度。现在很多支持Tensor Cores的GPU中已经实现了这样的操作。
Reduction操作(比如求很多向量元素的和)需要先转为FP32, 这样的操作大部分出现在batch norm或者softmax层中。这两个层都是从内存中读写FP16的向量,执行运算的时候要使用FP32格式。
逐点操作,如非线性和元素间矩阵乘法,内存占用有限,运算精度不影响这些操作的速度。
在分类任务(ILSVRC/ImageNet)、检测任务(VOC2007)、语音识别(English-Mandarin)、机器翻译(English-Frech)、语言模型(1 billion word)、DCGAN这几个任务进行了实验,这篇解读仅展示分类任务和检测任务的结果。
实验的时候每个任务都会设置一个两个对比试验
分类任务上选择了AlexNet、Vgg-D、GoogLeNet、Inceptionv2、Inceptionv3 和 预激活ResNet50几个模型进行测试,主要满足以下条件:
可以看到Mixed Precision方法能够和Baseline方法差不多准确率,有时候甚至会略高于Baseline。
在训练以上网络的时候,不需要使用Loss Scale方法,因为这些方法前向传播和反向传播的值都在FP16范围内。
这里选择了Faster RCNN和Multibox-SSD两种方法在VOC2007数据集上进行训练,两个方法都是用来VGG-16作为骨干网络。模型和训练脚本都来自于开源库。
可以看到,如果使用Mixed Precision方法,在训练Multibox SSD的时候可能会由于下溢出导致模型不收敛,但是当使用了Loss Scale技术以后,就可以正常收敛,达到与Baseline相同的结果。
Mixed Precision混合精度是处于一个非常简单的想法,使用低精度的表示可以节约显存、内存同时增加处理器的吞吐量。虽然有以上的种种好处,直接使用半精度会出现一定的问题,比如:下溢出、精度损失等。所以这篇论文核心就是解决使用半精度过程中出现的问题,提出了三个方法达到了非常理想的效果。如果你使用的是有Tensor Core的GPU,那就非常推荐使用混合精度来训练,只需要安装NVIDIA提供的Apex库,然后在你的PyTorch or TensorFlow代码中加几行代码就可以实现。
https://arxiv.org/pdf/1710.03740v3
https://zhuanlan.zhihu.com/p/163493798
https://zhuanlan.zhihu.com/p/79887894
【论文阅读】Mixed Precision Training
标签:oss 图片 googl 跳过 google 就会 weight 溢出 解决
原文地址:https://www.cnblogs.com/pprp/p/14165542.html