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

相关文章

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

CSS3中的字体及相关属性详解

《CSS3中的字体及相关属性详解》:本文主要介绍了CSS3中的字体及相关属性,详细内容请阅读本文,希望能对你有所帮助... 字体网页字体的三个来源:用户机器上安装的字体,放心使用。保存在第三方网站上的字体,例如Typekit和Google,可以link标签链接到你的页面上。保存在你自己Web服务器上的字

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis