【onnx模型转kmodel】记录和踩坑——nncase-v1.9使用

最近几天一直在找相关资料,坑太多,也可能我菜的成分更多一点吧!记录下来,以观后用;
在这里插入图片描述

背景

  1. 我手里有一个正点原子的K210的开发板;

  2. 刚刚安装了wsl2下的ubuntu22.04

  3. 我手里有正点原子的源码,但是源码中只有输出好的kmodel模型文件,我并不知道kmodel怎么来的,由此疑问;
    在这里插入图片描述

  4. 所以我想尝试用Pyttorch搞个简单的模型跑一下MNIST数据集,然后放进K210里面运行,补充上面的疑问之处;

  5. 了解到共有如下步骤:模型训练——>导出"model.pth"——>“model.onnx”——>“model.kmodel”——>编译产物"xxx.bin"——>烧录——>成功运行;

  6. 然后我成功的在"model.onnx"——>"model.kmodel"卡壳了;

需求

  1. 准备可以转换的onnx模型文件
  2. 准备转换所需的软件和脚本
  3. 修改和使用转换所需的脚步
  4. 执行onnx转kmodel
  5. 编译烧录之后可以成功运行

步骤

  1. 我的设备是k210的,根据nncase官网所说,nncase2.x版本不支持,所以我选择nncase1.9;
  2. 下载和安装时依据我ubuntu的python版本3.10选择如下:
# 下载nncase
root@2b11cc15c7f8:/mnt# wget -P https://github.com/kendryte/nncase/releases/download/v1.9.0/nncase-1.9.0.20230322-cp310-cp310-manylinux_2_24_x86_64.whl
# 安装nncase
root@2b11cc15c7f8:/mnt# pip3 install nncase-1.9.0.20230322-cp310-cp310-manylinux_2_24_x86_64.whl

在这里插入图片描述
3. 准备onnx模型

def pth_to_onnx():# 加载模型model = OptimizedMobileNetV1()model.load_state_dict(torch.load('./to_kmodel_test/demo_model.pth'))# 模型放到cpu上model = model.to(device)                            model.eval()# 模型输入shapeinput_shape = (1, 1, 28, 28)input_data = torch.randn(input_shape).to(device)# 模型转onnx,这里注意1.x的nncase不支持动态shape,不能使用dynamic_axes,否则影响转换kmodeltorch.onnx.export(model, input_data, './to_kmodel_test/demo_model.onnx',do_constant_folding=True,)  # 是否执行常量折叠优化#   input_names=["input"],  # 输入名#   output_names=["output"],  # 输出名#   dynamic_axes={"input": {0: "batch_size"},  # 批处理变量#                 "output": {0: "batch_size"}})# 加载并检查模型model_onnx = onnx.load('./to_kmodel_test/demo_model.onnx')onnx.checker.check_model(model_onnx)print(onnx.helper.printable_graph(model_onnx.graph))# 使用onnxsim进行模型精简model_simp, check = simplify(model_onnx)assert check, "Simplified ONNX model could not be validated"onnx.save(model_simp, './to_kmodel_test/demo_model.onnx')print("model to onnx done!")
  1. 安排转换脚本
    我是从 这里 找到的,这里我重命名为onnx_to_kmodel_copy.py
    以下代码我只修改了cpl_opt.input_shape = [1, 3, 224, 224]为我的模型输入shapecpl_opt.input_shape = [1, 1, 28, 28]
import argparse
import os
import sys
from pathlib import Pathimport cv2
import nncase
import numpy as np
print(os.getpid())def preproc(img, input_size, transpose=True):if len(img.shape) == 3:padded_img = np.ones((input_size[0], input_size[1], 3), dtype=np.uint8) * 114else:padded_img = np.ones(input_size, dtype=np.uint8) * 114r = min(input_size[0] / img.shape[0], input_size[1] / img.shape[1])resized_img = cv2.resize(img,(int(img.shape[1] * r), int(img.shape[0] * r)),interpolation=cv2.INTER_LINEAR,).astype(np.uint8)padded_img[: int(img.shape[0] * r), : int(img.shape[1] * r)] = resized_imgpadded_img = cv2.cvtColor(padded_img, cv2.COLOR_BGR2RGB)if transpose:padded_img = padded_img.transpose((2, 0, 1))padded_img = np.ascontiguousarray(padded_img)return padded_img, rdef read_images(imgs_dir: str, test_size: list):imgs_dir = Path(imgs_dir)imgs = []for p in imgs_dir.iterdir():img = cv2.imread(str(p))img, _ = preproc(img, test_size, True)  # img [h,w,c] rgb,imgs.append(img)imgs = np.stack(imgs)return len(imgs), imgs.tobytes()def main(onnx: str, kmodel: str, target: str, method: str, imgs_dir: str, test_size: list, legacy: bool, no_preprocess: bool):cpl_opt = nncase.CompileOptions()cpl_opt.preprocess = not no_preprocess# (x - mean) / scaleif legacy:cpl_opt.swapRB = False  # legacy use RGB cpl_opt.input_range = [0, 1]cpl_opt.mean = [0.485, 0.456, 0.406]cpl_opt.std = [0.229, 0.224, 0.225]else:cpl_opt.swapRB = True  # new model use BGR cpl_opt.input_range = [0, 255]cpl_opt.mean = [0, 0, 0]cpl_opt.std = [1, 1, 1]cpl_opt.target = target  # cpu , k210, k510!cpl_opt.input_type = 'uint8'cpl_opt.input_layout = 'NCHW'# cpl_opt.input_shape = [1, 3, 224, 224]cpl_opt.input_shape = [1, 1, 28, 28]cpl_opt.quant_type = 'uint8'  # uint8 or int8compiler = nncase.Compiler(cpl_opt)with open(onnx, 'rb') as f:imp_opt = nncase.ImportOptions()compiler.import_onnx(f.read(), imp_opt)# ptqif imgs_dir is not None:ptq_opt = nncase.PTQTensorOptions()ptq_opt.calibrate_method = methodptq_opt.samples_count, tensor_data = read_images(imgs_dir, test_size)ptq_opt.set_tensor_data(tensor_data)compiler.use_ptq(ptq_opt)compiler.compile()kmodel_bytes = compiler.gencode_tobytes()with open(kmodel, 'wb') as of:of.write(kmodel_bytes)of.flush()if __name__ == '__main__':parser = argparse.ArgumentParser("YOLOX Compile Demo!")parser.add_argument('onnx', default='model/yolox_nano_224_new.onnx', help='model path')parser.add_argument('kmodel', default='yolox_nano_224_new.kmodel', help='bin path')parser.add_argument('--target', default='cpu',choices=['cpu', 'k210', 'k510'], help='compile target')parser.add_argument('--method', default='no_clip',choices=['no_clip', 'l2', 'kld_m0', 'kld_m1', 'kld_m2', 'cdf'],help='calibrate method')parser.add_argument('--test_size', default=[224, 224],nargs='+', help='test size')parser.add_argument("--imgs_dir", default=None, help="images dir")parser.add_argument("--legacy", default=False,action="store_true", help="To be compatible with older versions")parser.add_argument("--no_preprocess", default=False,action="store_true", help="disable nncase preprocess for debug")args = parser.parse_args()main(args.onnx, args.kmodel, args.target, args.method, args.imgs_dir,args.test_size, args.legacy, args.no_preprocess)
  1. 执行onnx转换kmodel
root@2b11cc15c7f8: python3 ./to_kmodel_test/onnx_to_kmodel_copy.py ./to_kmodel_test/demo_model.onnx ./to_kmodel_test/demo_model.kmodel --legacy --target=k210
# 以下为执行成功输出
16303
1. Import graph...
1.1 Pre-process...|Dequantize:|Normalize:
2. Optimize target independent...
3. Optimize target dependent...
5. Optimize target dependent after quantization...
6. Optimize modules...
7.1. Merge module regions...
7.2. Optimize buffer fusion...
7.3. Optimize target dependent after buffer fusion...
8. Generate code...SUMMARY
INPUTS

成功后如下:
在这里插入图片描述

  1. 编译时需要用v1.9版本的nncaseruntime替换掉原来版本的,保持版本对齐才行,否则编译成功后运行可能出错
# nncaseruntime运行时库
root@2b11cc15c7f8:/mnt# wget https://github.com/kendryte/nncase/releases/download/v1.9.0/nncaseruntime-riscv64-none-k210.zip

替换路径:

kendryte-standalone-sdk/lib/nncase/v1/

删除该路径下的
在这里插入图片描述
将解压nncaseruntime-riscv64-none-k210.zip后的文件放进去就可以编译了

探索过程中遇到的问题

  1. 找不到转换的可用脚本 or 可用命令,一开始看网上大佬2022年的博客用到的nncase都是0.5左右版本的,用到的是ncc命令,更有大佬直接下源码编译,好吧我菜,看官网的使用说明,提供的程序试了有问题,毕竟程序可能是针对2.x版本的,而我的是1.9,最后才在https://github.com/kendryte/nncase/blob/v1.9.0/examples/下找到了yolox的例子,看了 readme ,yolox目录下的model目录有yolox_nano_224.onnx文件,我就尝试了python tools/compile.py model/yolox_nano_224.onnx yolox_nano_224.kmodel --legacy发现可以,这个过程断断续续花了我3天吧,苦逼啊;
  2. 使用脚本进行onnx转kmodel的时候,死活提示缺少xx shape信息,尝试把模型换成全连接的没问题,

在这里插入图片描述后穷尽手段后加了nncase 的QQ群,问了专业人士,好,结论如下:

1.x的nncase不支持动态shape,不能使用dynamic_axes,否则影响转换kmodel
  1. 终于烧录好,运行时却提示失败,G…,要崩溃了呀,不想玩了,我的模型才100多k,编译后的bin也就1M+
[..m/runtime_module.cpp:65 (shape_reg)] id < shape_regs_.size() = false (bool)
error: Result too large

还好有前人踩坑,大佬回答,一句话我就秒懂,发现编译时需要用v1.9版本的nncaseruntime替换掉原来版本的,保持版本对齐才行
https://github.com/kendryte/kendryte-standalone-sdk/issues/133

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

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

相关文章

项目管理监控难题解析:为何监控至关重要

项目管理中的监控环节常常被视为一项艰巨的任务&#xff0c;但它却是确保项目成功的关键所在。为何监控在项目管理中如此重要呢&#xff1f;让我们一同深入解析这个难题。 一、目前项目管理监控存在的问题 在项目管理的实践中&#xff0c;监控环节常常暴露出一系列问题&#x…

西门子S7-SMART运动控制向导

打开“运动控制”向导&#xff0c;“工具”->“向导”->“运动控制” 图 1.打开“运动控制”向导 选择需要配置的轴 图 2.选择需要配置的轴 为所选择的轴命名 图 3.为所选择的轴命名 输入系统的测量系统&#xff08;“工程量”或者“脉冲数/转”&#xff…

u_boot内核编译-生成uImage

内核编译 顶层目录&#xff0c;都在这个目录下进行操作 这是我们芯片的默认配置文件 第一步 拷贝一个默认的配置 以下两张是def文件内容 第二步 &#xff1a;打开可视化界面&#xff0c;前面的* 需要用空格点击两下&#xff0c;不改变原设置&#xff0c;大那是需要进行编辑操…

PDF全能免费转换 3.15 | 多功能PDF处理工具

主打就是免费好用&#xff01;1. PDF转Word/PPT/Excel/txt、图片等&#xff1b;2. PDF压缩、合并&#xff1b;3. 多图合并成长图、合并成PDF&#xff1b;4. 身份证扫描、文件扫描、证件扫描等&#xff1b;5. 证件照换底色&#xff1b;6. 热门tab页&#xff1b;7. 美化照片。 大…

【LLM论文日更】| BGE-M3E embedding模型

论文&#xff1a;https://arxiv.org/pdf/2402.03216代码&#xff1a;GitHub - FlagOpen/FlagEmbedding: Retrieval and Retrieval-augmented LLMs机构&#xff1a;BAAI领域&#xff1a;embedding model发表&#xff1a; ​ 研究背景 研究问题&#xff1a;这篇文章要解决的问…

(JAVA)熟悉队列的进阶结构 - 优先队列

1. 优先队列 ​ 普通队列是一种先进先出的数据结构&#xff0c;元素在队列尾追加&#xff0c;而从队列头删除。 ​ 在某些情况下&#xff0c;我们可能需要找出队列中的最大值或者最小值&#xff0c;例如使用一个队列保存计算机的任务&#xff0c;一般情况下计算机的任务都是有…

pytest框架之fixture测试夹具详解

前言 大家下午好呀&#xff0c;今天呢来和大家唠唠pytest中的fixtures夹具的详解&#xff0c;废话就不多说了咱们直接进入主题哈。 一、fixture的优势 ​ pytest框架的fixture测试夹具就相当于unittest框架的setup、teardown&#xff0c;但相对之下它的功能更加强大和灵活。 …

谁说电商选品找货源没有捷径,只要你用对工具!

最近跟很多同行聊&#xff0c;都在抱怨选品难的问题&#xff0c;都说7分靠选品&#xff0c;3分靠运营&#xff0c;对于选品来说&#xff0c;并没有捷径可走&#xff0c;但其实是有很多不同的角度的。 现在市面上大部分开发做的选品&#xff0c;“选品方法”或“产品分析方法”…

【含文档】基于Springboot+Android的校园论坛系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

前端省市区组件

官网 Element UI 级联 中国省市区数据. Latest version: 5.0.2, last published: 2 years ago. Start using element-china-area-data in your project by running npm i element-china-area-data. There are 114 other projects in the npm registry using element-china-are…

SpringBoot开发——SpringSecurity安全框架17个业务场景案例(三)

文章目录 一、Spring Security 常用应用场景介绍二、Spring Security场景案例12 表达式支持(Expression-Based)12.1 Spring Security 配置12.2 业务逻辑代码12.3 控制器13、安全上下文(Security Context)13.1 Spring Security 配置13.2 业务逻辑代码13.3 控制器14、安全过滤…

Python入门笔记(四)

文章目录 第九章 集合set9.1 创建集合&#xff1a;set()、集合生成式9.2 集合性质9.3 一些函数&#xff1a;issubset()、issuperset()、isdisjoint()9.4 集合增加元素&#xff1a;add()、update()9.5 集合删除元素&#xff1a;remove()、discard()、pop()、clear()9.6 创建不能…

用IntStream生成0到n的流,并找出不在numSet中的数字列表

这是用IntStream生成0到n的流&#xff0c;并找出不在numSet中的数字-CSDN博客的升级版 给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 先看这题低…

数据结构与算法——Java实现 32.堆

人的想法和感受是会随着时间的认知改变而改变&#xff0c; 原来你笃定不会变的事&#xff0c;也会在最后一刻变得释然 —— 24.10.10 堆 堆是基于二叉树实现的数据结构 大顶堆每个分支的上一个节点的权值要大于它的孩子节点 小顶堆每个分支的上一个节点的权值要小于它的孩子…

Linux系统通过编辑crontab来设置定时任务---定时关机

在Linux系统中&#xff0c;crontab 是用来设置周期性被执行的指令的守护进程。通过编辑 crontab&#xff0c;您可以安排定时任务&#xff0c;比如定时关机、定时备份文件、定时运行脚本等。以下是如何编辑 crontab 来设置定时任务的步骤&#xff1a; 打开终端&#xff1a;您可以…

25.第二阶段x86游戏实战2-背包属性补充

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

k8s 1.28.2 集群部署 MinIO 分布式存储

文章目录 [toc]MinIO 介绍MinIO 生产硬件要求MinIO 存储要求MinIO 内存要求MinIO 网络要求MinIO 部署架构分布式 MinIO复制的 MinIO 部署 MinIO创建目录节点打标签创建 namespace创建 pv创建 MinIO配置 ingress问题记录通过代理服务器访问 MinIO 的 Object Browser 界面一直显示…

免费获取的8个SVG图标库,轻松下载与复制!

SVG图标相比传统的JPG、PNG图标具有诸多优势&#xff0c;适用于各种类型的图像&#xff0c;不仅能在不同尺寸下保持清晰度&#xff0c;还具备高度压缩性和轻量特性&#xff0c;支持静态和动态效果。因此&#xff0c;SVG格式在网页设计中往往是优选。尽管如今有很多免费的图标库…

微信小程序-APP-软件开发

微信小程序开发&#xff0c;作为当下移动互联网领域的一股强劲势力&#xff0c;正以其便捷性、轻量化及高用户粘性的特点&#xff0c;深刻改变着我们的生活与工作方式。它不仅为企业和个人开发者提供了一个全新的服务入口&#xff0c;更极大地拓宽了商业应用的边界。 在微信小…

python+request+unittest+ddt自动化框架

参考资料&#xff1a; 用户中心 - 博客园 抓包模拟器笔记 肖sir__接口自动化pythonrequestddt&#xff08;模版&#xff09; - xiaolehua - 博客园 pythonrequestunittestddt自动化框架 博文阅读密码验证 - 博客园 肖sir__python之模块configparser - xiaolehua - 博客园 c…