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

news2024/12/23 0:34:44

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_source
        self._imgsz = config.imgsz
        self._batch_size = 1
        self._stride = 32
        self._single_cls = config.single_cls
        self._pad = 0.5
        self._rect = False
        self._workers = 1
        self._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 dataloader

    def __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_data

        im = im.float()
        im /= 255
        nb, _, height, width = im.shape
        img = im.cpu().detach().numpy()
        target = target.cpu().detach().numpy()

        annotation = dict()
        annotation['image_path'] = path
        annotation['target'] = target
        annotation['batch_size'] = nb
        annotation['shape'] = shape
        annotation['width'] = width
        annotation['height'] = height
        annotation['img'] = img

        return (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_thres
        self._iou_thres = config.iou_thres
        self._single_cls = config.single_cls
        self._nc = config.nc
        self._class_names = {idx:name for idx,name in enumerate(config.names)}
        self._device = config.device

    @property
    def 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]}

    @property
    def 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.0
        stats = [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, map

    def update(self, output, target):
        """ Calculates and updates metric value
        Contains 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.95
        niou = iouv.numel()
        seen = 0
        stats = []
        # NMS
        annotation = torch.Tensor(annotation)
        annotation[:, 2:] *= torch.Tensor([width, height, width, height]).to(self._device)  # to pixels
        lb = []
        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)
        # Metrics
        for 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 += 1

            if len(pred) == 0:
                if nl:
                    stats.append((torch.zeros(0, niou, dtype=torch.bool), torch.Tensor(), torch.Tensor(), tcls))
                continue

            # Predictions
            if self._single_cls:
                pred[:, 5] = 0
            predn = pred.clone()
            scale_coords(im[si].shape[1:], predn[:, :4], shape, shapes[si][1])  # native-space pred

            # Evaluate
            if nl:
                tbox = xywh2xyxy(labels[:, 1:5])  # target boxes
                scale_coords(im[si].shape[1:], tbox, shape, shapes[si][1])  # native-space labels
                labelsn = torch.cat((labels[:, 0:1], tbox), 1)  # native-space labels
                correct = 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 = stats

    def 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_config
    config["engine"] = engine_config
    config["dataset"] = dataset_config
    config["metric"] = metric_config
    config["algorithms"] = algorithms

    return 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.coloradmin.cn/o/571152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux之文件权限类命令

文件权限类命令 文件属性 Linux系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限。为了保护系统的安全线,Linux系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定,在…

白嫖免费版gpt与wetab插件的使用

目录 网址 如何使用 wetab 介绍wetab 怎么获得这个插件 使用效果 网址 1. wetab网站 : chatgpt (免费,不需要账号,不需要翻墙) 2. gpt镜像网站:https://chatbot.theb.ai/#/chat/1002 (免费,不需要账号&#xff0…

learn C++ NO.6——类和对象(4)

1.再谈构造函数 1.1.构造函数体赋值 在创建类的对象时,编译器回去调用类的构造函数,来各个成员变量一个合适的值。 class Date { public:Date(int year,int month,int day){_year year;_month month;_day day;}private:int _year;int _month;int _…

Neepu2023-部分Reserve复现

目录 Base IKUN检查器 dnSpy junk code Cheat Engine工具使用: 奇怪的ELF mov混淆问题: Xor Base 打开附件,可以看到主函数 先是给出一个物理题,要求输入答案,这个无关紧要,接着要求输入一串字符&…

MyBatis-Plus 可视化代码生成器来啦,生产力直接拉满

在基于Mybatis的开发模式中,很多开发者还会选择Mybatis-Plus来辅助功能开发,以此提高开发的效率。虽然Mybatis也有代码生成的工具,但Mybatis-Plus由于在Mybatis基础上做了一些调整,因此,常规的生成工具生成的代码还有一…

被Chatgpt碾压的打工人与大学生,准备反击!

最近一段时间,chatgpt可谓如火如荼,它的出现引发各行各业的震动,有人利用它实现了一夜暴富,有企业将它纳进人才招聘的技能要求中,国内各大厂商也纷纷下场推出自家的AI大模型,从第一代到GPT-4,所…

基于html+css的图片展示92

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

用好 kafka,你不得不知的那些工具

前言 工欲善其事,必先利其器。本文主要分享一下消息中间件 kafka 安装部署的过程,以及我平时在工作中针对 kafka 用的一些客户端工具和监控工具。 kafka 部署架构 一个 kafka 集群由多个kafka broker组成,每个broker将自己的元数据信息注册…

【ROS2】install micro_ros

本文参考b站up:“照祥同学”的教程来的,中间一些细节的操作谨以此文作为补充,或者说是我在按照教程走的时候遇到的问题记录。视频链接:第二节:安装micro_ros 的 Arduino 开发环境_哔哩哔哩_bilibili 1. 安装和配置ros…

集权安全 | 域渗透中的 DCSync技术分析

DCSync是AD域渗透中常用的凭据窃取手段,默认情况下,域内不同DC每隔15分钟会进行一次数据同步,当一个DC从另外一个DC同步数据时,发起请求的一方会通过目录复制协议(MS- DRSR)来对另外一台域控中的域用户密码…

一分钟图情论文:《面向学科建设的我国文献资源保障评价研究综述》

一分钟图情论文:《面向学科建设的我国文献资源保障评价研究综述》 高质量的文献资源保障工作不仅能够提供完备的环境、满足用户的信息需求,在高校中,还可以发挥促进教学资源优化和科研成果产出、增强科技基础能力等作用。华中师范大学的夏立…

『树莓派云台机器人』01. 使用手机控制树莓派云台机器人

目录 1. 检查是否已经开机,连接机器人wifi2. 安装树莓派控制app应用,直连模式连接机器人3. 机器人功能实现总结 欢迎关注 『树莓派云台机器人』 博客,持续更新中 欢迎关注 『树莓派云台机器人』 博客,持续更新中 动手组装等步骤请…

halcon 安装21.05版本 小坑记录

(注意:都可以设置语言) 1.选择扩展安装 影响安装进度显示 可以后续单独安装 Visual Studio变量检查扩展 2.破解相关 主程序dll路径 路径: C:\Users******\AppData\Local\Programs\MVTec\HALCON-21.05-Progress\bin\x64-win64 Visual St…

chatgpt赋能python:Python修改配置文件

Python 修改配置文件 Python 作为一种优秀的编程语言,在实际使用中起到了很大的作用。对于开发者来说,修改配置文件是一个常见的操作,Python 也支持在代码中修改配置文件。本篇文章将介绍如何使用 Python 修改配置文件,并且分享一…

【CSAPP】虚拟内存 | 地址空间 | 页表内存保护 | 页错误引发异常逐出 (evicted)

💭 写在前面:本文将学习《深入理解计算机系统》虚拟内存部分,CSAPP 是计算机科学经典教材《Computer Systems: A Programmers Perspective》的缩写,该教材由Randal E. Bryant和David R. OHallaron 合著。 📜 本章目录…

Bytebase:更好地管理你的 OceanBase 数据库

我们很高兴宣布:OceanBase 用户现在可以使用 Bytebase 进行数据库变更管理啦!🚀 Bytebase 是一款为 DevOps 团队准备的数据库 CI/CD 工具,专为开发者和 DBA 打造,也是唯一被 CNCF Landscape 收录的 Database CI/CD 产…

k8s 弹性伸缩的使用

1.手动扩缩容 编辑一个yaml文件 vi deployment-nginx.yaml apiVersion: apps/v1 kind: Deployment metadata:lables:app: nginxname: nginxnamespace: default spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name:…

C语言交换数组内容

代码&#xff1a; int main() {int arr1[] { 1,2,3,4,5 };int arr2[] { 6,7,8,9,0 };int sz sizeof(arr1) / sizeof(arr1[0]);int i 0;for (i 0;i<sz; i ) {int tmp arr1[i];arr1[i] arr2[i];arr2[i] tmp;}for (i 0; i < sz; i) {printf("%d ", ar…

用Vue简单开发一个学习界面

文章目录 一.首先创建我们的Vue文件夹二.源代码BodyDemoHearderDemoHomeDemoMarkdownDemoFileManager.jsMain.js&#xff08;注意绑定&#xff09;APP源代码 效果图&#xff08;按钮功能&#xff09;新增二级菜单&#xff08;v-for&#xff09;需要的可以私信 一.首先创建我们的…

办公技巧:学会这 7 种 PPT 制作技巧,让 PPT 制作效率飙升

F4 键&#xff1a;重复上一步操作 例如需要你在一分钟内完成 8 个形状的排版&#xff0c;你会怎么做&#xff1f; 如果是最基础的方式&#xff0c;可能得画出一个之后&#xff0c;慢慢的按住 Ctrl 复制新的出来&#xff0c;但这样实在是太慢了&#xff01;&#xff08;你是这样…