yolov5 v7.0转ncnn时问题解决

news/2024/7/10 22:41:02 标签: YOLO, ncnn, onnx2ncnn

yolov5 v7.0转ncnn时遇到很多问题,ncnn版本20231027以下仅做记录:

1.通过官方代码,export.py 转onnx,指定–dynamic --simplify参数

2.编译并安装ncnn,通过onnx2ncnn将onnx转化为ncnn.bin和ncnn.param

3.加载ncnn模型(该部分坑很多)

直接加载,构造输入,获取输出,直接挂掉了,经过排查发现问题,如下图:

在这里插入图片描述

  通过节点输出,发现当获取到Slice算子时,输出错误,因此初步判定Slice算子有问题,通过文档查看,发现ncnn中Slice的参数1=3(这里的1是axis),由于ncnn最多支持4维度(忽略掉batch,就只剩3维),因此这里的维度越界了,改为1=2就可以正常运行了。

  修改后接着往下运行,又挂掉了,定位到发现是后边的Concate算子报错了,同样也是维度问题,将0=3改为0=2。

  通过netron观察onnx模型,发现yolov5s 7.0中有三个这样的结构,全部按照上述两个操作更改,如下:

在这里插入图片描述

  运行成功,不会报错了

  然而,ncnn模型输出与onnxruntime推理的模型输出不一致,不仅仅是不一致,里边全是-nan,也就是中间某些层的参数一定是出了问题。

  最开始怀疑是推理模型是的问题,可能是fp32使用int8或fp16推理等,通过文档查看,ncnn推理时默认是使用fp32,而且转模型是默认也是fp32,排除这一想法。

  由于最终模型结构没有问题,那么问题肯定是出在模型参数上了,再次通过各个节点的部分结果与onnxruntime对比,在同样输入时,第一层(Convelution)的结果就不对,肯定是权重或偏置不对。

  于是在ncnn/src/lays/convelution.cpp的load_model中添加输出信息,重新编译安装ncnn,运行代码发现卷积层的weight不对,通过查看ncnn.param文件,发现convelution算子的前边还有6个MemoryData,如下图:

在这里插入图片描述

  查阅文档发现ncnn中参数读取是按照顺序,果然卷积层的错误的权重来自391节点,也就是说MemoryData定义有问题,文档中MemoryData的参数有三个,whc,默认值都是0:
在这里插入图片描述

因此也就是说,ncnn读取权重的时候,MemoryData的大小被误认为是0了,所以就没有读取,直接到Convelution了,所以这里将MemoryData的参数补齐(需要对照Metron的参数维度以及这些节点的使用位置),如下图:

在这里插入图片描述

然后重新运行程序,运行成功,贴一张图展示下:

在这里插入图片描述
  总结一下:

  通过这一波操作下来,发现onnx2ncnn这个工具目前还有很多操作需要完善,单个算子可能没问题,但是多个算子的组合可能就有问题(主要原因是不支持更多维度)。

如果模型转换后遇到模型推理失败:

1.获取节点返回值或输出节点维度,定位到出错节点,然后根据出错节点的参数排查问题

如果推理结果和预期不符:

1.由于ncnn输出的结果都是以ncnn::Mat,因此可以根据各个节点输出与onnxruntime对比,从最开始不一致的节点分析,如果ncnn.param参数没问题,那肯定就是权重问题。

2.切记,不要随意删除有权重信息的中间节点,因为ncnn权重加载是按顺序的,如果含有权重信息的参数被删除,后续的算子参数就是错乱。

如果是算子不支持:

1.通过自定义算子,将代码放在ncnn/src/lays中,重新编译

2.通过自定义算子,在代码运行时注册进去


http://www.niftyadmin.cn/n/5140941.html

相关文章

Arduino开发

文章目录 Arduino IDE 的使用1. 使能编译以及烧录的LOG:2. 下载配置3. 下载 Arduino指令程序下载步骤通过下载器下载通过串口下载 关于Arduino IDE工程生成的二进制文件对比Tools-->burn bootloader 和 ArduinoISP例程 的区别自带例程 Arduino IDE 的使用 1. 使…

go-反射

反射是指在程序运行时动态获取程序的类型信息和操作对象的属性和方法的能力。在Go语言中,反射是通过reflect包来实现的。 反射的主要作用是在程序运行时动态地获取类型信息和操作对象的属性和方法,这样就可以在不知道具体类型的情况下对对象进行操作。反…

NI USB9218国产对标51.2 kS/s/ch,2通道C系列通用模拟输入模块

51.2 kS/s/ch,2通道C系列通用模拟输入模块 NI‑9218专为多用途测量而设计。 它使用针对特定测量的适配器提供了对加速度计、供电传感器、全桥和电压测量以及四分之一桥、半桥、60V和电流测量的内置支持。 每个通道可单独选择,因而用户可在各个通道上进行…

Docker dnmp 多版本php安装 php8.2

Laravel9 开发需要用到php8.1以上的版本,而dnmp只支持到php8.0。安装php8.2的步骤如下: 1. 从/services/php80目录复制一份出来,重命名为php82,extensions目录只保留 install.sh 和 install-php-extensions 这两个文件 2. 修改.en…

【MySQL索引与优化篇】数据库设计实操(含ER模型)

数据库设计实操(含ER模型) 文章目录 数据库设计实操(含ER模型)1. ER模型1.1 概述1.2 建模分析1.3 ER 模型的细化1.4 ER 模型图转换成数据表1. 一个实体转换成一个数据库表2. 一个多对多的关系转换成一个数据表3. 通过外键来表达1对…

【毕业设计】基于springboot+vue+ssm的家乡特色推荐系统【源码+LW+PPT】

摘 要 在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括家乡特色推荐的网络应用,在外国家乡特色推荐系统已经是很普遍的方式,不过国内的管理网站可能还处于起步阶段。家乡特色推荐系统采用java技术&am…

docker 存储目录迁移

参考:【Docker专题】WSL镜像包盘符迁移详细笔记 - 掘金 docker迁移 一 默认目录 Windows版本(Windows 10 wsl 2)docker 默认程序安装到c盘,数据存放于 C:\Users\当前用户名\AppData\Local\Docker\wsl\data\ext4.vhdx 这样会导致…

【Java-代码-A02】(00) 通过Java遍历文件夹,快速上手;

前言 【描述】 通过"Java"遍历文件夹下的所有文件,快速上手; 【环境】 系统"Windows",软件"IntelliJ IDEA 2021.1.3(Ultimate Edition)";“Java版本"1.8.0_202”; 实操 【第一步…