OpenVINO 2022.3实战四:POT API 实现 YOLOv5 模型 INT8 量化

news/2024/4/20 10:34:06/文章来源:https://blog.csdn.net/shanglianlm/article/details/130882650

OpenVINO 2022.3实战四:POT API 实现 YOLOv5 模型 INT8 量化

将预训练的 YOLOv5m Pytorch 模型转换为 OpenVINO™ FP32 Intermediate Representation (IR) 模型。下一步,通过 OpenVINO™ Post-Training Optimization Tool (POT) API 来定义客制化DataLoader和Metric,从而复用 YOLOv5 客制化的前后处理(letterbox,Non-maximum Suppression)及精度计算等模块。采用 “DefaultQuantization” 的量化算法,定义和运行量化流水线对FP32模型进行 INT8 量化。

1 准备需要量化的模型

下载yolov5代码 ultralytics/yolov5

python export.py --weights yolov5s.pt --include torchscript onnx openvino

导出模型为 yolov5s_openvino_model
在这里插入图片描述

2 定义数据加载

继承来自 openvino.tools.pot.api 的 DataLoader类, 创建 YOLOv5DataLoader Class:定义数据和annotation加载和预处理;

class YOLOv5DataLoader(DataLoader):""" Inherit from DataLoader function and implement for YOLOv5."""def __init__(self, config):if not isinstance(config, Dict):config = Dict(config)super().__init__(config)self._data_source = config.data_sourceself._imgsz = config.imgszself._batch_size = 1self._stride = 32self._single_cls = config.single_clsself._pad = 0.5self._rect = Falseself._workers = 1self._data_loader = self._init_dataloader()self._data_iter = iter(self._data_loader)def __len__(self):return len(self._data_loader.dataset)def _init_dataloader(self):dataloader = create_dataloader(self._data_source['val'], imgsz=self._imgsz, batch_size=self._batch_size, stride=self._stride,single_cls=self._single_cls, pad=self._pad, rect=self._rect, workers=self._workers)[0]return dataloaderdef __getitem__(self, item):try:batch_data = next(self._data_iter)except StopIteration:self._data_iter = iter(self._data_loader)batch_data = next(self._data_iter)im, target, path, shape = batch_dataim = im.float()im /= 255nb, _, height, width = im.shapeimg = im.cpu().detach().numpy()target = target.cpu().detach().numpy()annotation = dict()annotation['image_path'] = pathannotation['target'] = targetannotation['batch_size'] = nbannotation['shape'] = shapeannotation['width'] = widthannotation['height'] = heightannotation['img'] = imgreturn (item, annotation), img

3 精度验证功能

继承来自 openvino.tools.pot.api 的 Metric 类, 创建 COCOMetric Class:定义模型后处理及精度计算方法;

class COCOMetric(Metric):""" Inherit from DataLoader function and implement for YOLOv5."""def __init__(self, config):super().__init__()self._metric_dict = {"AP@0.5": [], "AP@0.5:0.95": []}self._names = (*self._metric_dict,)self._stats = []self._last_stats = []self._conf_thres = config.conf_thresself._iou_thres = config.iou_thresself._single_cls = config.single_clsself._nc = config.ncself._class_names = {idx:name for idx,name in enumerate(config.names)}self._device = config.device@propertydef value(self):""" Returns metric value for the last model output.Both use AP@0.5 and AP@0.5:0.95"""mp, mr, map50, map = self._process_stats(self._last_stats)return {self._names[0]: [map50], self._names[1]: [map]}@propertydef avg_value(self):""" Returns metric value for all model outputs.Both use AP@0.5 and AP@0.5:0.95"""mp, mr, map50, map = self._process_stats(self._stats)return {self._names[0]: map50, self._names[1]: map}def _process_stats(self, stats):mp, mr, map50, map = 0.0, 0.0, 0.0, 0.0stats = [np.concatenate(x, 0) for x in zip(*stats)]if len(stats) and stats[0].any():tp, fp, p, r, f1, ap, ap_class = ap_per_class(*stats, plot=False, save_dir=None, names=self._class_names)ap50, ap = ap[:, 0], ap.mean(1)mp, mr, map50, map = p.mean(), r.mean(), ap50.mean(), ap.mean()np.bincount(stats[3].astype(np.int64), minlength=self._nc)else:torch.zeros(1)return mp, mr, map50, mapdef update(self, output, target):""" Calculates and updates metric valueContains postprocessing part from Ultralytics YOLOv5 project:param output: model output:param target: annotations"""annotation = target[0]["target"]width = target[0]["width"]height = target[0]["height"]shapes = target[0]["shape"]paths = target[0]["image_path"]im = target[0]["img"]iouv = torch.linspace(0.5, 0.95, 10).to(self._device)  # iou vector for mAP@0.5:0.95niou = iouv.numel()seen = 0stats = []# NMSannotation = torch.Tensor(annotation)annotation[:, 2:] *= torch.Tensor([width, height, width, height]).to(self._device)  # to pixelslb = []out = output[0]out = torch.Tensor(out).to(self._device)out = non_max_suppression(out, self._conf_thres, self._iou_thres, labels=lb,multi_label=True, agnostic=self._single_cls)# Metricsfor si, pred in enumerate(out):labels = annotation[annotation[:, 0] == si, 1:]nl = len(labels)tcls = labels[:, 0].tolist() if nl else []  # target class_, shape = Path(paths[si]), shapes[si][0]seen += 1if len(pred) == 0:if nl:stats.append((torch.zeros(0, niou, dtype=torch.bool), torch.Tensor(), torch.Tensor(), tcls))continue# Predictionsif self._single_cls:pred[:, 5] = 0predn = pred.clone()scale_coords(im[si].shape[1:], predn[:, :4], shape, shapes[si][1])  # native-space pred# Evaluateif nl:tbox = xywh2xyxy(labels[:, 1:5])  # target boxesscale_coords(im[si].shape[1:], tbox, shape, shapes[si][1])  # native-space labelslabelsn = torch.cat((labels[:, 0:1], tbox), 1)  # native-space labelscorrect = process_batch(predn, labelsn, iouv)else:correct = torch.zeros(pred.shape[0], niou, dtype=torch.bool)stats.append((correct.cpu(), pred[:, 4].cpu(), pred[:, 5].cpu(), tcls))self._stats.append((correct.cpu(), pred[:, 4].cpu(), pred[:, 5].cpu(), tcls))self._last_stats = statsdef reset(self):""" Resets metric """self._metric_dict = {"AP@0.5": [], "AP@0.5:0.95": []}self._last_stats = []self._stats = []def get_attributes(self):"""Returns a dictionary of metric attributes {metric_name: {attribute_name: value}}.Required attributes: 'direction': 'higher-better' or 'higher-worse''type': metric type"""return {self._names[0]: {'direction': 'higher-better','type': 'AP@0.5'},self._names[1]: {'direction': 'higher-better','type': 'AP@0.5:0.95'}}

4 运行优化流程

设置量化算法及相关参数,定义并运行量化流水线。

def get_config():""" Set the configuration of the model, engine,dataset, metric and quantization algorithm."""config = dict()data_yaml = check_yaml("./data/coco128.yaml")data = check_dataset(data_yaml)model_config = Dict({"model_name": "yolov5s","model": "./weights/yolov5s_openvino_model/yolov5s.xml","weights": "./weights/yolov5s_openvino_model/yolov5s.bin"})engine_config = Dict({"device": "CPU","stat_requests_number": 8,"eval_requests_number": 8})dataset_config = Dict({"data_source": data,"imgsz": 640,"single_cls": True,})metric_config = Dict({"conf_thres": 0.001,"iou_thres": 0.65,"single_cls": True,"nc": 1,  # if opt.single_cls else int(data['nc']),"names": data["names"],"device": "cpu"})algorithms = [{"name": "DefaultQuantization",  # or AccuracyAware"params": {"target_device": "CPU","preset": "mixed","stat_subset_size": 300}}]config["model"] = model_configconfig["engine"] = engine_configconfig["dataset"] = dataset_configconfig["metric"] = metric_configconfig["algorithms"] = algorithmsreturn config""" Download dataset and set config
"""
print("Run the POT. This will take few minutes...")
config = get_config()
init_logger(level='INFO')save_dir = Path("./weights/yolov5s_openvino_model/")
save_dir.mkdir(parents=True, exist_ok=True)  # make dir# Step 1: Load the model.
model = load_model(config["model"])# Step 2: Initialize the data loader.
data_loader = YOLOv5DataLoader(config["dataset"])# Step 3 (Optional. Required for AccuracyAwareQuantization): Initialize the metric.
metric = COCOMetric(config["metric"])# Step 4: Initialize the engine for metric calculation and statistics collection.
engine = IEEngine(config=config["engine"], data_loader=data_loader, metric=metric)# Step 5: Create a pipeline of compression algorithms.
pipeline = create_pipeline(config["algorithms"], engine)metric_results = None# Step 6: Execute the pipeline to calculate Min-Max value
compressed_model = pipeline.run(model)# Step 7 (Optional):  Compress model weights to quantized precision
#                     in order to reduce the size of final .bin file.
compress_model_weights(compressed_model)# Step 8: Save the compressed model to the desired path.
optimized_save_dir = Path(save_dir).joinpath("optimized")
save_model(compressed_model, Path(Path.cwd()).joinpath(optimized_save_dir), config["model"]["model_name"])

5 比较原始模型和量化模型的准确性

FP32:

# Step 9 (Optional): Evaluate the compressed model. Print the results.
metric_results_i8 = pipeline.evaluate(compressed_model)
print("Quantized INT8 model metric_results: {}".format(metric_results_i8))

输出:

FP32 model metric_results: {'AP@0.5': 0.7051576693437555, 'AP@0.5:0.95': 0.44624265930493545}

INT8:

# Step 9 (Optional): Evaluate the compressed model. Print the results.
metric_results_i8 = pipeline.evaluate(compressed_model)print("Quantized INT8 model metric_results: {}".format(metric_results_i8))

输出:

Quantized INT8 model metric_results: {'AP@0.5': 0.6924341121617621, 'AP@0.5:0.95': 0.43698028961534857}

6 比较原始模型和量化模型的性能

使用OpenVINO中的Benchmark Tool(推理性能测量工具)测量FP32和INT8模型的推理性能

FP32:

 benchmark_app -m .\weights\yolov5s_openvino_model\yolov5s.xml -d CPU -api async

输出:
在这里插入图片描述

INT8:

benchmark_app -m .\weights\yolov5s_openvino_model\optimized\yolov5s.xml -d CPU -api async

输出:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_306535.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】打开Linux大门,踏入Linux世界(环境搭建再加一群Linux基本指令就OK啦~)

🧑‍🎓个人主页:简 料 🏆所属专栏:Linux系统编程与网络编程 🏆个人社区:越努力越幸运社区 🏆简 介:简料简料,简单有料~在校大学生一枚&#x…

URLConnection(三)

文章目录 1. 配置连接2. protected URL url3. protected boolean connected4. protected boolean allowUserInteraction5. protected boolean doInput5. protected boolean doOutput6. protected boolean isModifiedSince7. protected boolean useCaches8. 超时 1. 配置连接 U…

【C++实现插入排序、希尔排序、冒泡排序、快速排序、选择排序】

使用C实现来插入排序、希尔排序、冒泡排序、快速排序、选择排序算法。 一、插入排序 插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好…

有哪些pdf转word的免费软件?这个办法值得一试

在日常工作和学习中,我们经常需要将PDF文件转换为Word文档。尤其是在需要编辑PDF文档中的内容时,将其转换为Word文档是非常必要的。但是,很多人不知道该如何快速完成这项任务。在本文中,我们将介绍一些简单的转换方式,…

服务器被勒索病毒攻击怎么办,如何进行勒索病毒解密与预防工作?

在当今社会中服务器已经成为企业关键数据存储和传输的重要载体,同样也成为黑客攻击和勒索病毒的首要目标。一旦服务器被勒索病毒攻击,企业的正常运转与经济利益和核心数据都将受到威胁。下面将为大家介绍一下服务器被勒索病毒攻击后应该采取怎样的措施及…

VanillaNet:深度学习极简主义的力量

摘要 基础模型的核心是“更多不同”的理念,计算机视觉和自然语言处理方面的出色表现就是例证。然而,Transformer模型的优化和固有复杂性的挑战要求范式向简单性转变。在本文中,我们介绍了VanillaNET,这是一种设计优雅的神经网络架…

vite-plugin-pwa配置详解

vite-plugin-pwa配置详解 前提:前端域名和后端服务域名相同时,用window.open新开页面下载或者导出文件,项目中导出和下载功能失效,原因是,域名相同走缓存 实现service worker离线缓存以前需要自己编写sw.js文件内容&…

npm更换成淘宝镜像源及cnpm使用

1.需求由来 由于node安装插件是从国外服务器下载,受网络影响大,速度慢且可能出现异常。所以如果npm的服务器在中国就好了,所以我们乐于分享的淘宝团队(阿里巴巴旗下业务阿里云)干了这事。来自官网:“这是一…

AnsiConsole-能够编写 ANSI 转义序列的控制台

Spectre.Console 是一款 .NET 库,提供了一种简单但强大的方式来创建美观和交互式的控制台应用程序。它允许开发人员轻松构建具有颜色、表格、进度条等功能的富命令行界面 (CLI)。 功能 Spectre.Console 的一些显着功能包括: 颜色:Spectre.C…

单片机GD32F303RCT6 (Macos环境)开发 (二十八)—— 蓝牙透传模块HC-08 Android App开发

蓝牙透传模块HC-08 Android App开发 1、App整体开发思路 a、首先要申请权限,采用动态申请的方式,用户点击确认后方可操作蓝牙。 b、搜索蓝牙,之前的版本用startLeScan函数搜索蓝牙,虽然高版本中依然可用,但是google已…

4.Ansible Inventory介绍及实战 - A list or group of lists nodes

什么是inventory? 官方解释:Ansible automates tasks on managed nodes or “hosts” in your infrastructure, using a list or group of lists known as inventory. Ansible可以同时与您基础设施中的一个或多个系统协同工作。为了与多台服务…

接口测试的请求和响应

接口测试的请求和响应 在软件开发中,接口测试是必不可少的一环节。接口测试主要涉及到测试请求和响应的过程。请求是指客户端向服务器发送的一些指令或数据,而响应则是服务器对这些请求做出的回应。 请求通常包括请求方法、请求头以及请求体。请求方法有…

【什么是iMessage苹果推?】什么是苹果推信?什么是苹果推?

挑选得当的IM推送平台:选择合用于PC真个IM推送平台 开辟或集成API:依照所选平台的开发文档,利用响应的编程语言(如Python、Java等)开发或集成API,以便与平台举行交互和节制。API可用于建立、办理和发送消息…

【HarmonyOS】【FAQ】HarmonyOS应用开发相关问题解答(二)

【写在前面】 之前和大家分享过一下HarmonyOS应用开发相关问题,今天继续和大家分享! 【前提简介】 本文档主要总结HarmonyOS开发过程中可能遇到的一些问题解答,主要围绕HarmonyOS展开,包括但不限于不同API版本HarmonyOS开发、UI…

单体项目偶遇并发漏洞!短短一夜时间竟让老板蒸发197.83元

事先声明:以下故事基于真实事件而改编,如有雷同,纯属巧合~ 眼下这位正襟危坐的男子,名为小竹,他正是本次事件的主人公,也即将成为熊猫集团的被告,嗯?这究竟怎么一回事?欲…

Linux网络编程—Day10

Linux服务器程序规范 Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端,因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程(PID为1的进程);Linux服务器程序通常有一套日志系统&#…

设备快线客户端软件V1.0用户手册

1.前言欢迎使用设备快线客户端软件产品。设备快线客户端软件简称DYClient,DYClient客户端是东用科技有限公司推出的一款用于远程维护的控制软件,主要为客户远程访问现场终端设备提供便捷的接入服务,并且通过DYClient客户端软件用户可以非常方便快捷的访问…

基于RetinaNet和TensorFlow Object Detection API实现目标检测(附源码)

文章目录 一、RetinaNet原理二、RetinaNet实现1. tf.train.CheckPoint简介2. RetinaNet的TensorFlow源码 一、RetinaNet原理 待补充 二、RetinaNet实现 1. tf.train.CheckPoint简介 待补充 2. RetinaNet的TensorFlow源码 Step 1:安装Tensorflow 2 Object Detect…

云原生之深入解析Docker容器退出码的含义和产生原因

一、前言 为什么我的容器没有运行?回答这个问题之前,需要知道 Docker 容器为什么退出?退出码会提示容器停止运行的情况?本文列出最常见的退出码,来回答两个重要问题:这些退出码是什么意思?导致该退出码的动作是什么?exit code:代表一个进程的返回码,通过系统调用 exi…

chatgpt赋能python:Python修改密码:一种安全可靠、快速高效的方式

Python 修改密码:一种安全可靠、快速高效的方式 在数字化时代,越来越多的信息被存储在计算机系统中,因此密码的保护变得尤为重要。人们需要保证他们的密码是安全可靠的,并定期更换密码。Python作为一种强大而且通用的编程语言&am…