rv1109/1126 rknn 模型部署过程

news2024/9/23 1:41:21

rv1109/1126是瑞芯微出的嵌入式AI芯片,带有npu, 可以用于嵌入式人工智能应用。算法工程师训练出的算法要部署到芯片上,需要经过模型转换和量化,下面记录一下整个过程。

量化环境

模型量化需要安装rk的工具包:
rockchip-linux/rknn-toolkit (github.com)
版本要根据开发板的固件支持程度来,如果二者不匹配,可能转出来的模型无法运行或者结果不对。

模型量化

rknn支持caffe,tensorflow,tflite,onnx,mxnet,pytorch等模型量化,下面以onnx为例,其他格式基本类似。即可以使用量化包带的可视化界面,也可以自行写代码,更推荐自己写代码,复用性和灵活性更强,对可视化界面一笔带过。

可视化量化工具

执行

python -m rknn.bin.visualization

image.png

选择对应格式,然后设置模型参数进行量化。
image.png

写代码量化

image.png

基础量化

最简单的量化方式如下,只需设置模型的均值、方差,载入原始模型,调用rknn.build接口,然后export_rknn即可。

from rknn.api import RKNN

if __name__ == '__main__':
	rknn=RKNN()
	# pre-process config
	print('--> config model')
	rknn.config(channel_mean_value='0 0 0 255',
				reorder_channel='0 1 2',
				target_platform=['rv1109'],
				#quantized_dtype="dynamic_fixed_point-i16"
				)
	print('done')

	# Load mxnet model
	onnx_model = 'yolov8n.onnx'
	print('--> Loading model')
	ret = rknn.load_onnx(onnx_model)
	if ret != 0:
		print('Load onnx_model model failed!')
		exit(ret)
	print('done')
	# Build model
	print('--> Building model')
	ret = rknn.build(do_quantization=True, dataset='../coco_resize.txt', pre_compile=False) # 若要在PC端仿真,pre_compile 为False
	if ret != 0:
		print('Build model failed!')
		exit(ret)
	print('done')

	print('--> Export RKNN model')
	ret = rknn.export_rknn('yolov8n_nohead.rknn')
	if ret != 0:
		print('Export RKNN model failed!')
		exit(ret)
	print('done')
	rknn.release()

模型量化需要提供量化图片的列表,格式为每行是一张图片的路径, 一般需要几百张,如:

images/0.jpg
images/1.jpg

模型推理验证

有两种方式验证模型的结果,一种是连接开发板,在开发板上运行,可以实际测试模型的推理速度,需要USB连接开发板,一种是在PC端仿真,速度较慢,适合在没有开发板的情况下,验证模型结果是否正确。两种方式使用的代码大部分一样,区别是在PC端仿真时,模型要以pre_compile=False模式进行量化,init_runtime参数为targe=None。

import os
import sys
from rknn.api import RKNN
import cv2
import numpy as np
 
if __name__=="__main__":
    # Create RKNN object
    rknn = RKNN()
    print('--> Loading RKNN model')
    ret = rknn.load_rknn('yolov8.rknn')
    if ret != 0:
        print('Load  failed!')
        exit(ret)
    print('load done')
    # Init Runtime
    rknn.init_runtime(target="rv1109")#第二个参数device_id为开发板的设备id,不用填, targe=None时,代表PC仿真
	 image = cv2.imread("1.jpg")
	 outputs = rknn.inference(inputs=[image]) 
    rknn.release()

量化精度评估(逐层)

有些时候,量化损失可能过大,这时我们希望能够逐层比对量化后模型与原始模型,这时需要使用accuracy_analysis接口,这个接口第一个参数是图片列表文件,里面是测试图片的路径,第二个参数是比对结果保存路径:

from rknn.api import RKNN

if __name__ == '__main__':
	rknn=RKNN()
	# pre-process config
	print('--> config model')
	rknn.config(channel_mean_value='0 0 0 255',
				reorder_channel='0 1 2',
				target_platform=['rv1109'],
				#quantized_dtype="dynamic_fixed_point-i16"
				)
	print('done')

	# Load mxnet model
	onnx_model = 'yolov8n.onnx'
	print('--> Loading model')
	ret = rknn.load_onnx(onnx_model)
	if ret != 0:
		print('Load onnx_model model failed!')
		exit(ret)
	print('done')
	# Build model
	print('--> Building model')
	ret = rknn.build(do_quantization=True, dataset='../coco_resize.txt', pre_compile=False) # 若要在PC端仿真,pre_compile 为False
	if ret != 0:
		print('Build model failed!')
		exit(ret)
	print('done')
	rknn.accuracy_analysis("test_list.txt", output_dir='./snapshot5')			               
	print('--> Export RKNN model')
	ret = rknn.export_rknn('yolov8n_nohead.rknn')
	if ret != 0:
		print('Export RKNN model failed!')
		exit(ret)
	print('done')
	rknn.release()

比对文件如下:

Conv__model.0_conv_Conv_214_out0_nhwc_1_320_320_16.tensor    	eculidean_norm=0.030792	cosine_norm=0.999525	eculidean=202.926056	cosine=0.999526
Sigmoid__model.0_act_Sigmoid_213_Mul__model.0_act_Mul_212_out0_nhwc_1_320_320_16.tensor 	eculidean_norm=0.049676	cosine_norm=0.998766	eculidean=178.751434	cosine=0.998767
Conv__model.1_conv_Conv_210_out0_nhwc_1_160_160_32.tensor    	eculidean_norm=0.103382	cosine_norm=0.994656	eculidean=521.709229	cosine=0.994656
Sigmoid__model.1_act_Sigmoid_211_Mul__model.1_act_Mul_209_out0_nhwc_1_160_160_32.tensor 	eculidean_norm=0.113702	cosine_norm=0.993536	eculidean=436.044495	cosine=0.993536
Conv__model.2_cv1_conv_Conv_208_out0_nhwc_1_160_160_32.tensor 	eculidean_norm=0.120058	cosine_norm=0.992793	eculidean=351.808380	cosine=0.992794
Sigmoid__model.2_cv1_act_Sigmoid_207_Mul__model.2_cv1_act_Mul_205_out0_nhwc_1_160_160_32.tensor 	eculidean_norm=0.169184	cosine_norm=0.985688	eculidean=262.819550	cosine=0.985688

混合量化

有些时候,使用默认量化方法模型精度损失较大,我们通过逐层分析,也知道了那些层的损失较大,这时就需要控制一些层不量化,或以更高精度模式量化,这种方式就是混合量化。
与基础量化相比,混合量化分为两步:
第一步是通过rknn.hybrid_quantization_step1(替换基础量化中的rknn.build)获得模型的量化配置文件:

rknn.hybrid_quantization_step1(dataset='../coco_resize.txt')

该接口会生成3个文件:

xx.data
xx.json
xx.quantization.cfg

其中,.cfg文件时量化配置文件,用于控制每一层的量化:

%YAML 1.2
---
# add layer name and corresponding quantized_dtype to customized_quantize_layers, e.g conv2_3: float32
customized_quantize_layers: {}
quantize_parameters:
    '@attach_Concat_/model.22/Concat_5/out0_0:out0':
        dtype: asymmetric_affine
        method: layer
        max_value:
        -   647.7965087890625
        min_value:
        -   0.0
        zero_point:
        -   0
        scale:
        -   2.5403785705566406
        qtype: u8
    '@Concat_/model.22/Concat_5_1:out0':
        dtype: asymmetric_affine
        method: layer
        max_value:
        -   647.7965087890625
        min_value:
        -   0.0
        zero_point:
        -   0
        scale:
        -   2.5403785705566406
        qtype: u8

对于不量化或者以其他精度模式量化的层,以字典形式写在customized_quantize_layers中,rv1109支持asymmetric_quantized-u8,dynamic_fixed_point-i8和dynamic_fixed_point-i16,默认情况下,以asymmetric_quantized-u8方式量化,在需要更高精度时,可用dynamic_fixed_point-i16,但速度会更慢。对于损失较大的层,我们可以尝试设置dynamic_fixed_point-i16量化(若float32则不量化):

customized_quantize_layers: {
    "Split_/model.22/Split_21": "dynamic_fixed_point-i16",
    "Reshape_/model.22/dfl/Reshape_20": "float32"
}

设置完成量化配置后,使用rknn.hybrid_quantization_step2进行量化:

from rknn.api import RKNN

if __name__ == '__main__':
	rknn=RKNN()
	# pre-process config
	print('--> config model')
	rknn.config(channel_mean_value='0 0 0 255',
				reorder_channel='0 1 2',
				target_platform=['rv1109'],
				#quantized_dtype="dynamic_fixed_point-i16"
				)
	print('done')

	# Load mxnet model
	onnx_model = 'yolov8n.onnx'
	print('--> Loading model')
	ret = rknn.load_onnx(onnx_model)
	if ret != 0:
		print('Load onnx_model model failed!')
		exit(ret)
	print('done')
	# Build model
	print('--> Building model')

	rknn.hybrid_quantization_step2(dataset='../coco_resize.txt',   model_input='torch_jit.json',
								   data_input="torch_jit.data",
								   model_quantization_cfg="torch_jit.quantization.cfg",
								   pre_compile=False)
	if ret != 0:
		print('Build model failed!')
		exit(ret)
	print('done')
	rknn.accuracy_analysis("test_list.txt", output_dir='./snapshot5')			               
	print('--> Export RKNN model')
	ret = rknn.export_rknn('yolov8n_nohead.rknn')
	if ret != 0:
		print('Export RKNN model failed!')
		exit(ret)
	print('done')
	rknn.release()

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

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

相关文章

weblogic XML反序列化分析——CVE-2017-10271

环境 https://vulhub.org/#/environments/weblogic/CVE-2017-10271/ 启动环境 docker-compose up -d代码审计 传入参数 中间跟进函数 最后的出口 没有限制,直接包参数传入xmlDecoder public String readLine() throws IOException {return (String)this.xml…

Class Central-全球在线课程搜索引擎和学习平台

Class Central(课程中央网站)是一个全球在线课程搜索引擎和学习平台,全球知名的慕课资源导航社区,汇集了来自Coursera(斯坦佛大学)、edX(麻省理工学院)、Futurelearn(英国…

如何使用vue ui创建一个项目?

首先打开cmd 输入vue ui 等待浏览器打开一个窗口,按照下图操作 在"功能页面"中,各个插件代表以下意思: Babel:Babel是一个JavaScript编译器,用于将ES6代码转换为向后兼容的JavaScript版本,以确保…

ORB-SLAM2学习笔记6之D435i双目IR相机运行ROS版ORB-SLAM2并发布位姿pose的rostopic

文章目录 0 引言1 D435i相机配置2 新增发布双目位姿功能2.1 新增d435i_stereo.cc代码2.2 修改CMakeLists.txt2.3 新增配置文件D435i.yaml 3 编译运行和结果3.1 编译运行3.2 结果3.3 可能出现的问题 0 引言 ORB-SLAM2学习笔记1已成功编译安装ROS版本ORB-SLAM2到本地&#xff0c…

C++入门篇6 C++的内存管理

在学习C的内存管理之前,我们先来回顾一下C语言中动态内存 int main() {int* p1 (int*)malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么?int* p2 (int*)calloc(4, sizeof(int));//calloc 可以初始化空间为0int* p3 (int*)reall…

渗透-01:DNS原理和HTML字符编码-HTML实体编码

一、DNS概念 DNS (Domain Name System 的缩写)就是根据域名查出IP地址(常用) DNS分类&#xff1a; 正向解析&#xff1a;已知域名解析IP反向解析&#xff1a;已知IP解析对应的域名 二、查询过程 工具软件dig可以显示整个查询过程 [rootnode01 ~]# dig baidu.com; <<>&…

pytorch学习——卷积神经网络——以LeNet为例

目录 一.什么是卷积&#xff1f; 二.卷积神经网络的组成 三.卷积网络基本元素介绍 3.1卷积 3.2填充和步幅 3.2.1填充&#xff08;Padding&#xff09; 填充是指在输入数据周围添加额外的边界值&#xff08;通常是零&#xff09;&#xff0c;以扩展输入的尺寸。填充可以在卷…

重磅特性 - SpreadJS推出新插件甘特图,预览版下载体验中

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 甘特图对于业务场景中的工程项目管理、预算执行、生产计划等都能将原有的表格数据&…

【数据分析】numpy (二)

numpy作为数据分析&#xff0c;深度学习常用的库&#xff0c;本篇博客我们来介绍numpy的一些进阶用法&#xff1a; 一&#xff0c;numpy的常用简单内置函数&#xff1a; 1.1求和&#xff1a; a np.array([[1, 2],[3, 4]]) np.sum(a)10 1.2求平均值&#xff1a; np.mean(a…

《向量数据库》——怎么安装向量检索库Faiss?

装 Faiss 以下教程将展示如何在 Linux 系统上安装 Faiss: 1. 安装 Conda。 在安装 Faiss 之前,先在系统上安装 Conda。Conda 是一个开源软件包和环境管理系统,可在 Windows、macOS 和 Linux 操作系统上运行。根据以下步骤在 Linux 系统上安装 Conda。 2. 从官网…

[模拟电路]集成运算放大器

目录 一.前言二.集成运放的介绍及特性分析1.集成运算放大器2.集成运放由四个部分组成3.集成运放的特性 三.集成运放的线性应用&#xff08;引入负反馈&#xff09;1.两个基本运算电路——反相/同相比例运算电路2.同相比例运算电路的特例——电压跟随器3.反相加法运算电路4.同相…

Android组件化入门:一步步搭建组件化架构

1、前言 最近因为业务需求变更&#xff0c;有考虑采用组件化架构进行开发&#xff0c;这方面我之前没有接触过。关于组件化的文章很多&#xff0c;各方大神更是提出了各种的组件化方案&#xff0c;我也看了很多相关文章。但是学习新东西看的再多&#xff0c;不如动手做一次&am…

CAD产品设计逆向软件 FARO RevEng Crack

CAD产品设计逆向软件 FARO RevEng 软件平台能为用户带来全面的数字设计体验。该反向工程软件有助于利用三维点云创建和编辑高质量的网格和 CAD 表面&#xff0c;以实现反向工程工作流程。然后&#xff0c;工业设计师可以利用这些网格模型进行进一步设计或三维打印。 RevEng 的商…

element-ui分页编辑器的使用

代码&#xff1a; 准备好初始数据; total: ,page: {pageSize: 1,pageNumber: 10,}, 当前显示在第一页,每页10条数据。 一,页码改变的事件 handleCurrentChange(val) { this.page.pageSizeval 通过传入(this.page) 获取当前页的数据 } 二.页容量改变 handleSizeChange(val) …

剑指offer49.丑数

看完题想了一下&#xff0c;就想到了一点&#xff0c;它就是先用1分别乘2&#xff0c;乘3&#xff0c;乘5然后往后加&#xff0c;然后用2分别乘2&#xff0c;乘3&#xff0c;乘5往后加&#xff0c;但是如果这样就是1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;4&…

更快的训练和推理: 对比 Habana Gaudi®2 和英伟达 A100 80GB

&#x1f917; 宝子们可以戳 阅读原文 查看文中所有的外部链接哟&#xff01; 通过本文&#xff0c;你将学习如何使用 Habana Gaudi2 加速模型训练和推理&#xff0c;以及如何使用 &#x1f917; Optimum Habana 训练更大的模型。然后&#xff0c;我们展示了几个基准测例&#…

春秋云镜 CVE-2020-5515

春秋云镜 CVE-2020-5515 Gila CMS 1.11.8 sql注入 靶标介绍 Gila CMS是一套基于PHP和MySQL的开源内容管理系统&#xff08;CMS&#xff09;。 Gila CMS 1.11.8版本中的/admin/sql?query存在SQL注入漏洞。该漏洞源于基于数据库的应用缺少对外部输入SQL语句的验证。攻击者可利…

【零基础学Rust | 基础系列 | 基础语法】变量,数据类型,运算符,控制流

文章目录 简介&#xff1a;一&#xff0c;变量1&#xff0c;变量的定义2&#xff0c;变量的可变性3&#xff0c;变量的隐藏 二、数据类型1&#xff0c;标量类型2&#xff0c;复合类型 三&#xff0c;运算符1&#xff0c;算术运算符2&#xff0c;比较运算符3&#xff0c;逻辑运算…

KVM+SAN 如何实现多个主机访问同一个卷组

KVMSAN存储 KVM宿主机的HBA卡通过光纤线 <-----> 光纤交换机 <-----> SAN存储 联想SAN存储&#xff1a; 1、创建卷组 可使用卷组来创建可供主机访问的一个或多个卷。卷组是具有共同特性&#xff08;如 RAID 级别和容量&#xff09;的卷的容器。 2、创建卷 可创…

vue el-input 使用 回车键会刷新页面的问题

场景&#xff1a; vue项目中 在输入框输入字符并按下回车键搜索时&#xff0c;不会进行搜索&#xff0c; 而是会刷新页面 原因&#xff1a; 当form表单中只有一个input时&#xff0c;按下回车建会自动触发页面的提交功能&#xff0c; 产生刷新页面的行为 解决&#xff1a; 在…