ncnn源码阅读(二)----网络模型结构和权重参数的加载

网络模型结构和权重参数的加载

ncnn推理框架中把模型的结构和权重参数分为两个文件进行存储,实现了结构和权重的分离。在xxx.param中存储了模型的结构信息,在xxx.bin中存储了模型的权重信息。xxx.param的文件结构如下:
xxx.param文件结构
layer:描述网络一共有多少层,例如:ReLU、Conv 都叫一个layer;
blob:表示数据节点,例如一个Conv就有一个输入blob和输出blob;

bottom_count:当前层接收输入blob的层个数
top_count:将当前层的输出作为输入blob的层个数

bottom_name:当前层输入数据的生产层名字
blob_name: 消费当前的输出结果的层名字

模型网络结构的加载

在ncnn中,通过重载实现不同格式的加载。最常见也是最容易看懂的加载方式:
通过输入模型结构的文件,来完成模型的加载,具体的重载如下图:
在这里插入图片描述
两个具体关系如下:

int Net::load_param(const char* protopath) {FILE* fp = fopen(protopath, "rb");if (!fp) {std::cout << "error" << std::endl;return -1;}int ret = load_param(fp);fclose(fp);
}

int load_param(FILE* fp)中完成对网络结构的构建,具体的步骤,如下:

  • 读取层数、blob数
  • 逐行读取,层类型和层名字,以及输入blob数据的个数,和将当前层输出作为输入blob的个数
  • 根据层类型得到类型的索引,然后通过该索引得到层实例化的指针;这个地方需要区分内部层和自定义的层;
    • 内部层
    • 自定义层
  • 为当前层设置类型和名字
  • 开始读取bottoms和tops,并构建blob的集合
  • 利用创建的额层实例指针,构建层集合
int Net::load_param(FILE* fp)
{//一、读取层数和blob数int layer_count = 0;int blob_count = 0;fscanf(fp, "%d %d", &layer_count, &blob_count);layers.resize(layer_count);blobs.resize(blob_count);int layer_index = 0;int blob_index = 0;while (!feof(fp)){//二、逐行读取,层类型和层名字,以及输入blob数据的个数,和将当前层输出作为输入blob的个数int nscan = 0;char layer_type[256];char layer_name[256];int bottom_count = 0;int top_count = 0;nscan = fscanf(fp, "%256s %256s %d %d", layer_type, layer_name, &bottom_count, &top_count);if (nscan != 4){continue;}//三、根据层类型得到类型的索引,然后通过该索引得到层实例化的指针;int typeindex = layer_to_index(layer_type);Layer* layer = create_layer(typeindex);if (!layer){typeindex = custom_layer_to_index(layer_type);layer = create_custom_layer(typeindex);}//四、为当前层设置类型和名字layer->type = std::string(layer_type);layer->name = std::string(layer_name);//五、开始读取bottoms和tops,并构建blob的集合layer->bottoms.resize(bottom_count);for (int i=0; i<bottom_count; i++){char bottom_name[256];nscan = fscanf(fp, "%256s", bottom_name);if (nscan != 1){continue;}//根据输入blob的名字,在blob集合中的索引,如果没有找到,就需要构建这个blob//并将构建的blob添加到blob中int bottom_blob_index = find_blob_index_by_name(bottom_name);if (bottom_blob_index == -1){Blob& blob = blobs[blob_index];bottom_blob_index = blob_index;blob.name = std::string(bottom_name);blob_index++;}//在blob集合中找到,将根据索引获取当前的blob实例//然后将当前层作为blob的消费者//在当前层的bottom中添加输入blobd的索引Blob& blob = blobs[bottom_blob_index];blob.consumers.push_back(layer_index);layer->bottoms[i] = bottom_blob_index;}//layer->tops.resize(top_count);for (int i=0; i<top_count; i++){Blob& blob = blobs[blob_index];char blob_name[256];nscan = fscanf(fp, "%256s", blob_name);if (nscan != 1){continue;}blob.name = std::string(blob_name);blob.producer = layer_index;layer->tops[i] = blob_index;blob_index++;}//如果当前层有特殊的参数,则读取特殊的参数int lr = layer->load_param(fp);if (lr != 0){fprintf(stderr, "layer load_param failed\n");continue;}//六、利用创建的额层实例指针,构建层集合layers[layer_index] = layer;layer_index++;}return 0;
}

权重参数的加载

加载模型参数同样通过了一个重载:
在这里插入图片描述
具体的说下int load_model(FILE* fp)

int Net::load_model(FILE* fp)
{// load fileint ret = 0;//遍历所有的层,然后每个层根据自己实现的load_model方法,读取对应的权重参数for (size_t i=0; i<layers.size(); i++){Layer* layer = layers[i];int lret = layer->load_model(fp);if (lret != 0){fprintf(stderr, "layer load_model %d failed\n", (int)i);ret = -1;break;}}return ret;
}

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

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

相关文章

开源防病毒引擎ClamAV

本文软件是应网友 Windows 的要求折腾的&#xff1b; 什么是 ClamAV &#xff1f; ClamAV 是一个开源 ( GPLv2 ) 反病毒工具包&#xff0c;专为邮件网关上的电子邮件扫描而设计。它提供了许多实用程序&#xff0c;包括灵活且可扩展的多线程守护程序、命令行扫描程序和用于自动数…

进程池线程池实现TCP高性能并发通信

进程池线程池实现TCP高性能并发通信 使用进程池与线程池实现并发服务&#xff0c;为多个客户进行接收和发送消息的服务 代码实现 # 导入进程池 from multiprocessing import Pool, cpu_count # 导入线程池 from multiprocessing.pool import ThreadPool from socket import …

Linux操作系统详解

文章目录 引言1. 认识Linux1.1 操作系统概述1.2 认识Linux1.3 虚拟机介绍1.4 远程连接Linux操作系统1.5 WSL1.6 虚拟机快照 2. Linux基础命令2.1 Linux的目录结构2.2 命令入门2.3 目录切换相关命令&#xff08;cd/pwd&#xff09;2.4 相对路径&#xff0c;绝对路径和特殊路径符…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(7 月 4 日论文合集)

文章目录 一、检测相关(15篇)1.1 Artifacts Mapping: Multi-Modal Semantic Mapping for Object Detection and 3D Localization1.2 Shi-NeSS: Detecting Good and Stable Keypoints with a Neural Stability Score1.3 HODINet: High-Order Discrepant Interaction Network for…

centos7安装git及maven

安装git 直接使用yum安装&#xff0c;指令如下&#xff1a; yum install git然后执行如下指令判断是否安装完成&#xff1a; git --version紧接着需要维护git的用户名及邮箱等信息 git config --global user.name "zzy" git config --global user.email "ex…

Spring MVC 程序开发

什么是 Spring MVC&#xff1f; 官⽅对于 Spring MVC 的描述是这样的&#xff1a; Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,”…

Android App的几个核心概念

Application启动 点击桌面图标启动App(如下流程图) 针对以上流程图示&#xff1a; ActivityManagerService#startProcessLocked()Process#start()ActivityThread#main()&#xff0c;入口分析的地方ActivityThread#attach()&#xff0c;这个里面的逻辑很核心 ActivityManagerS…

【Springboot集成Neo4j完整版教程】

&#x1f680; Neo4j &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;C…

python绘制带有误差棒的条形图

文章目录 bar和barh加入误差棒定制误差棒颜色 bar和barh 在matplotlib中&#xff0c;通过bar和barh来绘制条形图&#xff0c;分别表示纵向和横向的条形图。二者的输入数据均主要为高度x和标签height&#xff0c;示例如下 import matplotlib.pyplot as plt import numpy as np…

使用RabbitMQ

使用RabbitMQ 1 Docker安装RabbitMQ 1.1 安装RabbitMQ # 下载含有管理页面的镜像 docker pull rabbitmq:3.8.8-management# 创建容器 # 5672&#xff1a;应用访问端口&#xff1b;15672&#xff1a;控制台Web端口号&#xff1b; docker run -itd \ --namemy-rabbitmq \ --re…

html,css笔记1

这里写目录标题 一、快捷键及基础常识基础框架2.lang语言种类3.字符集4.HTML常用标签4.1标题标签&#xff08;重要&#xff09;4.2段落和换行标签(重要)4.3文本格式化标签 一、快捷键及基础常识 1.快速复制一行 快捷键&#xff1a;shiftalt下箭头 光标定位到要复制的一行 2.…

CAD绘制三维升旗台

首先绘制长方体的底座 用交叉对角线来定位&#xff0c;绘制一个小一点的矩形&#xff0c;用来定位 大概的效果&#xff1a; 沿着矩形的一个角绘制三个长方体&#xff0c;形成护栏 用阵列或者复制等形成四个角的护栏 旋转&#xff0c;换成真实的效果图&#xff1a; 添加一个圆…