fp16是指采用2字节(16位)进行编码存储的一种数据类型;
fp32是指采用4字节(32位);
fp16和fp32相比对训练的优化:
- 1.内存占用减少:应用fp16内存占用比原来更小,可以设置更大的batch_size
- 2.加速计算:加速计算只在最近的一些新gpu中,这一块我还没有体验到好处...有论文指出fp16训练速度可以是fp32的2-8倍
数据类型 | 取值范围 |
float16 | -65504 ~ 65504 |
float32 | -2^31 ~ 2^31-1 |
int8 | -2^7 ~ 2^7-1 (-128 ~ 127) |
uint8 | 0 ~ 2^8-1 (0~255) |
1.量化目的
在开发机器学习应用程序时,有效利用服务器端和设备上的计算资源非常重要。为了支持在服务器和边缘设备上更高效的部署,对模型量化的支持将变的更加重要。
量化利用8位整数(int8)指令来减小模型大小并更快地运行推断(减少延迟),并且可以是实现服务质量目标或甚至适合移动设备上可用资源的模型之间的差异。即使在资源不太受限的情况下,它也可以使您部署更大、更准确的模型。
量化主要是一种加快推理速度的技术,并且只支持量化运算符的前向传递。在深度学习中,量化指的是使用更少的bit来存储原本以浮点数存储的tensor,以及使用更少的bit来完成原本以浮点数完成的计算。
2.量化简介
量化主要是一种加速推理的技术,量化运算符仅支持前向传递。量化是指使用精度较低的数据进行计算和内存访问的技术,与浮点实现相比,通常是int8。
可以在几个重要领域实现性能提升:
模型尺寸缩小 4 倍;
内存带宽减少 2-4 倍;
由于内存带宽的节省和使用int8算法更快计算,推理速度提高了2-4倍。
然而,量化并非没有额外代价。从根本上说,量化意味着引入近似值,由此产生的网络精度略低。这些技术试图最小化完整浮点精度和量化精度之间的差距。
3.量化方式
3.1 Dynamic Quantization - 动态量化
PyTorch支持的最简单的量化方法称为动态量化。这不仅涉及将权重转换为int8,而且还涉及在执行计算之前将激活转换为int 8(因此为“动态”)。因此,将使用高效的int8矩阵乘法和卷积实现来执行计算,从而实现更快的计算。然而,激活是以浮点格式读取和写入内存的。
3.2 Post-Training Static Quantization - 训练后静态量化
通过将网络转换为同时使用整数算术和int8内存访问,可以进一步提高性能(延迟)。静态量化执行额外的步骤,首先通过网络输入数据批,并计算不同激活的结果分布。该信息用于确定不同的激活应该在推断时量化的具体程度。重要的是,这一附加步骤允许我们在操作之间传递量化值,而不是在每个操作之间将这些值转换为浮点值,然后再转换为整数,从而大大加快了速度。
3.3 Quantization Aware Training - 量化感知训练
量化感知训练(QAT)是这三种方法中精度最高的一种。使用QAT,所有权重和激活在训练的前向和后向过程中都是“伪量化”的:也就是说,浮点值被舍入为模拟int8值,但所有计算仍然使用浮点数字完成。因此,训练期间的所有权重调整都是在“感知到”模型最终将被量化这一事实的情况下进行的;因此,在量化之后,该方法通常比其他两种方法产生更高的精度。
4.PTQ 和 QAT 简介
依据是否要对量化后的参数进行调整可将量化方法分为量化感知训练(QAT)和训练后量化(PTQ)。 这两种方法的操作区别如下图所示(图左为QAT,图右为PTQ):
量化感知训练 QAT 是将训练过的模型量化后又再进行重训练。由于定点数值无法用于反向梯度计算,实际操作过程是在某些op前插入伪量化节点(fake quantization nodes), 用于在训练时获取流经该op的数据的截断值,便于在部署量化模型时对节点进行量化时使用。我们需要在训练中通过不断优化精度来获取最佳的量化参数。由于它需要对模型进行训练, 对操作人员技术要求较高。
训练后量化 PTQ 是使用一批校准数据对训练好的模型进行校准, 将训练过的FP32网络直接转换为定点计算的网络,过程中无需对原始模型进行任何训练。只对几个超参数调整就可完成量化过程, 且过程简单快速, 无需训练, 因此此方法已被广泛应用于大量的端侧和云侧部署场景。
模型类型 | 首选方案 | 为什么 |
LSTM/RNN | 动态量化 | 吞吐量由权重的计算/内存带宽决定 |
BERT/Transformer | 动态量化 | 吞吐量由权重的计算/内存带宽决定 |
CNN | 静态量化 | 吞吐量受激活的内存带宽限制 |
CNN | 量化感知训练 | 在静态量化无法达到精度的情况下 |