【yolov8目标检测部署】TensorRT int8量化

embedded/2024/10/19 13:20:33/

原作者github:https://github.com/xuanandsix/Tensorrt-int8-quantization-pipline/tree/main

改进:
源代码支持的TensorRT版本为7.许多属性已经弃用;
在原有的代码上将支持的TensorRT版本从7改到8.

!!不知道如何安装TensorRT?请参考:【通俗易懂】Windows系统安装TensorRT。
!!项目排坑请参考:【Debug】TensorRT报错汇总 欢迎大家补充。

一、简介

模型量化是深度学习领域中一种重要的模型优化技术,它主要涉及将模型中的浮点数(如FP32)转换为低比特的格式(如INT8)。这样做的目的是为了减少模型的存储大小和内存占用,同时加快模型的推理速度,尤其在硬件资源受限的设备上效果显著。

模型量化的方法:
1. 训练时量化也叫量化感知训练(Quantization-Aware-Training,QAT),在训练过程中模拟量化操作,使模型适应量化,减少量化误差。
2. 训练后量化(Post-Training Quantization,PTQ),PTQ不需要再训练,因此是一种轻量级的量化方法。在模型训练好后,再通过一个校准(Calibration)流程去计算比例因子,从而实现量化过程。
这里使用第二种方法简单且高效。

二、量化流程

2.1 TensorRT提供了四种IInt8Calibrator:

  • Int8EntropyCalibrator2:当前推荐的熵校准器,默认情况下校准发生在层融合之前,推荐用于CNN模型中。
  • IInt8MinMaxCalibrator:该校准器使用激活分布的整个范围来确定比例因子,默认情况下校准发生在层融合之前,推荐用于NLP任务的模型中。
  • IInt8EntropyCalibrator: 该校准器是TensorRT最原始的熵校准器,默认情况下校准发生在层融合之后,目前已不推荐使用。
  • IInt8LegacyCalibrator: 该校准器需要用户进行参数化,默认情况下校准发生在层融合之后,不推荐使用。

2.2 IInt8Calibrator需要实现的功能

  • getBatchSize:获取校准过程中的batchSize;
  • getBatch:获取校准过程中的输入;
  • writeCalibrationCache:由于校准花费的时间比较长,调用该函数将校准参数结果写入本地文件,方便下次直接读取。
  • readCalibrationCache:读取保存在本地的校准参数文件,在生成引擎过程中会自动调用。.

2.3 TensorRT构建INT8模型引擎时,会执行下面的步骤:

构建一个32位的模型引擎,然后在校准数据集上运行这个引擎,然后为每个张量激活值的分布记录一个直方图;
从直方图构建一个校准表,为每个张量计算出一个比例因子;
根据校准表和模型的定义构建一个INT8的引擎。
校准的过程可能会比较慢,不过第二步生成的校准表可以输出到文件并可以被重用,如果校准表文件已存在,那么校准器就直接从该文件中读取校准表而无需执行前面两步。另外,与引擎文件不同的是,校准表是可以跨平台使用的。因此,我们在实际部署模型过程中可以先在带通用GPU的计算机上生成校准表,然后在Jetson Nano等嵌入式平台上去使用。为了编码方便,我们可以用Python编程来实现INT8量化过程来生成校准表。
TensorRT流程(官方)

三、关键代码:

加载校准文件:quantization.py:

import numpy as np
import util_trt
import glob,os,cv2BATCH_SIZE = 4  # 批处理大小
BATCH = 100     # 校准批次
height = 640    # 输入高度
width = 640     # 输入宽度
CALIB_IMG_DIR = './calibration/'    # 校准图片路径
onnx_model_path = './weights/yolov8s.onnx'  # 待校准onnx模型路径def preprocess(img):img = cv2.resize(img, (height, width))img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)img = img.transpose((2, 0, 1)).astype(np.float32)img /= 255.0return imgclass DataLoader:def __init__(self):self.index = 0self.length = BATCHself.batch_size = BATCH_SIZE# self.img_list = [i.strip() for i in open('calib.txt').readlines()]self.img_list = glob.glob(os.path.join(CALIB_IMG_DIR, "*.jpg"))assert len(self.img_list) > self.batch_size * self.length, '{} must contains more than '.format(CALIB_IMG_DIR) + str(self.batch_size * self.length) + ' images to calib'print('found all {} images to calib.'.format(len(self.img_list)))self.calibration_data = np.zeros((self.batch_size,3,height,width), dtype=np.float32)def reset(self):self.index = 0def next_batch(self):if self.index < self.length:for i in range(self.batch_size):assert os.path.exists(self.img_list[i + self.index * self.batch_size]), 'not found!!'img = cv2.imread(self.img_list[i + self.index * self.batch_size])img = preprocess(img)self.calibration_data[i] = imgself.index += 1# example onlyreturn np.ascontiguousarray(self.calibration_data, dtype=np.float32)else:return np.array([])def __len__(self):return self.lengthdef main():# onnx2trtfp16_mode = Falseint8_mode = True print('*** onnx to tensorrt begin ***')# calibrationcalibration_stream = DataLoader()engine_model_path = "./weights/yolov8s_Int8.trt"calibration_table = 'best_calibration.cache'# fixed_engine,校准产生校准表engine_fixed = util_trt.get_engine(BATCH_SIZE, onnx_model_path, engine_model_path, fp16_mode=fp16_mode, int8_mode=int8_mode, calibration_stream=calibration_stream, calibration_table_path=calibration_table, save_engine=True)print(engine_fixed)assert engine_fixed, 'Brokenls engine_fixed'print('*** onnx to tensorrt completed ***\n')if __name__ == '__main__':main()

四、测试结果

model(640*640)infer_time(ms)/framesize
float32(trt)8.51.6M
int8(trt)2.14.3M

yolov8s模型FP32和INT8精度的目标检测结果分别如下面两张图片所示:

float32 tensorrtint8 tensorrt
请添加图片描述请添加图片描述

http://www.ppmy.cn/embedded/34821.html

相关文章

【Python深度学习(第二版)(2)】深度学习之前:机器学习简史

文章目录 一. 深度学习的起源1. 概率建模--机器学习分类器2. 早期神经网络--反向传播算法的转折3. 核方法 -- 忽略神经网络4. 决策树、随机森林和梯度提升机5. 神经网络替代svm与决策树 二. 深度学习与机器学习有何不同 可以这样说&#xff0c;当前工业界所使用的大部分机器学习…

开源15T tokens!HuggingFace放出规模最大、质量最高预训练数据集 | 最新快讯

新智元报道 编辑&#xff1a;LRS FineWeb 是一个高质量的预训练数据集&#xff0c;包含 15T 个 tokens&#xff0c;主要包含英语文本&#xff1b;消融实验证明了 FineWeb 数据集的质量要高于其他开源数据集&#xff1b;数据清洗脚本也已开源。 Meta 最近开源的 Llama 3 模型再次…

AUTOCRAWLER : A Progressive Understanding Web Agent for WebCrawler Generation

AUTOCRAWLER&#xff1a;用于生成 WebCrawler 的渐进式理解 Web 代理 Fudan University;Alibaba Holding-Aicheng Technology-Enterprise Abstract&#xff1a; 网络自动化是一项重要技术&#xff0c;它通过自动化常见的网络操作来完成复杂的网络任务&#xff0c;提高效率并…

Vue3组件通信全解析:利用props、emit、provide/inject跨层级传递数据,expose与ref实现父子组件方法调用

文章目录 一、父组件数据传递N个层级的子组件vue3 provide 与 injectA组件名称 app.vueB组件名称 provideB.vueC组件名称 provideCSetup.vue 二、使用v-model指令实现父子组件的双向绑定父组件名称 app.vue子组件名称 v-modelSetup.vue 三、父组件props向子组件传值子组件 prop…

最短路径(朴素)+堆排序+模拟堆

文章目录 Dijkstra求最短路 I堆排序模拟堆 Dijkstra求最短路 I 给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为正值。 请你求出 1 号点到 n 号点的最短距离&#xff0c;如果无法从 1 号点走到 n 号点&#xff0c;则输出 −1。 输…

synchronized底层加锁和释放锁的原理

新建Decompilation.java文件 public class Decompilation {private Object object new Object();public void insert(Thread thread) {synchronized (object) {}} }编译 javac Decompilation.java反编译获得字节码指令 javap -verbose Decompilation.classpublic void inse…

c#word文档:3.向Word文档中插入表格/4.读取Word文档中表格

--向Word文档中插入表格-- &#xff08;1&#xff09;在OfficeOperator项目的WordOperator类中定义向Word文档插入换页的函数NewPage &#xff08;2&#xff09;在WordOperator类中定义向Word文档插入表格的函数InsertTable using Microsoft.Office.Interop.Word;// 引入Mic…

android TV app适配遥控器思路,recycleview选中放大

背景&#xff1a; 当遥控器遥控盒子&#xff0c;app内是有一套机制&#xff0c;响应遥控器的操作&#xff0c; 需要做的就是&#xff1a; 1、activity中&#xff0c;普通view的处理&#xff1a; 直接监听该view的“setOnFocusChangeListener”方法&#xff0c;如下&#xff1…