【ncnn android】算法移植(六)——onnx2ncnn源码阅读理解/设计思路

本文主要是介绍【ncnn android】算法移植(六)——onnx2ncnn源码阅读理解/设计思路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇写道:onnx2ncnn的时候,不支持sigmoid,upsample层,于是想着阅读onnx2ncnn的源码。目的:

  • 理解ncnn中onnx2ncnn的主要流程
  • 自定义upsample层(最高要求)

1. 相关资料

  1. Open Neural Network Exchange - ONNX ,onnx的文档
  2. https://github.com/Tencent/ncnn,注意ncnn的不同版本代码是不一样,这里以20180704为准。

2. 主要流程

2.1 ncnn.param保存网络结构参数的格式

2.2 onnx关键api

  1. graph
    GraphProto: graph定义了模型的计算逻辑以及带有参数的node节点,组成一个有向图结构;
    const onnx::GraphProto& graph = model.graph();
    关键属性
    在这里插入图片描述
  • initializer:好像是预训练的权重
  1. node
    NodeProto: 网络有向图的各个节点OP的结构,通常称为层,例如conv,relu层;
    const onnx::NodeProto& node = graph.node(i);
    关键属性
    在这里插入图片描述

  2. attribute
    AttributeProto:各OP的参数,通过该结构访问,例如:conv层的stride,dilation等;
    const onnx::AttributeProto& attr = node.attribute(i);
    在这里插入图片描述

  3. tensor
    TensorProto: 序列化的tensor value,一般weight,bias等常量均保存为该种结构;

// batchnorm
const onnx::TensorProto& scale = weights[node.input(1)];
const onnx::TensorProto& B = weights[node.input(2)];
const onnx::TensorProto& mean = weights[node.input(3)];
const onnx::TensorProto& var = weights[node.input(4)];

一些疑问

  • node.attribute怎么确定?比如conv,batchnorm有不同的参数
    猜想: 在pytorch2onnx中是不是又具体的定义或代码?

  • 比如batchnorm又多个预训练权重的保存顺序
    猜想: 还是在pytorch2onnx中定义的

4. 一些例子

主要分为两类,无结构参数,如batchnorm,直接保存到bin文件中(注意各个参数的顺序);第二类,有结构参数,无预训练权重。就需要将结构参数保存到ncnn.param网络结构参数中。

4.1 batchnorm

float epsilon = get_node_attr_f(node, "epsilon", 1e-5f);const onnx::TensorProto& scale = weights[node.input(1)];
const onnx::TensorProto& B = weights[node.input(2)];
const onnx::TensorProto& mean = weights[node.input(3)];
const onnx::TensorProto& var = weights[node.input(4)];int channels = get_tensor_proto_data_size(scale);fprintf(pp, " 0=%d", channels);		// batchnorm的通道数fwrite_tensor_proto_data(scale, bp);	// batchnorm的缩放变量
fwrite_tensor_proto_data(mean, bp);		// 均值

4.2 pooling

pooling层是没有预训练的参数,但是有很多类型(maxpool,averagepool),和网络参数(kernel_size, pads)等。

std::string auto_pad = get_node_attr_s(node, "auto_pad");//TODO
std::vector<int> kernel_shape = get_node_attr_ai(node, "kernel_shape");
std::vector<int> strides = get_node_attr_ai(node, "strides");
std::vector<int> pads = get_node_attr_ai(node, "pads");int pool = op == "AveragePool" ? 1 : 0;
int pad_mode = 1;if (auto_pad == "SAME_LOWER" || auto_pad == "SAME_UPPER")
{
// TODO
pad_mode = 2;
}fprintf(pp, " 0=%d", pool);if (kernel_shape.size() == 1) {
fprintf(pp, " 1=%d", kernel_shape[0]);
} else if (kernel_shape.size() == 2) {
fprintf(pp, " 1=%d", kernel_shape[1]);
fprintf(pp, " 11=%d", kernel_shape[0]);
}if (strides.size() == 1) {
fprintf(pp, " 2=%d", strides[0]);
} else if (strides.size() == 2) {
fprintf(pp, " 2=%d", strides[1]);
fprintf(pp, " 12=%d", strides[0]);
}if (pads.size() == 1) {
fprintf(pp, " 3=%d", pads[0]);
} else if (pads.size() == 2) {
fprintf(pp, " 3=%d", pads[1]);
fprintf(pp, " 13=%d", pads[0]);
} else if (pads.size() == 4) {
fprintf(pp, " 3=%d", pads[1]);
fprintf(pp, " 13=%d", pads[0]);
fprintf(pp, " 14=%d", pads[3]);
fprintf(pp, " 15=%d", pads[2]);
}fprintf(pp, " 5=%d", pad_mode);

reference

  1. https://blog.csdn.net/SilentOB/article/details/102863944

这篇关于【ncnn android】算法移植(六)——onnx2ncnn源码阅读理解/设计思路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1056867

相关文章

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一