以下内容主要来自于Pytorch官网Pytorch量化,特此记录学习过程。(其实更像直接翻译了一下,逃~
Pytorch 量化概览
1、什么是量化?
量化是一种近来深度学习加速中快速发展的技术,它指的是以比浮点精度更低的比特宽度来执行计算并存储 Tensors 的技术。
一个量化的模型便采用的是 整数 来对 Tensors 执行部分或全部操作。
2、量化的意义?
因为量化精度低,则它使得在许多硬件平台上可以使用更加压缩的模型和高性能的矢量化操作。
Pytorch支持 INT8
量化,与典型的FP32模型相比,模型大小减少了4倍,内存带宽需求减少了4倍。对INT8计算的硬件支持通常比FP32计算快2到4倍。
3、Pytorch 量化简介
上面说到 Pytorch 支持 INT8
量化,而 Pytorch 支持多种量化方式。
一般情况下,模型以浮点精度 FP32 进行训练,然后在量化转化为 INT8。
此外,PyTorch 还支持量化感知训练,该训练使用伪量化模块对前向和后向过程中的量化误差进行建模。
在较低的层次上,PyTorch 提供了一种表示量化 Tensors 并对其执行操作的方法。它们可以用来直接构造模型,以较低的精度执行全部或部分计算。
如今,Pytorch 支持如下平台的量化:
- x86 CPUs with AVX2 support or higher (without AVX2 some operations have inefficient implementations)
- ARM CPUs (typically found in mobile/embedded devices)
特别注意Pytorch当前版本(1.3)不能在CUDA上进行量化,只可以在CPU上进行量化,以后的版本可能就可在CUDA上量化了。
4、量化张量
PyTorch支持每个张量和每个通道的非对称线性量化。
每个张量意味着所有张量内的值都以相同的方式缩放。
每个通道意味着对于每个维度,通常是一个张量的通道维度,张量中的值被一个不同的值缩放和偏移(实际上缩放和偏移变成了矢量)。这使得把张量转换成量化值的误差更小。
使用公式来进行浮点Tensors的量化:
Q
(
x
,
s
c
a
l
e
,
z
e
r
o
_
p
o
i
n
t
)
=
r
o
u
n
d
(
x
s
c
a
l
e
+
z
e
r
o
_
p
o
i
n
t
)
Q(x, scale, zero\_point) = round(\frac{x}{scale} + zero\_point)
Q(x,scale,zero_point)=round(scalex+zero_point)
为了在PyTorch中实现量化,我们需要能够用张量表示量化数据。量化张量允许存储量化数据(表示为int8/uint8/int32)以及诸如scale和zero_point之类的量化参数。量化张量允许许多有用的操作,使量化算术变得容易,此外还允许以量化格式序列化数据。
5、算子范围
量化张量支持正则全精度张量数据处理方法的有限子集。对于Pytorch中包含的NN算子,支持限制为:
- 8 bit weights (data_type = qint8)
- 8 bit activations (data_type = quint8)
注意,算子实现目前仅支持卷积层和线性算子的权值的各信道量化。此外,输入数据的最小值和最大值被线性映射到量化数据类型的最小值和最大值,使得零表示没有量化误差。
而量化是在 torch.nn.quantized
中提供。
具体操作
PyTorch提供了三种量化模型的方法:
- 训练后动态量化:这是最简单的量化形式,其中权重提前量化,但激活值在推理过程中动态量化。这用于模型执行时间由从内存加载权重而不是计算矩阵乘法所支配的情况。这适用于批量较小的LSTM。对整个模型应用动态量化只需调用
torch.quantization.quantization_dynamic()
。 - 训练后静态量化:这是最常用的量化形式,其中权重提前量化,激活张量的比例因子和偏差是根据在校准过程中观察模型的行为预先计算的。当CNNs是一个典型的用例时,训练后量化通常是在内存带宽和计算节省都很重要的情况下进行的。进行训练后量化的一般过程是:
- 准备模型:a.通过添加quantstbub和dequantstbub模块来指定激活的量化和非量化位置。b.确保模块不重复使用。c.将任何需要重新量化的操作转换为模块
- 将conv+relu或conv+batchnorm+relu等操作融合在一起,以提高模型精度和性能。
- 指定量化方法的配置,例如选择对称或非对称量化以及MinMax或L2Norm校准技术。
- 使用
torch.quantization.prepare()
插入在校准期间观察激活张量的模块。 - 通过对校准数据集运行推断来校准模型。
- 最后,使用
torch.quantization.convert()
方法转换模型本身。这可以做几件事:量化权重,计算并存储每个激活张量要使用的scale和bias,并替换键运算符量化的实现。