模型量化是一种将浮点计算转成低比特定点计算的技术,可以有效的降低模型计算强度、参数大小和内存消耗,但往往带来巨大的精度损失。尤其是在极低比特(<4bit)、二值网络(1bit)、甚至将梯度进行量化时,带来的精度挑战更大。
模型量化是由模型、量化两个词组成。我们要准确理解模型量化,要看这两个词分别是什么意思。
在计算机视觉、深度学习的语境下,模型特指卷积神经网络,用于提取图像/视频视觉特征。
量化是指将信号的连续取值近似为有限多个离散值的过程。可理解成一种信息压缩的方法。在计算机系统上考虑这个概念,一般用“低比特”来表示。也有人称量化为“定点化”,但是严格来讲所表示的范围是缩小的。定点化特指scale为2的幂次的线性量化,是一种更加实用的量化方法。
卷积神经网络具有很好的精度,甚至在一些任务上比如人脸识别、图像分类,已经超越了人类精度。但其缺点也比较明显,具有较大的参数量,计算量,以及内存占用。而模型量化可以缓解现有卷积神经网络参数量大、计算量大、内存占用多等问题,具有为神经网络压缩参数、提升速度、降低内存占用等“潜在”优势。为什么“潜在”是加引号的呢?因为想同时达到这三个特性并不容易,在实际应用过程中存在诸多限制和前提条件。
另外,由于模型量化是一种近似算法方法,精度损失是一个严峻的问题,大部分的研究都在关注这一问题。
模型量化在最初的定义里是为了压缩模型参数,比如韩松在ICLR2016上获得best paper的论文,首次提出了参数量化方法。其使用k-mean聚类,让相近的数值聚类到同一个聚类中心,复用同一个数值,从而达到用更少的数值表示更多的数,这是量化操作的一种方案。反过来,从量化数变到原始数的过程,称之为反量化,反量化操作完之后,模型就可以按照原来的方式进行正常的计算。
我们认为绝大部分的模型量化算法都能压缩参数,因此压缩参数的实用性不存在问题。
量化是否一定能加速计算?回答是否定的,许多量化算法都无法带来实质性加速。
引入一个概念:理论计算峰值。在高性能计算领域,这概念一般被定义为:单位时钟周期内能完成的计算个数 乘上 芯片频率。
什么样的量化方法可以带来潜在、可落地的速度提升呢?我们总结需要满足两个条件:
1、量化数值的计算在部署硬件上的峰值性能更高 。
2、量化算法引入的额外计算(overhead)少 。
要准确理解上述条件,需要有一定的高性能计算基础知识,限于篇幅就不展开讨论了。现直接给出如下结论:已知提速概率较大的量化方法主要有如下三类,
**1、二值化,**其可以用简单的位运算来同时计算大量的数。对比从nvdia gpu到x86平台,1bit计算分别有5到128倍的理论性能提升。且其只会引入一个额外的量化操作,该操作可以享受到SIMD(单指令多数据流)的加速收益。
**2、线性量化,**又可细分为非对称,对称和ristretto几种。在nvdia gpu,x86和arm平台上,均支持8bit的计算,效率提升从1倍到16倍不等,其中tensor core甚至支持4bit计算,这也是非常有潜力的方向。由于线性量化引入的额外量化/反量化计算都是标准的向量操作,也可以使用SIMD进行加速,带来的额外计算耗时不大。
**3、对数量化,**一个比较特殊的量化方法。可以想象一下,两个同底的幂指数进行相乘,那么等价于其指数相加,降低了计算强度。同时加法也被转变为索引计算。但没有看到有在三大平台上实现对数量化的加速库,可能其实现的加速效果不明显。只有一些专用芯片上使用了对数量化。
简单看一下二值化和线性量化两种方式,分别是右上角的图和右下角的图。
总结一下,要使用量化技术来提升模型运行速度,需要满足两个条件:
1、选择适合部署的量化方案。
2、在部署平台上使用经过深度优化的量化计算库(必要的时候,可能需要撸起袖子自己上)。
首先保证你实现的低比特计算效率超过原先浮点计算,否则为何要承担精度损失的风险而使用并不加速的量化模型呢。但低比特计算效率超过浮点计算其实并不容易,因为大家在浮点的计算库上已经做了非常多细致的优化比如winograd,间接卷积等等。
为了最大限度保证实用性,后面的论文所有工作都是基于二值化、线性量化两种前提来做的,并且绝大部分工作都报告最终实际的加速效果。这也是链接与编译团队做研究的一个风格。
模型量化还有一个潜在的好处是降低运行时内存占用,这个特性无论是在移动端还是云端都是具有现实意义的。如果降低内存占用,可以得到如下好处:
1、降低访存量,存在提升速度的可能 。
2、在同样硬件环境下,同时处理更多视频或者视频路数 。
3、训练更大的模型。
我们分析下运行时内存都是被什么东西占用的,大家关心的参数weight只占很少一部分, 大部分内存占用来自激活值activation。如果你做低比特量化只关注卷积的话(很多论文其实也是只量化了卷积),那么是无法带来内存占用降低的。
如何才能用量化降低内存占用,只有一个方式: 将尽可能多的layer的激活值都进行量化 。在这个方向上之前商汤的一位实习生李润东也有一个工作,做了除了卷积之外更多层的量化。但是这样做会带来更多的精度损失,这可能也是大家需要关心的。
生产一个量化模型的有以下几种方法,借鉴了ICCV2019上一篇data-free量化论文的定义。
L1:直接将一个浮点参数直接转化成量化数,一般会带来很大的精度损失,但使用上非常简单。
L2:基于数据校准的方案,很多芯片都会提供这样的功能,比如tensorRT,高通,寒武纪等。它需要转模型的时候提供一些真实的计算数据。
L3:基于训练finetune的方案,有很多论文都是使用这种方法,它的好处是可以带来更大的精度提升,缺点是需要修改训练代码,实施周期比较长。
上图描述了一种实用的pipeline流程,一般会优先使用不进行finetune的offline方法,也就是离线方案。当离线方案精度损失过于严重,我们才会进行基于finetune的方法,来做进一步的抢救。
一种特别而有趣的技术是量化,它将网络内部的浮点数替换为整数。
有两种基本表示形式:整数和浮点数。
整数以基数2的数字系统表示。根据所使用的位数,整数可以占用几种不同的大小。最重要的是
-
int8 or short (ranges from -128 to 127),
-
uint8 (ranges from 0 to 255),
-
int16 or long (ranges from -32768 to 32767),
-
uint16 (ranges from 0 to 65535).
如果要表示实数,则必须放弃完美的精度。举个例子,数字1/3可以十进制形式写为0.33333…,具有无限多个数字,这些数字无法在内存中表示。为了解决这个问题,引入了浮点数。
本质上,浮点数是数字形式的科学记数法
最常以2为基数,但也可以是10。 (出于我们的目的,这无关紧要,但是我们假设它是2。)
与整数相似,有不同类型的浮点数。最常用的是
half或float16(1位符号,5位指数,10位有效数,所以总共16位),
单或float32(1位符号,8位指数,23位有效值,所以总共32位),
double或float64(1位符号,11位指数,52位有效值,所以总共64位)。
如果您尝试以科学格式将两个数字相加并相乘,您会发现浮点算术比整数算术要复杂得多。实际上,每次计算的速度很大程度上取决于实际的硬件。例如,台式机中的现代CPU的浮点运算速度与整数运算速度一样快。另一方面,GPU更针对单精度浮点计算进行了优化。 (因为这是计算机图形学中最普遍的类型。)
并不是完全精确,可以说使用int8通常比float32更快。但是,默认情况下将float32用于神经网络的训练和推理。 (如果您之前曾训练过网络并且未指定参数和输入的类型,则很可能是float32。)
那么,如何将网络从float32转换为int8?
这个想法原则上非常简单。 (实际上并没有那么多,我们将在后面看到。)假设您有一个输出在[-a,a)范围内的层,其中a是任何实数。
首先,我们将输出缩放到[-128,128),然后简单地舍入。也就是说,我们使用转换
To give a concrete example, let’s consider the calculation below.
The range of the values here is in (-1, 1), so if we quantize the matrix and the input, we get
在这里,我们看到结果不是int8。由于将两个8位整数相乘是一个16位整数,因此我们可以通过转换对结果进行反量化
to obtain the result
如您所见,这与我们最初的情况不完全相同。这是预料之中的,因为量化只是一个近似值,在此过程中我们会丢失信息。但是,有时这是可以接受的。稍后,我们将看到模型性能如何受到影响。
如果您想尝试这些技术,则不必从头开始。最完善的工具之一是TensorFlow Lite的模型优化工具包。它包含了尽可能缩小模型的方法。
You can find the documentation and an introductory article below.
https://www.tensorflow.org/lite/performance/model_optimization
https://medium.com/tensorflow/introducing-the-model-optimization-toolkit-for-tensorflow-254aca1ba0a3
PyTorch还支持多种量化工作流程。尽管目前已将其标记为实验性功能,但功能齐全。 (但是,请注意API会一直更改,直到它处于实验状态。)
https://pytorch.org/blog/introduction-to-quantization-on-pytorch/
-
weight的8 bit量化 :data_type = qint8,数据范围为[-128, 127]
-
activation的8 bit量化:data_type = quint8,数据范围为[0, 255]
bias一般是不进行量化操作的,仍然保持float32的数据类型,还有一个需要提前说明的,weight在浮点模型训练收敛之后一般就已经固定住了,所以根据原始数据就可以直接量化,然而activation会因为每次输入数据的不同,导致数据范围每次都是不同的,所以针对这个问题,在量化过程中专门会有一个校准过程,即提前准备一个小的校准数据集,在测试这个校准数据集的时候会记录每一次的activation的数据范围,然后根据记录值确定一个固定的范围。
-
1.Post Training Dynamic Quantization:这是最简单的一种量化方法,Post Training指的是在浮点模型训练收敛之后进行量化操作,其中weight被提前量化,而activation在前向推理过程中被动态量化,即每次都要根据实际运算的浮点数据范围每一层计算一次scale和zero_point,然后进行量化;
-
2.Post Training Static Quantization:第一种不是很常见,一般说的Post Training Quantization指的其实是这种静态的方法,而且这种方法是最常用的,其中weight跟上述一样也是被提前量化好的,然后activation也会基于之前校准过程中记录下的固定的scale和zero_point进行量化,整个过程不存在量化参数(scale和zero_point)的再计算;
-
3.Quantization Aware Training:对于一些模型在浮点训练+量化过程中精度损失比较严重的情况,就需要进行量化感知训练,即在训练过程中模拟量化过程,数据虽然都是表示为float32,但实际的值的间隔却会受到量化参数的限制。
-
至于为什么不在一开始训练的时候就模拟量化操作是因为8bit精度不够容易导致模型无法收敛,甚至直接使用16bit进行from scrach的量化训练都极其容易导致无法收敛,不过目前已经有了一些tricks去缓解这个问题,但不在本文讨论之列。
以最常用的Post Training (Static) Quantization为例:
**1.准备模型:**准备一个训练收敛了的浮点模型,用QuantStub和DeQuantstub模块指定需要进行量化的位置;
**2. 模块融合:**将一些相邻模块进行融合以提高计算效率,比如conv+relu或者conv+batch normalization+relu,最常提到的BN融合指的是conv+bn通过计算公式将bn的参数融入到weight中,并生成一个bias;
**3. 确定量化方案:**这一步需要指定量化的后端(qnnpack/fbgemm/None),量化的方法(per-layer/per-channel,对称/非对称),activation校准的策略(最大最小/移动平均/L2Norm(这个不太清楚,是类似TensorRT的校准方式吗???));
-
activation校准:利用torch.quantization.prepare()
利用torch.quantization.prepare() 插入将在校准期间观察激活张量的模块,然后将校准数据集灌入模型,利用校准策略得到每层activation的scale和zero_point并存储;
**5. 模型转换:**使用 torch.quantization.convert()函数对整个模型进行量化的转换。 这其中包括:它量化权重,计算并存储要在每个激活张量中使用的scale和zero_point,替换关键运算符的量化实现;
https://zhuanlan.zhihu.com/p/132561405模型量化是一种将浮点计算转成低比特定点计算的技术,可以有效的降低模型计算强度、参数大小和内存消耗,但往往带来巨大的精度损失。尤其是在极低比特(<4bit)、二值网络(1bit)、甚至将梯度进行量化时,带来的精度挑战更大。Part 1 量化综述什么是模型量化?为什么要进行模型量化?模型量化是由模型、量化两个词组成。我们要准确理解模型量化,要看这两个词分别是什么意思。在计算机视觉、深度学习的语境下,模型特指卷积神经网络,
模型
的weights数据一般是float32的,
量化
即将他们转换为int8的。当然其实
量化
有很多种,主流是int8/fp16
量化
,其他的还有比如
二进制神经网络:在运行时具有二进制权重和激活的神经网络,以及在训练时计算参数的梯度。
三元权重网络:权重约束为+1,0和-1的神经网络
XNOR网络:过滤器和卷积层的输入是二进制的。 XNOR 网络主要使用二进制运算来近似卷积。现在很多框架或者工具比如nvidia的TensorRT,xilinx的DNNDK,TensorFlow,PyTorch
yolov5 的
模型
量化
,好好看看export.py
写的很清楚了,
step1:pip install -r requirements.txt coremltools onnx onnx-simplifier onnxruntime-gpu openvino-dev tensorflow # GPU
step2:
python export.py --weights weights/yolov5x6.pt --include onnx torchscript engine
遇到报错:
TensorRT:
模型
量化
是由
模型
、
量化
两个词组成。我们要准确理解
模型
量化
,要看这两个词分别是什么意思。
在计算机视觉、深度学习的语境下,
模型
特指卷积神经网络,用于提取图像/视频视觉特征。
量化
是指将信号的连续取值近似为有限多个离散值的过程。可理解成一种信息压缩的方法。在计算机系统上考虑这个概念,一般用“低比特”来表示。也有人称
量化
为“定点化”,但是严格来讲所表示的范围是缩小的。定点化特指scale为2的幂次的线性
量化
,是一种更加实用的
量化
方法。
.........
在使用Pytorch编写
模型
时,为了验证检查代码是否正确,需要查看
模型
每一层的输出shape或是
模型
结构。
然而在Pytorch只能够直接查看
模型
的结构,无法简单、直观地查看每一层的输出大小,需要自行手动计算,并且在输入shape改变时,每一层的输出同样随之变化,需要重复计算。
因此,这里建议使用一个工具,torchsummary...
ONNX
模型
量化
是指将已经训练好的ONNX
模型
进行压缩和优化,以降低
模型
的存储空间和计算资源需求,同时保持
模型
的精度和性能。
量化
可以通过减少浮点数的位数来实现,例如将浮点数转换为整数或低精度浮点数。
根据引用,可以使用基于Python的TensorRT库进行ONNX
模型
量化
。TensorRT是英伟达推出的用于高性能深度学习推理的库,它支持使用INT8
量化
技术对ONNX
模型
进行压缩和加速。
具体步骤如下:
1. 下载并解压缩ONNX
模型
文件。
2. 使用TensorRT的
量化
工具,将ONNX
模型
转换为INT8
量化
格式。
3. 保存
量化
后的ONNX
模型
。
引用中提供了一个使用PaddlePaddle框架和Paddle2ONNX工具进行ONNX
模型
量化
的示例。在示例中,先下载并解压缩MobileNetV1
模型
文件,然后使用Paddle2ONNX工具将
模型
转换为ONNX格式,并指定opset_version为12,最后实现动态
量化
。
综上所述,ONNX
模型
量化
是通过压缩和优化已经训练好的ONNX
模型
,以降低存储空间和计算资源需求的技术。可以使用TensorRT等库和工具来实现ONNX
模型
的
量化
。<span class="em">1</span><span class="em">2</span><span class="em">3</span>
#### 引用[.reference_title]
- *1* [ONNX的
模型
优化与
量化
细节](https://blog.csdn.net/sunny0660/article/details/120405998)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"]
- *2* [基于python的tensorrt int8
量化
yolov5 onnx
模型
实现](https://download.csdn.net/download/weixin_42848583/85041103)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"]
- *3* [
模型
量化
(3):ONNX
模型
的静态
量化
和动态
量化
](https://blog.csdn.net/m0_63642362/article/details/124741589)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"]
[ .reference_list ]