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

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

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_channelslayers.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.mzph.cn/news/146882.shtml

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

相关文章

传递函数的推导和理解

传递函数的推导和理解 假设有一个线性系统,在一般情况下,它的激励 x ( t ) x(t) x(t)与响应 y ( t ) y(t) y(t)所满足的的关系,可用下列微分方程来表示: a n y ( n ) a n − 1 y ( n − 1 ) a n − 2 y ( n − 2 ) ⋯ a 1 y…

k8s上Pod生命周期、重启策略、容器探测简介

目录 一.Pod的创建过程 二.Pod的终止过程 三.Pod的重启策略(restartPolicy) 1.Always 2.OnFailture 3.Never 4.示例 四.Pod生命周期内的5种状态(相位) 1.Pending 2.Running 3.Succeeded 4.Failed 5.Unknown 五.初始…

SpringCache

1、基本信息 Spring缓存方案:JDK内置的缓存(ConcurrentHashMap)、第三方缓存组件(Caffeine)、分布式的缓存实现(Memcahed、Redis)。 ConcurrentHashMap是JUC之中提供最为重要的技术实现。SpringCache之中为了便于缓存结构的管理,在“org.s…

flutter TabBar指示器

第一层tabView import package:jade/configs/PathConfig.dart; import package:jade/customWidget/MyCustomIndicator.dart; importpackage:jade/homePage/promotion/promotionPost/MyPromotionListMainDesc.dart; import package:jade/homePage/promotion/promotionPost/MyPr…

C++入门(1)—命名空间、缺省参数

目录 一、什么是C 1、C关键字(C98) 2、C兼容C 二、C程序预处理指令 三、命名空间 1、命名冲突 第一种: 第二种: 2、域作用限定符 3、实现命名空间 4、命名空间冲突 5、访问命名空间 6、命名空间“std” 四、输入输出 1、定义 2、自动识…

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

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

腾讯云服务器租用价格,腾讯云服务器价格流量怎么算?

首先,让我们来看看腾讯云服务器租用价格。根据您的需求不同,腾讯云提供了多种不同的配置选项,从轻量级应用服务器到高性能的GPU服务器,都可以满足您的需求。以下是一些常见的腾讯云服务器租用价格: 一、腾讯云服务器租…

Mysql-复合查询

实际开发中往往数据来自不同的表,所以需要多表查询。 1.笛卡尔积 通俗来讲就是两个表的每一列都组合一遍,也就是穷举法。 穷举出来的数据表会有大量重复数据,而我们只需要加上一些限定条件就可以完成有效数据的筛选。 select EMP.ename, EM…

解决:虚拟机远程连接失败

问题 使用FinalShell远程连接虚拟机的时候连接不上 发现 虚拟机用的VMware,Linux发行版是CentOs 7,发现在虚拟机中使用ping www.baidu.com是成功的,但是使用FinalShell远程连接不上虚拟机,本地网络也ping不通虚拟机&#xff0c…

STM32 I2C详解

STM32 I2C详解 I2C简介 I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线 两根通信线: SCL(Serial Clock)串行时钟线,使用同步的时序,降低对硬件的依赖,同时同步的时序稳定…

【UE5】显示或隐藏物体轮廓线

效果 步骤 1. 先下载所需的材质文件“M_Highlight.uasset” 材质下载链接: 链接:https://pan.baidu.com/s/1rxmRhkUoXVq6-DkIKyBhAQ 提取码:55bv 2. 在视口中拖入后期处理体积 根据需求设置后期处理体积的大小或者直接设置无限范围&…

python爬取网站数据,作为后端数据

一. 内容简介 python爬取网站数据,作为后端数据 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 2.3代码 链接: 三.主要流程 3.1 通过urllib请求网站 里面用的所有的包 ! pip install lxml ! pip install selenium ! pip install…

【Linux】U盘安装的cfg引导文件配置

isolinux.cfg文件 default vesamenu.c32 timeout 600display boot.msg# Clear the screen when exiting the menu, instead of leaving the menu displayed. # For vesamenu, this means the graphical background is still displayed without # the menu itself for as long …

计算两个图形遮盖率

读取图像 首先,加载待处理的图像,可以使用图像处理库(例如OpenCV)来实现这一步。确保已加载正确的图像。 定义特定颜色范围 确定所需的特定颜色范围。这将是要检测的马赛克填充的颜色。需要指定颜色的下限值和上限值,通…

深度学习中文汉字识别 计算机竞赛

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习中文汉字识别 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐&#xf…

快速搭建本地的chatgpt

快速搭建本地的chatgpt 参考:一篇文章教你使用Docker本地化部署Chatgpt(非api,速度非常快!!!)及裸连GPT的方式(告别镜像GPT)-CSDN博客 前提是linux下 已安装docker 命…

Leetcode—142.环形链表II【中等】

2023每日刷题(三十三) Leetcode—142.环形链表II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode *detectCycle(struct ListNode *head) {struct ListNode* …

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

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

阿里巴巴java开发手册-编程规约

编程规约 命名风格常量定义代码格式OOP 规约日期时间集合处理并发处理控制语句注释规约前后端规约其他 命名风格 【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。 反例:_name / name / n a m e / n a m e / n a m e…

Linux下安装部署redis(离线模式)

一、准备工作 1.下载redis的安装包 下载地址:Index of /releases/ 大家可以自行选择redis的版本,笔者选择的是最新的 2.上传到服务器 前提是我先在服务器上创建了一个目录redis7.2.3,我直接上传到这个目录下 二、安装redis 1.解压redis t…