C++卷积神经网络实例:tiny_cnn代码详解(11)——层结构容器layers类源码分析

本文主要是介绍C++卷积神经网络实例:tiny_cnn代码详解(11)——层结构容器layers类源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  在这篇博文中我们对tiny_cnn卷积神经网络模型中的最后一个网络结构方面的类——layers做简要分析。

  首先,layers通俗的讲可以被称为是层结构的vector,即层结构容器。由于卷积神经网络是一个多层的网络模型,因此有必要将网络中各个层进行统一管理,这便引出了本篇博文中所要介绍的layers类。layers类是一个vector类型的变量,其中压入的元素就是网络中的各个层模型,这里给出一个简单的结构图,一目了然:

  从上图中可以清晰的看到layers的vector结构,说白了就是一个层结构类的容器,彼此之间通过prev_(指向后一层)和next_(指向前一层)两个指针相联系。接下来开始着重分析layers的内部代码结构。首先给出layers的结构示意图:

  同样我们按照成员变量、成员函数的思路对这个类的结构和代码进行解读。

  一、成员变量

  layers有两个成员变量,一个是vector容器变量,用来保存各个压栈的层结构类;一个是input_layer类型变量,用来保存网络模型中输入层的结构信息:

  这个有两个问题需要强调:

  (1)容器元素的类型。从上图中可以看出,layers_容器中的基本元素类型是layer_base*类型,原因很明确,layer_base是卷积层、下采样层、全连接层等层结构的公共基类,声明成指针形式是为了方便使用前向指针和反向指针进行连接。

  (2)输入层的独特性。这里之所以将输入层单独拿出来作为一个成员变量,主要是考虑到在任何卷积神经网络的网络模型(无论是单层模型还是多层模型)中,输入层都是必不可少的,并且都处于网络模型的最前端。对于这个存在性和位置都已经确定的层成员,这里选择将其放在layers中进行默认添加构造,使得用户在指定层结构模型时无需再一成不变的添加输入层。

  二、构造函数

  layers类内提供了两种功能的构造函数:

  第一个构造函数用于构造单层网络模型,即只有一个输入层(first_是一个input_layer类型变量);第二个构造函数用于按照指定的层类型来构造多层网络模型,构造函数的实现机制主要通过add()和construct()两个函数,有关这两个函数的具体功能稍后介绍。

  三、模型构造方法

  layers在对网络模型执行构造的过程中,主要依赖于add()和construct()这两个构造方法,这里稍作分析。

  3.1 add()函数

  顾名思义,add()函数的作用是将指定的层类型类添加到当前的layers结构体中,类似于vector中的压栈操作(实际上也确实借用了push_back):

  add()函数在执行过程中主要分为两大部分,即建立连接关系和层结构压栈。首先需要调用connect()函数来建立待加入层(new_tail)与已有模型之间的关系。connect()函数是定义在基类layer_base中的成员函数,目的就是建立网络模型中前后两层之间的指针联系:

  在connect函数中,首先针对前后层之间的连接关系进行判断,在连接匹配的情况下,通过“next_ = tail”语句将当前层的下一层指定为tail(新加入的层),再通过“tail->prev_ = this”将新加入的层的前一层指定为当前层。从这种意义上将,connect()的构造方式与指针队列的构造方式很像。

  继续分析add()函数。在通过connect函数建立新加入层与已有模型的最后一层之间的指针联系之后,直接调用push_back将待加入的层结构类压栈即可,完成新层的构造和存储。

  3.2 construct()函数

  construct()函数旨在完成多层模型的构造,包括建立连接和压栈等等,其基本的工作原理就是循环调用add()函数:

  这里同样可以分为两个过程。首先,向layers容器中加入输入层first_,因为对于所有的模型,输入层都是必不可少的,因此与其让用户在每次构建模型时都先在第一个位置写上Input_layer,还不如将这一步放到构造函数内部来自动执行。接下来就循环调用add()函数,将需要添加的层逐个的建连接、压栈、建连接、压栈。

  四、权重操作

  由于layers属于对层结构类的再封装,因此需要提供与各个网络层共有功能相对应的接口,比如说权重操作。这里的权重操作主要包括权重的初始化、重置以及权重更新等操作。这些操作函数一般都是只提供一个接口,具体实现过程中主要还是调用各个类内部的对应的功能函数,比如说权重的初始化和重置:

  再比如说权重的更新update:

  五、属性返回

  由于layers是用户所能接触到的最上层的层结构封装,因此其有必要提供一些属性返回的接口函数,供用户查看网络层的输出以及权重核的具体情况等等,当然这里的接口函数同样作为一个桥梁式的存在,一方面连接用户,一方面调用各个元素类的对应功能函数。除此之外还需要添加一些与整体层结构相关的属性返回函数,来告诉用户这个保存着layer_base的vector实际上有多少层,第一层是什么,最后一层是什么,怎么访问到指定层。

  首先是如何访问第一层和最后一层,这里提供了两个函数head()和tail(),具体实现机制很简单,相信大家一看就懂:

  至于如何访问指定层,tiny_cnn提供两个手段,一是定义at函数,并通过dynamic_cast进行类型转换:

  另一种手段是重载“[]”运算发,类数组形式访问

  以上两种访问方式都是通过索引(index)来完成,比较方便。

  OK,有关层结构容器layers类的源码就先介绍到这里,还有一些补丁式的小函数,也就一两行代码,功能明确,实现简单,这里就不再赘述了。这个系列的博文截止到现在已经将所有与网络层相关的类都介绍完毕,在接下来的博文中将重点根据训练算法和测试算法来对程序进行解读。由于程序在前向/反向传播函数中大量用到了TBB编程相关的知识,我决定专门拿出一段时间来研究一下TBB的相关知识和基本用法,再加上这段时间需要忙论文的事,这个系列的博文可能要暂时停更一周左右的时间,望大家见谅。

 


如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢。


这篇关于C++卷积神经网络实例:tiny_cnn代码详解(11)——层结构容器layers类源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名