问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深度学习模型剪枝、量化和TensorRT推理

创作时间:
作者:
@小白创作中心

深度学习模型剪枝、量化和TensorRT推理

引用
CSDN
1.
https://blog.csdn.net/linghu8812/article/details/109585506

深度学习模型的优化是提升模型效率和性能的关键步骤。本文将详细介绍模型剪枝和量化两种优化方法,并介绍如何使用TensorRT进行高效的模型推理。

模型剪枝算法

模型剪枝是一种通过删除神经网络中冗余或不重要的部分来减小模型大小和计算复杂度的技术。以下是几种常见的模型剪枝算法:

预定义网络结构剪枝

剪枝方法
参考文献
github
剪枝原理
L1-norm based Filter Pruning
Pruning Filters for Efficient ConvNets
l1-norm-pruning
在每一个卷积层,根据卷积核的权重值的L1 norm大小,修剪掉相应百分比的通道数。
ThiNet
ThiNet: A Filter Level Pruning Method for Deep Neural Network Compression
剪枝时,不根据当前层进行剪枝,而是修剪去对下一卷积层激活值影响最小的权重值。
Regression based Feature Reconstruction
Channel Pruning for Accelerating Very Deep Neural Networks
根据LASSO回归算法选出有代表性的卷积层通道,减枝去掉冗余通道,使用最小二乘法重建剩余通道。

自动网络结构剪枝

剪枝方法
参考文献
github
剪枝原理
Network Slimming
(1) Learning Efficient ConvNets through Network Slimming(2) SlimYOLOv3: Narrower, Faster and Better for Real-Time UAV Applications
在剪枝时,对BN层的gamma参数进行惩罚进行稀疏训练,剪枝时选择稀疏训练后BN层gamma值较大的参数进行保留
Sparse Structure Selection
Data-Driven Sparse Structure Selection for Deep Neural Networks
除了对通道进行稀疏训练,还可以对残差模块进行稀疏训练。

稀疏训练代码示例:

def updateBN():
    for m in model.modules():
        if isinstance(m, nn.BatchNorm2d):
            m.weight.grad.data.add_(args.s*torch.sign(m.weight.data))

需要注意的是,在剪枝时对残差模块通道的剪枝策略需要考虑,方案有不剪枝(减去的参数较少)或者根据残差模块的某一层进行剪枝,也有对所有残差通道的mask进行或运算。剪枝后的效果如下图所示,在剪枝时必须保证shortcut连接的两个卷积层通道数相等。另外,使用network slimming算法时,每个卷积层都必须剩下至少1个通道。

TensorRT int8量化算法

TensorRT是一个高性能的深度学习推理引擎,支持int8量化以进一步提升模型的推理速度和降低内存需求。

量化概述

  • 目标:将fp32的卷积神经网络转换为int8而不会造成明显的精度损失;
  • 原因:int8方法具有更高的吞吐量和更低的内存需求;
  • 挑战:int8的精度和动态范围明显低于fp32;
类型
动态范围
最小精度
fp32
-3.4 x 1038~ +3.4 x 1038
1.4 x 10-45
fp16
-65504 ~ +65504
5.96 x 10-8
int8
-128 ~ +127
1
  • 解决方案:在将训练的模型权重量化为int8时以及在int8计算激活时,最大限度地减少信息损失;
  • 结果:在TensorRT中实现了int8方法,并且不需要任何额外的fine tune或重训练。
  • 问题:为什么要量化而不使用int8直接训练?模型训练是需要反向传播和梯度下降的,训练时的超参一般都是浮点型,如学习率等,int8类型无法进行训练。

线性量化

公式:
Tensor Values = fp32 scale factor * int8 array

根据量化公式仅需求fp32 scale factor即可进行int8量化,那么如何求fp32 scale factor?

从上图中可以看出,有两种int8量化方法,一种是非饱和映射(左),另一种是饱和映射(右)。经过验证,非饱和映射会造成严重的准确率损失,原因是由于卷积层计算的正负分布很不均匀,如果按照对称非饱和映射(原意是为了尽可能多地保留原信息)的话,那么+max那边有一块区域就浪费了,也就是说scale到int8后,int8的动态范围就更小了,举个极限的例子就是量化后正的样本没有,负的全部扎堆在一个很小的值附近,这样会造成严重的精度损失。饱和映射方法是先找一个阈值T,将低于最低阈值的值全部都饱和映射到-127上,如右上图的左边的三个红色的点。

如何选择量化阈值?

  1. 标定步骤:
  • 在标定数据集上进行fp32推理。
  • 对每一个卷积层:
  • 收集激活的直方图;
  • 生成具有不同饱和阈值的量化分布;
  • 选择使KL发散最小化的阈值。
  • 一般来说,整个标定过程需要几分钟的时间
  1. 标定数据集选择:
  • 有代表性
  • 多样化
  • 理想情况下是验证数据集的子集
  • 1000+样例

深度学习模型转TensorRT

  1. 深度学习模型PyTorch训练并转ONNX与TensorRT部署
  2. darknet YOLOv4模型转ONNX转TensorRT部署
  3. yolov5 PyTorch模型转TensorRT
  4. CenterFace模型转TensorRT
  5. RetinaFace MXNet模型转ONNX转TensorRT
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号