模型剪枝:
具体实现就是排序,把排在前面的存进权重,后面的不要了。然后对比裁剪前后的权重在同一数据集上的精度。判断裁剪是否过度。排序的准则并不限于l1范数,裁剪的比例也是人为调试。
l1范数裁剪:比如说layer1,对所有通道的卷积核的l1范数进行排序,认为l1范数大的卷积核更重要,也就是对layer1的输出影响更大。排在后面的卷积核不太重要,也就是冗余的,可以裁去。
张量分解(模型剪枝的更近一步)
由于原始网络参数中存在大量的冗余,除了剪枝的方法以外,我们还可以利用SVD分解和PQ分解等方法,将原始张量分解为低秩的若干张量,以减少卷积的计算量,提升前向速度。
BN层合并(模型剪枝的更近一步)
将BN层合并到卷积层
只有conv层后面接bn层才可以合并
https://www.jianshu.com/p/e042d693f3fb/
模型蒸馏:
所谓的蒸馏,指的是从大模型(通常称为teacher model)中学习小模型(通常称为student model)
训练的时候需要teacher model的网络结构,student model的网络结构。损失函数分为两个部分,student model的结果与gt的结果间的损失,student model的结果与teacher model的结果间的损失
https://blog.csdn.net/u013596454/article/details/120529820
模型量化:
将模型降低到fp16或者int8
有很多量化工具可以支持
训练后量化PTQ:我们导出ONNX模型,转换为TensorRT的过程中可以使用trt提供的Calibration方法去校准,这个使用起来比较简单。可以直接使用trt官方提供的trtexec命令去实现,也可以使用trt提供的python或者C++的API接口去量化,比较容易。但是这其中是一个黑盒子,无法控制tensorrt如何做量化
训练中量化QAT:TensorRT有直接加载QAT模型的能力。QAT模型这里是指包含QDQ操作的量化模型。QDQ模块会参与训练,负责将输入的FP32张量量化为INT8,随后再进行反量化将INT8的张量在变为FP32。实际网络中训练使用的精度还是FP32,只不过这个量化算子在训练中可以学习到量化和反量化的尺度信息,这样训练的时候就可以让模型权重和量化参数更好地适应量化这个过程(当然,scale参数也是可以学习的),量化后的精度也相对更高一些。
什么是QDQ呢,QDQ就是Q(量化)和DQ(反量化)两个op,在网络中通常作为模拟量化的op。作用是储存量化信息还有当做是显式指定哪一层是量化层。
有了QDQ信息,TensorRT在解析模型的时候会根据QDQ的位置找到(我们给予提示的)可量化的op,然后与QDQ融合(吸收尺度信息到OP中)。
相关代码库:
https://github.com/NVIDIA/TensorRT/tree/master/tools/onnx-graphsurgeon 可以对onnx结果进行修改
https://github.com/openppl-public/ppq 商汤的量化框架
https://github.com/onnx/onnx-tensorrt 可以对tensorrt进行修改
https://github.com/NVIDIA/TensorRT tensorrt代码库
https://mmcv.readthedocs.io/zh_CN/latest/deployment/onnxruntime_custom_ops.html
https://github.com/NVIDIA/TensorRT/tree/main/tools/pytorch-quantization tensorrt官方量化工具库