[深度学习]卷积神经网络的概念,入门构建(代码实例)

news2024/11/22 15:55:09

# 不再任何人,任何组织的身上倾注任何的感情,或许这就是能活得更开心的办法 

0.写在前面:

卷积神经网络的部分在之前就已经有所接触,这里重新更全面地总结一下关于深度学习中卷积神经网络的部分.并且在这里对如何构建代码,一些新的思想和网络做出一点点补充,同时会持续更新一些注入残差网络等现代的卷积网络部分.

简言之,入门看这篇就行.........

1.关于卷积网络的概念:

在一些图片处理之类的问题中,我们不可避免地会碰到一些环境监测的工作,其实正常来说,神经网络读取的数据肯定是矩阵,张量,为了保证图像的严整性,我们需要把每个像素都抽象化为一个具体的数字,这就会带来两个问题:

1.对于图像数据来说,需要考虑的是一个上下文的环境,换句话说,例如对人物,车辆的识别工作,不可能对像素进行处理.

2.另一个角度来说,我们在之前的多层感知机中使用了展平层来处理三维数据,这样子处理以后不仅不符合逻辑,计算量也很大,因此要引入卷积神经网络的概念.

并且不只是图像,对于一些大预言模型的处理,我们需要对传输数据进行一定的画框,然后分批次进行读取. 另外就是我最近在座的生物信息分析的数据,更需要考虑到其中一个上下文的环境

例如有一段生物信息代码:
ACTUTCCTAA

例如这段生物信息为例,我们在做数据分析的时候不能盲目地转化为[0,1,0,1,1,3....]这样子的数组

比如这段信息,我们倾向于对每条数据划分,在检测某个位点的时候,需要考虑到前后文关系,比如我们考虑第三个碱基C,我们需要传递近来计算的特征则是[ACT].

好吧我得承认这个说法仍然足够抽象,用图形的方式来理解,就显得比较容易了

1.1.什么卷积层:

卷积层的这个卷积,在计算机图形学中的应用同样很广泛,而且概念上也是一样的.

其实严格来说,我们这个操作并不能称之为卷积操作,因为数学论文中的卷积操作需要额外的一个步骤就是倒转卷积核,在这里我们仅仅是对固定的层数和区域做运算而已.

在大一的时候,我们接触过滑动窗口算法,用来进行平滑的操作,,或者就像是我们在ps中进行图像处理的时候,所用到的污点修复工具, 也是一种卷积.

这其实就是卷积神经网络中的一部分,只不过严格来说这个操作被称之为pooling(池化)

首先我们要介绍一下卷积核 / 过滤器  / convolution kernel / filtering

就是一个小型矩阵,深度和被卷积对象匹配(为什么这里说被卷积对象而不是输入,这个和我们后面的一个叫做分离卷积的东西有关,当然这个是后话了)

过滤器是怎么样工作的,或者说卷积的数学原理是什么,差不多就这样,那个小的过滤矩阵被称之为核

然后类似滑动窗口的操作,只不过这次窗口被严格限制在了原本张量范围内,窗口的每个计算,对应着目标中一个数字的输出
(图片其实贴在上面了)

例如在这张图中,涉及到了边缘检测的一个简单示例

很好地展现了一个垂直的边缘检测器,这个检测器也是我们常用的类型了

还有一些其他的核

但是迄今为止,我们说到的东西仅仅止步于数学和图形学,神经网络呢???

别急,核心的数目很多,种类很多,能达到的效果都不一样,如果能检测到更适合我们手中样本的数据,就是训练呗.

比如这样一个9*9大小的卷积核心,我们可以设置参数w1--w9, 后面如果有需要还可以使用bias还有激活函数之类的东西进行处理,紧接着根据参数开始训练,这就是我们的一个核心思路.

1.2.卷积层的相关参数

里我们展示一个比较完整的卷积神经网路的图像.

我们可以看到,现在我们的卷积是在三维上进行处理的,每个核的卷积结果都是一个二维矩阵.

如图所示

而具体的计算方法可以是这样子的

在这种比较正常的卷积操作中,我们设置一些相关的参数,并且将他们的名称作为约定俗成

有关参数
n:输入的长宽度

f:卷积核的长宽

s;卷积运算的移动步长

p:填充的长度(注意这个填充长度,不同的材料中表示的含义不太一样)

num:卷积核的数目,卷积核的数目在一般情况下决定了输出的三维张量的频道数量(频道是深度的另一种称呼)

这是一张纯三维的展示图像,途中我们可以看到这里又不止一个卷积核,每个卷积核都能得到一个结果.这里其实存在一个物理意义,每个卷积核都是提取自己需要的特征,比如A获取的是垂直边缘,B获取的是水平边缘.叠加起来就是我们需要的东西(比如轮廓图)

填充和步长
在进行卷积的时候,可以注意到一个问题,随着卷积的增加,虽然特征提取了,但是输出的长宽是肉眼可见的不断变小的.并且步长也会直接影响输出的因素.

而且,卷积也会导致对于边缘部分的采集不充分,所以对于这种情况,我们的处理方法是在原本的输入基础上,在四周填充长度为p的部分,使得卷积出来的结果大小发生一些变化

如图所示

步长

这里还有一个计算公式,通过这个计算公式我们可以得到关于输入和输出的尺寸的区别

1.3. 什么是池化层

池化层的翻译怎么说呢....汇聚层这个翻译其实更符合语意的

池化层其实个人感觉和卷积没有本质上的区别,都是对局部特征进行提取,然后够获取特征部分,压缩输入,节约计算.或者一些其他的奇奇怪怪的功能.

但是真说计算上的区别,那么就是池化层不需要任何训练参数,比较常用的两个池化核心是最大池化和平均池化. 另外,池化层的特点是,每个池化核心只有一层,这就代表了池化层是不会对输入的通道产生影响,而至少影响尺寸的大小

(另外在这里补充一点通常我们在说有关卷积神经网络的时候,所说的"尺寸"指的是二维尺寸,对于第三维度的高度(我们俗称的Z轴),我们称之为通道数目)

如果说在实际运行代码上的区别,我还记得一个特点就是如果不指定,那么池化层默认自己的步长和核心的尺寸大小一致

如图所示,这个就是池化层中被称之为平均池化层的操作,将自己所在"窗口"内的部分进行加和求平均,剩下最大池化层是干什么应该就不用我多说了.

并且在实际应用中,卷积和池化层中的尺寸计算通常会向下取整,以保持输出结果的整数尺寸

这是因为在卷积和池化操作中,输入特征图的尺寸往往无法被池化窗口或卷积核完全整除。为了保持输出特征图的尺寸与输入特征图的对应关系,并避免信息丢失或产生不连续的特征图,通常会将计算结果向下取整到最接近的整数

1.4,关于CNN的代码简单展示

我们就不使用具体的pytorch的函数和方法来进行过多的展示了,这里直接使用Sequential容器来进行一点简单的展示

# padding如果没有默认为0 ,stride如果不存在默认为1
net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2),  输出结果为[6,27,27]
    nn.Sigmoid(),                               进行sigmoid操作,将范围固定在0-1的范围之中
    nn.AvgPool2d(kernel_size=2, stride=2),      输出结果为[6,13,13](原本计算结果为13.5,但是向下取整)
    nn.Conv2d(6, 16, kernel_size=5),            输出结果为[16,.....]
    nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),      输出结果为[16,.....] 嘛.计算结果差不多就这样不算了
    nn.Flatten(),  #------------------自此开始重新将数据进行展平(如果是大批量数据会保留第一个维度的存在)
    nn.Linear(16 * 5 * 5, 120), 
    nn.Sigmoid(),
    nn.Linear(120, 84), 
    nn.Sigmoid(),
    nn.Linear(84, 10))

2.关于pytorch中的一些实现代码,参数,以及注意问题

2.1关于具体的神经网络层的api

首先说明一下构建各种类型的卷积层的方法

# 2d的卷积层
nn.Conv2d(in_channels, out_channels, kernel_size=?,padding=?,stride=?)

# 2d的最大池化层
nn.MaxPool2d( kernel_size=?,padding=?,stride=?)

# 2d的平均池化层
nn.AvgPool2d( kernel_size=?,padding=?,stride=?)

上面所展示的内容全部都是单一维度的2d,其实还有其他的维度卷积,这里就不加一解释了

里面的参数就不用我多说了 

另外这里要单独说明另一个api:ModuleList

2.2关于神经网络层的初始化

神经网络的初始化这里其实要说明一点,就算我们不进行初始化操作,pytorch也会自动进行一些小范围的初始化操作.不过为减少迭代和训练次数,还是有必要的.

因为上面我们引入了有关于ModuleList的东西,所以对于这个使用方法更新的方式,我们需要一点更新,这个是一个具体案例,负责初始化一个携带有ModuleList的块.

def init_weight(m):
            if type(m)==nn.Linear or type(m)==nn.Conv2d:
                torch.nn.init.constant_(m.bias,0.1)
                torch.nn.init.normal_(m.weight,std=0.01)
            elif type(m)==nn.ModuleList:
                for i,subLayer in enumerate(m):
                    torch.nn.init.constant_(subLayer.bias,0.1)
                    torch.nn.init.normal_(subLayer.weight,std=0.01)
        self.apply(init_weight)

 如图所示(注意,无论是sequential容器构建的神经网络,还是通过class类进行构建的,只要是成功继承了nn.Module的神经网络结构部分, 都可以使用这种apply内置接口来对模型,都可以用这种方式来初始化函数,并且对每个模型都进行操作)

对于携带ModuleList的内部类中,我们需要enmuerate函数遍历的操作,然后对内部进行重新的修整.

2.3需要注意的问题

需要注意的问题就是:(长期补充)

1.ModuleLis虽然也是一种容器,但是它真的只是一个存储容器,因此我们无法通过ModuleList进行直接的先前传播计算

这些块在计算的时候会被认为是注册了的层,所以反向传播是可以正常训练的

但是正向转播的时候,这个容器本身是不能进行任何前向传播计算的,需要单独拆出来进行遍历

至于为什么pytorch总能找到哪些神经网络层参与了计算

底层来说,是反向传播机制. 代码上说, pytorch中特有的跟踪机制吧.....

3.关于一些现代神经网络还有内部的实现

其实关于卷积层和卷积层构建的神经网络,其实和密集层,激活函数本质上没什么区别.

但是随着现代神经网络和科学的发展,无论是神经网络本身还是更多的一些需求,我们都扩展出了一些现代的概念和函数架构,在这里我们会简单展示"VGG","NiN","GoogleNet"这三个块形式的结构,并且会在后面拓展一些关于残差等等的东西.

(1)VGG,以及块级别操作的接口

VGG这个名字感觉好怪每次都读成VCC了,.......

其实VGG块没什么太多好讲的,其实本质就是一个简单的卷积神经网络块,通过参数调整来保证无论是输入还输出部分,都能保证通道数目一致.

代码实例如图所示

def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels,
                                kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
    return nn.Sequential(*layers)

但是这里主要需要解释的就是块级别的网络层,也就是block,这个思想其实就是前向传播实现的,也就是实现了forward接口来实现的结果.至于好处我个人认为有以下两种

  1. 模块化和可复用性:通过将一组层组织成块的形式,可以将网络的结构划分为更小、更易于管理的模块。这种模块化的设计使得网络的构建更加清晰和可复用。每个块都可以被视为一个独立的单元,可以在不同的网络架构中使用,从而提高代码的可重用性。

  2. 实现复杂网络架构:块结构可以用于实现一些复杂的网络架构,如残差网络(ResNet)、Inception 网络、U-Net 等。这些网络往往由多个重复的块组成,通过简单的块结构的组合和堆叠,可以构建出具有强大表达能力的网络架构。

(2)NiN

NiN块(network in network)神经网络,其实说真我自己都没有太好的理解

# NiN和其他的网络有一点小小的区别

# 一般的NiN卷积层是一个普通卷积层,一个池化层,两个1*1但是不改变最终尺寸的卷积层

# 前两个就是正常的卷积操作,最后两个池化层的作用就是增加更多的非线性变换

# 提升特征的可提取度

# 卷积层举例:
def nin_block(in_channels, out_channels, kernel_size, strides, padding):
    return nn.Sequential(
        nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),
        nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())

(3)GoogleNet,以及并行处理,还有inception函数

在进行最后的神经网络计算的时候,我们首先要介绍一个概念,并行操作

其实对于这个操作,其实源自于某一个科研项目(这里指的是我自己),需要处理一个很有特点的数据

一个批次(张量的数据)一共有四个特征,差不多是这个格式

[
[1,2,3,4,5,6,7,8,9,1,2,3,4],[1,2,3,4,5,6,7,8,9,1,2,3,4],
[1,2,3,4,5,6,7,8,9,1,2,3,4],[1,2,3,4,5,6,7,8,9,1,2,3,4]
]

每个特征都有自己的特征,而且科研内容的背景环境是完全不同的,所以我们不能使用2d来进行操作

我们需要实现的核心思路就是

首先 , 遍历得到里面的每一个子模块

然后每个子模块计算输入的一部分(张量高级语法),得到一个单独的输出结果

再把这些单独的输出结果重新拼合到张量,作为下一个输入

首先我有一个自己的处理函数写的比较蠢

for i in range(4):
            output.append(self.Convs1[i](X[:,i:i+1,:].float()))
        X=torch.cat(output,dim=1) #这个dim等于1的压缩机制是啥来着???

通过这种方式,我们尝试实现了最简单的Inception模块

(不过在这里,我们的实现方式是ModuleList模块)

class MyNet(nn.Module):
    def __init__(self):
        super().__init__()

        #创建一个多输入的卷积层
        self.Convs1=nn.ModuleList()
        #内部传入四个卷积层,卷积以后对每一个层的结果是一个[4,9]
        self.Convs1.append(nn.Conv1d(1,1,padding=0,kernel_size=5,stride=1))
        self.Convs1.append(nn.Conv1d(1,1,padding=0,kernel_size=5,stride=1))
        self.Convs1.append(nn.Conv1d(1,1,padding=0,kernel_size=5,stride=1))
        self.Convs1.append(nn.Conv1d(1,1,padding=0,kernel_size=5,stride=1))
        # 13 - x +1=9
        #创建一个多输入的密集层
        self.Convs2=nn.ModuleList()
        #内部传入四个密集层           密集计算以后每一个层的结果都是[4,3]
        self.Convs2.append(nn.Linear(9,3))
        self.Convs2.append(nn.Linear(9,3))
        self.Convs2.append(nn.Linear(9,3))
        self.Convs2.append(nn.Linear(9,3))

        #展平层  [4,3]---->[12]
        self.Flatten=nn.Flatten()
        #最后一个密集层做处理
        self.Linear1=nn.Linear(12,1)
        
        self.init()
   #13 - 5 +c1 = 9
    #向前传播计算逻辑
    def forward(self,X):
        output=[]

        for i in range(4):
            output.append(self.Convs1[i](X[:,i:i+1,:].float()))
        X=torch.cat(output,dim=1) #这个dim等于1的压缩机制是啥来着???

        output=[]
        for i  in range(4):
            output.append(self.Convs2[i](X[:,i:i+1,:].float()))
        X=torch.cat(output,dim=1) #这个dim等于1的压缩机制是啥来着???

        X=self.Flatten(X)

        X=self.Linear1(X)
        return (X)
    
    # 权重初始化函数
    def init(self):
        def init_weight(m):
            if type(m)==nn.Linear or type(m)==nn.Conv2d:
                torch.nn.init.constant_(m.bias,0.1)
                torch.nn.init.normal_(m.weight,std=0.01)
            elif type(m)==nn.ModuleList:
                for i,subLayer in enumerate(m):
                    torch.nn.init.constant_(subLayer.bias,0.1)
                    torch.nn.init.normal_(subLayer.weight,std=0.01)
        self.apply(init_weight)

net=MyNet()

(电脑没电了,未完,有空补充)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深信服AC密码认证(外部认证:LDAP认证)

拓扑图 搭建好自己AD域服务器,我搭建的服务器域名叫做liyanlongyu.com,如何搭建这里我就不做演示了 一.在AC中添加自己AD域服务器 二.添加LDAP认证策略 验证: 未认证发现,无法上网 点击网页,弹出认证页面 认证后&…

HAL库STM32串口开启DMA接收数据

STM32CubeMx的配置 此博客仅仅作为记录,这个像是有bug一样,有时候好使,有时候不好,所以趁现在好使赶紧记录一下,很多地方用到串口接收数据,DMA又是一种非常好的接收方式,可以节约CPU的时间&…

【C语言】深入理解数据表示与存储

文章目录 1.分析上述源程序中的变量在机器内是如何表示的1.1.并给出变量在内存中的存储情况(变量占多少个字节,每个字节的地址和存放的数据是多少)1.2.说明其存放顺序(大端、小端次序?)1.3.对齐方式&#x…

2023.11.18 - hadoop之zookeeper分布式协调服务

1.zookeeper简介 ZooKeeper概念: Zookeeper是一个分布式协调服务的开源框架。本质上是一个分布式的小文件存储系统 ZooKeeper作用: 主要用来解决分布式集群中应用系统的一致性问题。 ZooKeeper结构: 采用树形层次结构,没有目录与文件之分,ZooKeeper树中的每个节点被…

代码随想录 Day49 单调栈01 LeetCode LeetCodeT739每日温度 T496 下一个最大元素I

前言 折磨的死去活来的动态规划终于结束啦,今天秋秋给大家带来两题非常经典的单调栈问题,可能你不清楚单调栈是什么,可以用来解决什么问题,今天我们就来一步一步的逐渐了解单调栈,到能够灵活使用单调栈.注意以下讲解中,顺序的描述为 从栈头到栈底的顺序 什么时候用单…

“流量为王”的时代一去不返!如何押注互联网下一个黄金十年

目录 1“流量为王”的时代一去不返!如何押注互联网下一个黄金十年 2AI夺走的第一份工作竟是OpenAI CEO?阿尔特曼被“扫地出门”,网友热评:是被GPT-5取代了吗?马斯克更“毒”,挂出求职申请链接 3GPT-4V新玩…

生活总是自己的,请尽情打扮,尽情可爱,,

同色系拼接羽绒服了解一下 穿上时尚感一下子就突显出来了 90白鸭绒填充,不仅时尚还保暖 设计感满满的羽绒服不考虑一下吗?

9 STM32标准库函数 之 独立看门狗(IWDG)所有函数的介绍及使用

9 STM32标准库函数 之 独立看门狗(IWDG)所有函数的介绍及使用 1. 图片有格式该文档修改记录:总结 函数描述格式: 函数名外设函数的名称函数原形原形声明功能描述简要解释函数是如何执行的输入参数{x}输入参数描述输出参数{x}输出…

OpenCV快速入门:图像滤波与边缘检测

文章目录 前言一、噪声种类与生成1.1 椒盐噪声1.2 高斯噪声1.3 彩色噪声 二、卷积操作2.1 卷积基本原理2.2 卷积操作代码实现 三、线性滤波3.1 均值滤波均值滤波原理均值滤波公式均值滤波代码实现 3.2 方框滤波方框滤波原理方框滤波公式方框滤波代码实现 3.3 高斯滤波高斯滤波原…

手把手教你用C语言写出“走迷宫”小游戏(能看懂文字就会自己敲系列)

目录 设计迷宫地图 设计主角——小球 完整代码 这次教大家编写一个简单的“走迷宫”小游戏,我们可以通过键盘上的‘W’、‘S’、‘A’、‘D’四个键来控制一个“小球”向上,下,左,右移动,目的就是让这个“小球”从起…

element表格头部加入图标

首先看看效果 下面是代码 <el-table-column prop"integralBalance"><template slot"header" slot-scope"scope"><div style"display: flex;justify-content: center;align-items: center;">积分余额<i class&qu…

mac无法向移动硬盘拷贝文件怎么解决?不能读取移动硬盘文件怎么解决

有时候我们在使用mac的时候&#xff0c;会遇到一些问题&#xff0c;比如无法向移动硬盘拷贝文件或者不能读取移动硬盘文件。这些问题会给我们的工作和生活带来不便&#xff0c;所以我们需要找到原因和解决办法。本文将为你介绍mac无法向移动硬盘拷贝文件怎么回事&#xff0c;以…

Mysql -常见函数

目录 字符串函数 数值函数 日期函数 流程函数 字符串函数 -- 拼接 SELECT CONCAT(Hello, World); -- 小写 SELECT LOWER(Hello); -- 大写 SELECT UPPER(Hello); -- 左填充 SELECT LPAD(01, 5, -); -- 右填充 SELECT RPAD(01, 5, -); -- 去除空格 SELECT TRIM( Hello World )…

sqli-labs关卡20(基于http头部报错盲注)通关思路

文章目录 前言一、回顾上一关知识点二、靶场第二十关通关思路1、判断注入点2、爆数据库名3、爆数据库表4、爆数据库列5、爆数据库关键信息 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。注意靶场是可以练习的平台&#xff0c;不能随意去尚…

基于 gin + websocket 即时通讯项目 (一、项目初始化)

基于 gin websocket 即时通讯项目 1、安装环境与初始化 搜索各种包官网 https://pkg.go.dev/ 1.1 安装 grom go get -u gorm.io/grom 1.2 安装 MySQL 驱动 go get -u gorm.io/driver/sqlite go get -u gorm.io/driver/mysql 1.3 安装 gin go get -u github.com/gin-gonic/gi…

深入了解Java 8 新特性:lambda表达式基础

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概000多字&#xff0c;预计阅读时间长需要5分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&#xf…

RIP路由信息协议

RIP路由信息协议(Routing Information Protocol) 最先得到广泛应用的协议&#xff0c;最大优点是简单要求网络中的每个路由器都要维护一张表&#xff0c;表中记录了从它自己到其他每一个目的网络的距离RIP是应用层协议&#xff0c;它在传输层使用UDP&#xff0c;RIP报文作为UD…

Git 简介及使用

前言 假设有这样一个场景&#xff0c;老板让员工做一个档案&#xff0c;员工这个档案做好了之后交给老板看&#xff0c;此时老板不满意&#xff0c;又让回去改&#xff0c;改完给老板看&#xff0c;但是老板又不是很满意&#xff0c;就这样改了又改&#xff0c;给老板看过之后&…

WPF中行为与触发器的概念及用法

完全来源于十月的寒流&#xff0c;感谢大佬讲解 一、行为 (Behaviors) behaviors的简单测试 <Window x:Class"Test_05.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winf…

YOLOv8改进 | DAttention (DAT)注意力机制实现极限涨点

论文地址&#xff1a; DAT论文地址 官方地址&#xff1a;官方代码的地址 代码地址&#xff1a;文末有修改了官方代码BUG的代码块复制粘贴即可 一、本文介绍 本文给大家带来的是YOLOv8改进DAT(Vision Transformer with Deformable Attention)的教程&#xff0c;其发布于2022…