深度学习模型部署(四)——RKNN

一、RKNN部署及工具包安装

参考1:https://blog.csdn.net/qq_40280673/article/details/136211086#/
参考2:瑞芯微官方教程
RKNN部署针对瑞芯微芯片优化,支持NPU硬件加速,需要安装rknn-toolkit,用于将pytorch模型转换为RKNN模型
以下操作均在ubuntu中进行
运行环境要求如下:
在这里插入图片描述

1、安装python及相关依赖

sudo apt-get install python3 python3-dev python3-pip
sudo apt-get install libxslt1-dev zlib1g zlib1g-dev libglib2.0-0 libsm6 libgl1-mesa-glx libprotobuf-dev gcc

2、创建虚拟环境

# 创建虚拟环境
conda create -n your_env_name
# 激活虚拟环境
conda activate your_env_name

3、下载系统依赖及rknn-tookit安装包

系统依赖的库:requirements_cpxx-1.5.0.txt;
rknn-toolkit2安装包:rknn_toolkit2-1.5.0+fa95b5c-cpxx-linux_x86_64.whl
上述两个文件自取:
通过网盘分享的文件:libpackages
链接: https://pan.baidu.com/s/10xjTZ2Wr8CgGFV80tfXmZA 提取码: wwzn
【注】 cpxx取决于安装的python版本,如我的环境是ubuntu22.04,python版本3.10,因此我需要安装的是requirements_cp310-1.5.0.txt和rknn_toolkit2-1.5.0+fa95b5c-cp310-linux_x86_64.whl

4、安装系统依赖及rknn-toolkit2

激活需要安装的虚拟环境,运行以下指令时,执行目录须为txt文件和whl文件所在目录,也可以指定文件所在路径

pip install -r requirements_cp310-1.5.0.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
pip install rknn_toolkit2-1.5.0+1fa95b5c-cp310-cp310-linux_x86_64.whl -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

【注】 安装过程中可能有包下载不成功,可以手动pip安装,多试几个镜像源,或者爬梯子安装,一定要确保所有包安装成功

二、pytorch模型转换为rknn模型

我的文件结构如下:
在这里插入图片描述
datasets.txt的内容为
在这里插入图片描述

1、torch.nn.module——>rknn

参考1:https://blog.csdn.net/qq_40280673/article/details/136229500#/ 大佬的公众号有源码包,可以下载后执行
我参考着导出了一下yolov11n-cls模型:
【注】 要使用相同版本的pytorch导出模型并转为RKNN模型,否则会因为前后版本不一致导致RKNN转换失败。

# yolov11n-cls.pt转rknn模型
'''
1、导入RKNN包
2、实例化RKNN对象
3、定义数据预处理和量化方法
4、加载pytorch模型,即'.pt'文件
5、构建rknn模型
6、导出rknn模型
7、释放RKNN对象
'''
from rknn.api import RKNNif __name__=="__main__":rknn = RKNN()'''初始化RKNN对象时,可以设置verbose和verbose_file参数:verbose:是否在屏幕上打印详细的日志信息verbose_file:日志文件示例:将详细日志信息输出到屏幕,并写入到build.log文件中rknn=RKNN(verbose=True,verbose_file='./build.log')'''rknn.config(mean_values=[[0.0, 0.0, 0.0]], std_values=[[1.0, 1.0, 1.0]],target_platform='rk3588')'''def config(mean_values: Any | None = None, 输入的均值,用于数据预处理中的normalization,如mean_values=[128, 128, 128]]表示输入的三个通道的值减去128std_values: Any | None = None, 输入的标准差,用于数据预处理中的normalization,如std_values=[[128, 128, 128]]表示输入的三个通道减去均值后再除以128quantized_dtype: str = 'asymmetric_quantized-8',量化类型,目前支持asymmetric_quantized-8、asymmetric_quantized-16quantized_algorithm: str = 'normal',计算每一层的量化参数时采用的量化算法,目前支持normal、mmse和kl_divergencenormal:速度快,推荐量化数据量一般为20-100张左右mmse:暴力迭代方式,速度较慢,但精度比normal要高,推荐量化数据量20-50张左右kl_divergence:所有时间比normal多,比mmse少,适用于feature分布不均匀的场景,推荐量化数据量20-100张左右quantized_method: str = 'channel',目前支持layer、channellayer:每层的weight只有一套量化参数channel:每层的weight的每个通道都有一套量化参数,因此channel会比layer精度高target_platform: Any | None = None,指定RKNN模型是基于那个目标芯片平台生成的,目前支持‘rk3566’、‘rk3588’等quant_img_RGB2BGR: bool = False,表示在加载量化图像时是否需要先做RGB2BGR的操作(一般用在Caffe模型上)。如果有多个输入,则用列表包括起来,如[True, True, False]该配置只对jpg/jpeg/png/bmp格式的图片有效该配置仅用于量化阶段(build接口)读取量化图像或量化精度分析(accuracy_analysis接口),并不会保存在最终的RKNN模型中,因此如果模型的输入为bgr,则调用toolkit2的inference或C-API的run函数之前需要保证传入的图像数据为BGR格式float_dtype: str = 'float16',用于制定非量化情况下的浮点的数据类型,目前只支持float16optimization_level: int = 3,模型优化等级,通过修改该值可以关掉部分或全部模型转换过程中使用到的优化规则optimization_level=3:打开所有优化选项optimization_level=1或2:关闭一部分可能会对部分模型精度产生影响的优化选项optimization_level=0:关闭所有优化选项custom_string: Any | None = None,添加自定义字符串信息到RKNN模型,可以在runtime时通过query查询到该信息,方便部署时根据不同的RKNN模型做特殊处理remove_weight: bool = False,去除conv等权重以生成一个RKNN的从模型,该从模型可以与带完整权重的RKNN模型共享权重以减少内存消耗compress_weight: bool = False,压缩模型权重,可以减小RKNN模型的大小inputs_yuv_fmt: Any | None = None,single_core_mode: bool = False,是否仅生成单核模型,可以减小RKNN模型的大小和内存消耗,目前仅对RK3588生效dynamic_input: Any | None = None,用于根据用户制定的多组输入shape,来模拟动态输入的功能,格式为[[input0_shapeA, input1_shapeA, ...], [input0_shapeB, input1_shapeB, ...], ...]假设原始模型只有一个输入,shape为[1, 3, 224, 224],但需要该模型支持3种不同的输入shape,如[1, 3, 224, 224], [1, 3, 192, 192]和[1, 3, 160, 160]可以设置dynamic_input=[1, 3, 224, 224], [1, 3, 192, 192]和[1, 3, 160, 160],转换成RKNN模型后进行推理时,需要传入对应shape的数据【注】需要原始模型支持动态输入才可以开启此功能model_pruning: bool = False,对模型进行无损剪枝,对于权重稀疏的模型,可以减小转换后RKNN模型的大小和计算量op_target: Any | None = None,用于指定OP的具体执行目标(如NPU/CPU/GPU等)格式为{'op0_output_name':'cpu', 'op1_output_name':'npu',...}'op0_output_name'和'op1_output_name'对应op的输出tensor名,可以通过精度分析(accuracy_analysis)返回结果中获取'cpu'和'npu'表示该tensor对应的op的执行目标是CPU或NPU**kwargs: Any)无返回值'''rknn.load_pytorch(model = "yolov11n-cls.pt",input_size_list = [[1, 3, 480, 480]])'''def load_pytorch(model: Any,pytorch模型文件(.pt)路径,必须是torchscript格式的input_size_list: Any每个输入节点对应的shape,所有输入shape存放在一个列表中)   返回值:0:导入成功;-1;导入失败'''rknn.build(do_quantization=True,dataset='datasets.txt')'''def build(do_quantization: bool = True,是否对模型进行量化dataset: Any | None = None,用于量化校正的数据及,目前仅支持文本文件格式,用户可以把用于校正的图片(jpg、bmp或png格式)放到一个.txt文件中,文本文件中每一方存放一条路径信息,如a.jpg如果有多个输入,每个输入对应的文件用空格隔开,如a.jpg b.jpgrknn_batch_size: Any | None = None模型的输入batch参数调整,如果设置为大于1,则可以在一次推理中同时推理多帧输入图像或输入数据会同时改变输入和输出的batch)返回值:0:构建成功;-1:构建失败'''rknn.export_rknn(export_path="yolov11n-cls.rknn")'''def export_rknn(export_path: Any,导出模型文件的路径cpp_gen_cfg: Any | None = None,是否生成C++部署示例,生成文件:模型路径同文件夹下,生成rknn_deploy_demo文件夹、说明文档;支持验证模型推理是,各CAPI接口耗时;验证推理结果的余弦精度;支持常规API接口;支持图片/NPY输入**kwargs: Any)返回:0:导出成功;-1:导出失败'''print("finisned")rknn.release()

2、torch.nn.module——>onnx——>rknn

可以通过onnx作为中转解决pytorch导出和转换rknn模型的版本不一致问题
参考2:瑞芯微的官方教程
可以看出,onnx转rknn的程序与torch模型转rknn唯一的不同就是在加载模型时,使用load_onnx()
【注】 onnx的opset版本需要注意,如果导出失败可以根据报错提示,去修改导出onnx文件中的opset的版本号,如报错信息为ValueError: Unsupport onnx opset 17, need <= 12!,在导出onnx文件中设置model.export(format=“onnx”, opset=11) 即可

from rknn.api import RKNNif __name__=='__main__':rknn = RKNN()rknn.config(mean_values=[[0.0, 0.0, 0.0]],std_values=[[1.0, 1.0, 1.0]],target_platform='rk3588')rknn.load_onnx('yolov11n-cls.onnx')'''def load_onnx(model: Any,onnx模型文件路径inputs: Any | None = None,模型输入节点(tensor名),支持多个输入节点,所有输入节点名放在一个列表中input_size_list: Any | None = None,每个输入节点对应的shape,所有输入shape放在一个列表中。如果inputs有设置,input_size_list也需要设置input_initial_val: Any | None = None,设置模型输入的初始值,格式为ndarray的列表。主要用于将某些输入固化为常量,对于不需要固化为常量的输入可以设置为Noneoutputs: Any | None = None模型的输出节点(tensor名),支持多个输出节点,所有输出节点名放在一个列表中)返回值:0:导入成功;-1:导入失败'''rknn.build(do_quantization=True,dataset='datasets.txt')rknn.export_rknn('yolov11n-cls.rknn')rknn.release()

三、模型推理

模型推理有两种方式:
1、在PC上运行非RKNN模型
2、在NPU上运行RKNN模型

1、在PC上运行非RKNN模型

在这里插入图片描述

实现步骤为:

'''
1、实例化RKNN对象
2、调用Config接口设置模型的预处理参数
3、调用load_pytorch、load_onnx接口导入pytorch\onnx模型等
4、调用build接口构建RKNN模型
5、调用ini_runtime接口初始化运行环境,注意设置target=None,表示在模拟器上运行
6、导入要推理的数据并预处理数据
7、调用inference接口进行推理,获取推理结果
8、释放RKNN对象
'''

实现代码如下:

from rknn.api import RKNN
import cv2
import numpy as npif __name__=='__main__':rknn = RKNN()rknn.config(mean_values=[[0.0, 0.0, 0.0]], std_values=[[1.0, 1.0, 1.0]],target_platform='rk3588')# rknn.load_pytorch('yolov11n-cls.pt',#                   input_size_list=[[1, 3, 480, 480]])rknn.load_onnx('yolov11n-cls.onnx',input_size_list=[[1, 3, 480, 480]])rknn.build(do_quantization=True, dataset='datasets.txt', rknn_batch_size=-1)rknn.init_runtime(target=None,# target='rk3588',target_sub_class=None,device_id=None,perf_debug=False,eval_mem=False,async_mode=False,core_mask=RKNN.NPU_CORE_AUTO,)img = cv2.imread(filename='A6_6499.bmp')img = cv2.resize(img, (480, 480))cv2.cvtColor(img, cv2.COLOR_BGR2RGB)outputs = rknn.inference(inputs=[img],data_format="nhwc",'''cv2.imread()读取的图像数据的layout为NHWC,data_format的默认值为NHWC,如果模型的输入不是通过cv2.imread()读取,需要设置正确的data_format值''')print(np.array(outputs[0][0]))rknn.release()

2、在NPU上运行RKNN模型

2.1 推理前的准备工作

1)确保开发板的USB OTG连接到PC,并正确识别到设备。可以通过adb device命令查询相应设备,也可调用rknn-toolkit2的list_devices接口查询相应设备。

rknn = RKNN()
rknn.list_devices()
'''
def list_devices():无参数,返回adb_devices列表和ntb_devices列表,如果设备为空,则返回空列表
'''
rknn.release()输出为:
*************************
all device(s) with adb mode:
VD46C3KM6N
*************************

2)参考https://github.com/rockchip-linux/rknpu2/blob/master/rknn_server_proxy.md说明更新开发板的runtime库和rknn_server库,并确保rknn_server服务已经启动(大部分平台需要手动通过串口启动)
3)调用init_runtime接口初始化运行环境时需要指定target参数(开发平台,如target=‘rk3588’)和device_id参数(由步骤2list_devices中获取,如本例程中device_id=‘VD46C3KM6N’)。

2.2 模型推理实现步骤
在这里插入图片描述

'''
运行RKNN模型,不需要设置模型预处理参数,也不需要构建RKNN模型,推理流程:
1、实例化RKNN对象
2、调用load_rknn导入RKNN模型
3、调用init_runtime初始化,注意设置target='rk3588', device_id的值需要通过rknn.list_devices获取
4、导入要处理的数据并处理成需要的输入格式
5、调用inference进行推理并获取推理结果
6、释放RKNN对象
'''

实现代码:

from rknn.api import RKNN
import cv2 
import numpy as npif __name__=="__main__":rknn = RKNN()rknn.load_rknn('yolov11n-cls.rknn')rknn.init_runtime(target='rk3588',device_id='VD46C3KM6N')img = cv2.imread(filename='A6_6499.bmp')img = cv2.resize(img, (480, 480))cv2.cvtColor(img, cv2.COLOR_BGR2RGB)outputs = rknn.inference(inputs=[img],data_format="nhwc", '''cv2.imread()读取的图像数据的layout为NHWC,data_format的默认值为NHWC,如果模型的输入不是通过cv2.imread()读取,需要设置正确的data_format值''')print(np.array(outputs[0][0]))rknn.release()

四、模型量化

RKNN模型量化是一种将深度学习模型从浮点精度(如FP32)转换为低比特整数(如INT8)的技术,旨在减少模型体积、提升推理速度并降低功耗。量化对象:权重量化(模型参数从浮点转为整数)、激活量化(推理时中间特征图的数值转换)
4.1 量化原理:

1)线性量化原理

  • 使用比例因子scale和零点zero_point将浮点值映射到整数区间, quantized_value = round(float_value / scale) + zero_point
  • 反量化是还原近似原始值,float_value ≈ (quantized_value - zero_point) * scale

2)校准过程(PTQ)

  • 通过校准数据集统计各层激活值的动态范围,确定最优scale和zero_point
  • 关键作用:减少量化误差,避免数值溢出或截断

3)量化类型

  • 对称量化:零点为0,适合权重分布对称的场景
  • 非对称量化,零点非0,适合偏态分布数据
  • 混合精度量化:敏感层保留FP16,其他层用INT8

4.2 量化精度分析

重点函数为accuracy_analysis()
【注】 该接口只能在build和hybrid_quantization_step2之后调用。
【注】 如未制定target,且原始模型应该为已量化的模型,否则会调用失败
【注】 该接口使用的量化方式与config中制定的一致。

4.2.1 量化精度分析步骤

  • 实例化RKNN对象
  • 设置模型预处理和量化参数
  • 调用load_onnx等接口导入模型
  • 调用build构建模型
  • 调用accuracy_analysis进行量化精度分析
  • 释放RKNN对象

4.2.2 代码实现

from rknn.api import RKNNif __name__=="__main__":rknn = RKNN()rknn.config(mean_values=[[0.0, 0.0, 0.0]],std_values=[[1.0, 1.0, 1.0]],target_platform='rk3588')rknn.load_onnx('yolov11n-cls.onnx')rknn.build(do_quantization=True, dataset='datasets.txt')rknn.accuracy_analysis(inputs=['A6_6499.bmp'],output_dir='snapshot',target=None,         # 如果连接了开发板,target='rk3588', device_id=设备编号device_id=None)'''推理并产生快照,也就是dump出每一层的tensor数据,会dump出包括fp32和quant两种数据类型的快照,用于计算量化误差。def accuracy_analysis(inputs: Any,图像(jpg/png/bmp/npy等)路径listoutput_dir: str = './snapshot',输出目录,所有快照都保存在该目录下,默认值为'./snapshot'如果没有设置target,在output_dir下会输出:1、simulator目录:保存整个量化模型在simulator上完整运行时每一层的结果(已经转成float32)2、golden目录:保存整个浮点模型在simulator上完整跑下来时每一层的结果3、error_analysis.txt:记录simulator上量化模型逐层运行时每一层的结果与golden浮点模型逐层运行时每一层的结果的余弦距离(entire_error cosine),以及量化模型取上一层的浮点结果作为输入时,输出与浮点模型的余弦距离(single_error cosine)如果有设置target,则在output_dir里还会多输出:1、runtime目录:保存整个量化模型在NPU上完整运行时每一层的结果(已转成float32)2、error_analysis.txt:在上述记录内容的基础上,还会记录量化模型在simulator上逐层运行时每一层的结果的余弦距离target: Any | None = None,目标硬件平台,如果设置了target,则会获取NPU运行时每一层的结果,并进行精度分析device_id: Any | None = None设备编号,如果pc连接多台设备时,需要指定该参数)返回值:0:成功;-1:失败'''rknn.release()

4.2.3 输出

在这里插入图片描述
在这里插入图片描述
上图右侧有两列数值输出,其中entire表示simulator上量化模型逐层运行时每一层的结果与golden浮点模型逐层运行时每一层的结果的余弦距离,即量化模型整体输出与原始浮点模型(golden)的误差,反映端到端的累计误差;sigle表示量化模型取上一层的浮点结果作为输入时,输出与浮点模型的余弦距离,反映单层量化精度。值越接近于1表示误差越小。
【警惕关键现象1】 误差值范围,越接近1 表示量化误差越小,若出现显著下降(如0.99以下)须警惕精度损失
【警惕关键现象2】 NaN值,表示张量全零或数值极端,可能由无法激活或量化溢出导致。若存在须检查校准数据或量化参数。

4.2.4 优化建议

1)敏感层定位:对比entire和single误差差异较大层,优先采用混合量化
2)校准数据优化:若误差集中在前几层,需检查输入数据预处理是否与训练一致
3)量化策略调整:对误差突增层尝试非对称量化或调整量化粒度

4.3 混合量化

量化功能可能会使模型特殊模型的精度下降,为了在性能和精度之间做更好的平衡,混合优化功能,可以根据用用户的手动指定某些层是否进行量化。

4.3.1 混合量化步骤

  • 生成混合量化配置文件,hybrid_quatization_step1()
  • 修改第一步生成的量化配置文件(.quantization.cfg)
  • 生成新的RKNN模型,hybrid_quantization_step2()

4.3.2 生成混合量化配置文件

重要API为hybrid_quatization_step1(),执行以下代码会生成临时模型文件(.model)、数据文件(.data)和量化配置文件(.quantization.cfg)
步骤为:

  • 实例化RKNN对象
  • 设置模型预处理参数config
  • 加载模型文件, onnx等
  • 调用hybrid_quantization_step1()
  • 释放RKNN对象
from rknn.api import RKNNif __name__=="__main__":rknn = RKNN()rknn.config(mean_values=[[0.0, 0.0, 0.0]],std_values=[[1.0, 1.0, 1.0]],target_platform='rk3588')rknn.load_onnx('./yolov11n-cls.onnx')rknn.hybrid_quantization_step1(dataset='./datasets.txt',proposal=True,)'''用于生成临时模型文件(.model)、数据文件(.data)和量化配置文件(.quantization.cfg)def hybrid_quantization_step1(dataset: Any | None = None,量化用的数据集rknn_batch_size: Any | None = None,模型的输入batch参数的调整proposal: bool = False,产生混合量化的配置建议proposal_dataset_size: int = 1proposal使用的dataset的张数,默认为1.因proposal功能比较耗时,所以默认只是用1张,也就是dataset里的第一张)'''rknn.release()

yolov11n-cls.quatization.cfg文件内容如下

custom_quantize_layers:/model.0/conv/Conv_output_0: float16/model.0/act/Mul_output_0: float16/model.1/conv/Conv_output_0: float16/model.2/m.0/cv1/conv/Conv_output_0: float16/model.2/m.0/cv1/act/Mul_output_0: float16/model.2/m.0/Add_output_0: float16/model.2/Concat_output_0: float16/model.4/m.0/cv2/conv/Conv_output_0: float16/model.4/m.0/cv2/act/Mul_output_0: float16/model.4/m.0/Add_output_0: float16/model.4/Concat_output_0: float16/model.4/cv2/conv/Conv_output_0: float16/model.4/cv2/act/Mul_output_0: float16/model.5/conv/Conv_output_0: float16/model.6/m.0/m/m.0/cv1/act/Mul_output_0: float16/model.6/m.0/m/m.0/cv2/conv/Conv_output_0: float16/model.6/m.0/m/m.0/cv2/act/Mul_output_0: float16/model.6/m.0/m/m.0/Add_output_0: float16/model.6/m.0/cv3/act/Mul_output_0: float16/model.6/Concat_output_0: float16/model.8/m.0/m/m.0/cv1/act/Mul_output_0: float16/model.8/m.0/m/m.0/cv2/conv/Conv_output_0: float16/model.8/m.0/m/m.0/cv2/act/Mul_output_0: float16/model.8/m.0/m/m.0/Add_output_0: float16/model.8/m.0/m/m.1/cv1/conv/Conv_output_0: float16/model.8/m.0/m/m.1/Add_output_0: float16/model.8/m.0/m/m.1/cv1/act/Mul_output_0: float16/model.8/m.0/m/m.1/cv2/conv/Conv_output_0: float16/model.8/m.0/m/m.1/cv2/act/Mul_output_0: float16/model.8/m.0/Concat_output_0: float16/model.8/m.0/cv3/conv/Conv_output_0: float16/model.8/m.0/cv3/act/Mul_output_0: float16/model.8/Concat_output_0: float16/model.8/cv2/conv/Conv_output_0: float16/model.8/cv2/act/Mul_output_0: float16/model.9/cv1/conv/Conv_output_0: float16/model.9/cv1/act/Mul_output_0: float16/model.9/Split_output_0: float16/model.9/Concat_output_0: float16/model.9/Split_output_1: float16/model.9/m/m.0/attn/qkv/conv/Conv_output_0: float16/model.9/m/m.0/Add_output_0: float16/model.9/m/m.0/attn/Reshape_output_0: float16/model.9/m/m.0/attn/Split_output_0: float16/model.9/m/m.0/attn/Softmax_output_0: float16/model.9/m/m.0/attn/Transpose_1_output_0: float16/model.9/m/m.0/attn/MatMul_1_output_0: float16/model.9/m/m.0/attn/Reshape_1_output_0: float16/model.9/m/m.0/attn/Add_output_0: float16/model.9/m/m.0/attn/proj/conv/Conv_output_0: float16/model.9/m/m.0/ffn/ffn.0/act/Mul_output_0: float16/model.9/m/m.0/ffn/ffn.1/conv/Conv_output_0: float16/model.9/cv2/act/Mul_output_0: float16/model.10/conv/conv/Conv_output_0: float16/model.10/conv/act/Mul_output_0: float16/model.10/pool/GlobalAveragePool_2conv_0: float16/model.10/pool/GlobalAveragePool_output_0: float16/model.10/linear/Gemm_output_0_conv: float16
quantize_parameters:images:qtype: asymmetric_quantizedqmethod: layerdtype: float32min:-   0.0max:-   255.0scale: []zero_point: []ori_min:-   0.0ori_max:-   255.0...

其中,custom_quatize_layers是一个自定义量化tensor字典,用户可以将tensor名和相应的量化类型添加到该字典中,即可实现将该tensor作为输出的层的运算类型改为指定的运算类型。上面的文件是我的rknn导出的cfg文件,可以看出custom_quatize_layers已经列了一些优化层了。
quantize_parameters:是模型中每个tensor的量化参数,每一个tensor都是一个字典,每个字典的key为tensor的名,字典的value为量化参数,如果没有经过量化,dtype值为float16

4.3.3 修改第一步生成的量化配置文件(.quantization.cfg)
为了测试一下混合量化,我自己修改了一下我的cfg文件,在上一步量化精度分析中,下面两层的entire和single误差差值有一点点大

[exSwish] /model.4/cv1/act/Mul_output_0                          0.999917  0.999983       
[Split] /model.4/Split_output_0                                  			0.999907  0.999983

因此修改yolov11n-cls.quatization.cfg文件如下
【注】 custom_quantize_layers格式问题,官方文档给的是custom_quantize_layers:{x:float16, x2:float16},但是我这边会报错,改成YAML格式的就好了,不晓得为啥。YAML不需要{},也不需要,作为分割,只要缩进做好就可,详细请参考下述代码

custom_quantize_layers:/model.4/cv1/act/Mul_output_0:float16/model.4/Split_output_0:float16# 将/model.4/cv1/act/Mul_output_0,/model.4/Split_output_0设置为float16,即不进行量化quantize_parameters:images:qtype: asymmetric_quantizedqmethod: layerdtype: float32min:-   0.0max:-   255.0scale: []zero_point: []ori_min:-   0.0ori_max:-   255.0/model.0/conv/Conv_output_0:qtype: asymmetric_quantizedqmethod: layerdtype: int8min:-   -15024.08984375max:-   9862.2978515625scale:-   97.59367723651961zero_point:-   26ori_min:-   -15024.08984375ori_max:-   9862.2978515625

4.3.4 生成新的RKNN模型,hybrid_quantization_step2()
步骤为:

  • 实例化RKNN对象
  • 调用hybrid_quantization_step2()
  • 调用accuracy_analysis()再次评估模型,验证混合量化效果
  • 导出RKNN模型
  • 释放RKNN模型
# 混合量化前
[exSwish] /model.4/cv1/act/Mul_output_0                          0.999917  0.999983       
[Split] /model.4/Split_output_0                                  0.999907  0.999983# 混合量化后
[exSwish] /model.4/cv1/act/Mul_output_0                          0.999791  1.000000       
[Split] /model.4/Split_output_0                                  0.999786  1.000000 

五、模型部署

待更新

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

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

相关文章

重构研发效能:项目管理引领软件工厂迈向智能化

1.项目管理智能化&#xff0c;激活软件工厂新引擎 在高速发展的软件开发时代&#xff0c;企业如何高效管理多个项目、协调团队合作、优化资源配置&#xff0c;已成为推动技术进步的关键。尤其是在多任务、多项目并行的复杂环境下&#xff0c;智能项目组合管理工具正成为软件工…

小米汽车二期工厂下月将竣工,产能提升助力市场拓展

在新能源汽车市场竞争日益激烈的当下&#xff0c;小米汽车传来重要进展消息。据多方信息显示&#xff0c;小米汽车二期工厂下月即将竣工&#xff0c;这一关键节点的到来&#xff0c;有望为小米汽车的产能提升与市场布局带来重大突破。​ 小米汽车二期工厂位于北京亦庄&#xff…

Python 爬虫实战:电竞比赛直播数据实时抓取与可视化分析

一、引言 在电竞行业快速发展的今天,电竞比赛直播数据成为了电竞爱好者、分析师和商业机构关注的焦点。实时抓取电竞比赛直播数据并进行分析,不仅可以帮助观众更好地理解比赛,还能为战队战术优化、选手表现评估以及赛事运营提供重要参考。 本文将详细介绍如何使用Python爬…

零基础设计模式——创建型模式 - 生成器模式

第二部分&#xff1a;创建型模式 - 生成器模式 (Builder Pattern) 前面我们学习了单例、工厂方法和抽象工厂模式&#xff0c;它们都关注如何创建对象。生成器模式&#xff08;也常被称为建造者模式&#xff09;是另一种创建型模式&#xff0c;它专注于将一个复杂对象的构建过程…

Debezium快照事件监听器系统设计

Debezium快照事件监听器系统设计 1. 系统概述 1.1 设计目标 为 Debezium 的快照过程提供可扩展的事件监听机制允许外部系统在快照过程中执行自定义逻辑提供线程安全的事件分发机制确保监听器的异常不会影响主快照流程1.2 核心功能 表快照开始事件监听表快照完成事件监听行数据…

手术机器人行业新趋势:Kinova多机械臂协同系统如何突破复杂场景适应性瓶颈?

机器人手术历经多阶段技术演进&#xff0c;已成为现代医疗重要方向。其需求增长源于医疗机构对高精度低风险手术方案的需求、微创手术普及及技术进步带来的复杂场景适应性提升。Kinova 轻型机械臂凭借模块化设计与即插即用功能&#xff0c;可快速适配不同手术环境&#xff0c;为…

力扣面试150题-- 二叉树展开为链表

Day 46 题目描述 思路 初次做法&#xff1a;由于我直接考虑O&#xff08;1&#xff09;级别的空间复杂度&#xff0c;于是采取了以下做法&#xff1a; 接下来的内容就是递归函数如果该节点为空&#xff0c;就返回null将此时的current作为头节点&#xff0c;left和right作为孩…

【Python】开发工具uv

文章目录 1. uv install1.1 下载安装脚本来安装1.2 使用pipx安装uv1.3 补充 2. 考虑在离线系统上安装uv2.1 下载并上传安装包2.2 用户级安装uv&#xff08;~/.local/bin/&#xff09;2.3 补充 3. uv 管理Python解释器4. uv 管理依赖5. uv运行代码5.1 uv不在项目下执行脚本5.2 u…

zabbix批量主机维护脚本兼容性更新

最近做新老版本zabbix监控主机迁移发现zabbix6.0后api安全有了效大升级&#xff0c;批量主机维护脚本出现认证兼容性问题&#xff0c;以下为脚本更新token支持&#xff1a;在这里插入代码片&#xff1a; # /usr/bin/env python3 # -*- coding:utf-8 -*- import requests impor…

Java中static关键字深度解析:从入门到高阶实战

Java中static关键字深度解析&#xff1a;从入门到高阶实战 目录 static的本质与核心特性静态变量 vs 实例变量&#xff1a;底层对比静态方法的设计哲学与应用场景高级用法&#xff1a;突破常规的static技巧 4.1 静态代码块&#xff1a;类加载的“初始化引擎”4.2 静态内部类&…

基于RT-Thread的STM32F4开发第五讲——软件模拟I2C

文章目录 前言一、RT-Thread工程创建二、AT24C02三、函数编写1.I2C_soft.c2.I2C_soft.h3.main.h 四、效果展示五、资源分享总结 前言 本章是基于RT-Thread studio实现软件模拟I2C&#xff0c;开发板是正点原子的STM32F4探索者&#xff0c;使用的RT-Thread驱动是5.1.0&#xff0…

49、c# 能⽤foreach 遍历访问的对象需满足什么条件?

在 C# 中&#xff0c;要使用 foreach 循环遍历一个对象&#xff0c;该对象必须满足以下条件之一&#xff1a; 1. 实现 IEnumerable 或 IEnumerable 接口 非泛型版本&#xff1a;System.Collections.IEnumerable public class MyCollection : IEnumerable {private int[] _da…

推客小程序系统开发:全栈式技术解决方案与行业赋能实践​

​ 在数字化营销深度渗透各行业的当下&#xff0c;传统推广模式已难以满足企业精细化运营与高效获客的需求。专业的推客小程序系统凭借其强大的裂变传播能力与灵活的推广机制&#xff0c;成为企业构建私域流量池、提升推广效能的核心工具。我们基于多年技术沉淀与行业洞察&…

WPF布局系统详解:掌握界面设计的核心艺术

掌握界面设计的核心艺术 1. WPF布局系统概述2. Grid布局详解2.1 基本行列定义2.2 单元格定位与跨行跨列 3. StackPanel布局4. DockPanel布局5. WrapPanel与Canvas5.1 WrapPanel自动换行布局 5. Canvas绝对定位6. 布局嵌套与综合应用7. 布局性能优化8. 响应式布局技巧9. 实战&am…

labview实现LED流水灯的第一种方法

目的&#xff1a;写一个跑马灯程序&#xff0c;7个灯从左到右不停的轮流点亮&#xff0c;闪烁间隔由滑动条调节。 一、方法1&#xff1a;使用顺序结构 使用顺序结构&#xff0c;平铺式顺序结构与创建局部变量实现LED流水灯 具体步骤如下&#xff1a; 第一步&#xff0c;选择…

uniapp如何设置uni.request可变请求ip地址

文章目录 简介方法一&#xff1a;直接在请求URL中嵌入变量方法二&#xff1a;使用全局变量方法三&#xff1a;使用环境变量方法四&#xff1a;服务端配置方法五&#xff1a;使用配置文件&#xff08;如config.js&#xff09;:总结 简介 在uni-app中&#xff0c;uni.request 用…

深度学习篇---LSTMADF轨迹预测

文章目录 前言LSTM 轨迹预测原理应用在行人轨迹预测方面在自动驾驶车辆的轨迹预测中优点缺点APF 轨迹预测原理应用在船舶运动规划在无人驾驶车辆避障轨迹跟踪优点缺点示例代码前言 本文简单介绍LSTM(长短期记忆网络)和ADF(人工势场法)这两种不同的轨迹预测方法。 LSTM 轨迹…

python实现Web请求与响应

目录 一&#xff1a;什么是Web请求与响应&#xff1f; 1&#xff1a;Web请求 2&#xff1a;Web响应 3&#xff1a;HTTP协议概述 4&#xff1a;常见的HTTP状态码包括&#xff1a; 二&#xff1a;python的requests库 1&#xff1a;安装requests库 2&#xff1a;发送GET请…

Unity使用sherpa-onnx实现说话人识别

网友软绵绵的面包人推荐&#xff0c;模型3dspeaker_speech_eres2net_base_200k_sv_zh-cn_16k-common.onnx的效果比3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx要好 具体代码 using System; using System.Collections.Generic; using System.IO; using Sherpa…

ElasticSearch-集群

本篇文章依据ElasticSearch权威指南进行实操和记录 1&#xff0c;空集群 即不包含任何节点的集群 集群大多数分为两类&#xff0c;主节点和数据节点 主节点 职责&#xff1a;主节点负责管理集群的状态&#xff0c;例如分配分片、添加和删除节点、监控节点故障等。它们不直接…