借助CIFAR10模型结构理解卷积神经网络及Sequential的使用

 CIFAR10模型搭建

CIFAR10模型结构

0. input 3@32x323通道32x32的图片 --> 特征图(Feature maps) : 32@32x32
即经过323@5x5的卷积层,输出尺寸没有变化(有x个特征图即有x个卷积核。卷积核的通道数与输入的通道数相等,即3@5x5)。
两种方法推导出padding = 2stride = 1的值:

公式法:

𝐻𝑜𝑢𝑡=32,𝐻𝑖𝑛=32,dilation = 1(默认值,此时没有空洞),kernel_size = 5

理论法:为保持输出尺寸不变,padding都是卷积核大小的一半,则有padding=kernel_size/2;奇数卷积核把中心格子对准图片第一个格子,卷积核在格子外有两层那么padding=2

1.input 32@32x32 --> output : 32@16x16
即经过2x2的最大池化层,stride = 2(池化层的步长为池化核的尺寸),padding = 0,特征图尺寸减小一半。
2.input 32@16x16 --> output : 32@16x16
即即经过323@5x5的卷积层,输出尺寸没有变化。padding = 2stride = 1
3.input : 32@16x16 --> output : 32@8x8
即经过2x2的最大池化层,stride = 2padding = 0,通道数不变,特征图尺寸减小一半。
4.input : 32@8x8 --> output : 64@8x8
即即经过643@5x5的卷积层,输出尺寸没有变化。padding = 2stride = 1
5.input : 64@8x8 --> output : 64@4x4
即经过2x2的最大池化层,stride = 2,padding = 0,通道数不变,特征图尺寸减小一半。
6.input:64@4x4-->output :1×1024
即经过展平层 Flatten 作用,将64@4x4的特征图依次排开。

7.input:1×1024-->output :​​​​​​​1×64
即经过线性层Linear1的作用。
8.input:1×64-->output:1×10
即经过线性层Linear2的作用。

代码验证:
按照网络结构一层一层搭建网络结构。
示例1:

# 导入需要用到的库
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear# 搭建CIFAR10模型网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.conv1 = Conv2d(3, 32, 5, padding=2) # 第一个卷积层self.maxpool1 = MaxPool2d(2) # 第一个最大池化层self.conv2 = Conv2d(32, 32, 5, padding=2) # 第二个卷积层self.maxpool2 = MaxPool2d(2) # 第二个最大池化层self.conv3 = Conv2d(32, 64, 5, padding=2) # 第三个卷积层self.maxpool3 = MaxPool2d(2) # 第三个最大池化层self.flatten = Flatten() # 展平层# 两个线性层self.linear1 = Linear(1024, 64) # 第一个线性层self.linear2 = Linear(64, 10) # 第二个线性层def forward(self, x):x = self.conv1(x)x = self.maxpool1(x)x = self.conv2(x)x = self.maxpool2(x)x = self.conv3(x)x = self.maxpool3(x)x = self.flatten(x)x = self.linear1(x)x = self.linear2(x)return xtudui = Tudui() # 实例化
print(tudui) # 观察网络信息
input = torch.ones((64, 3, 32, 32)) # 为网络创建假想输入,目的是检查网络是否正确
output = tudui(input) # 输出
print(output.shape) # torch.Size([64, 10]),结果与图片结果一致

 运行结果:

# 两个print出的内容分别为:
Tudui((conv1): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(maxpool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(conv2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(maxpool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(conv3): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(maxpool3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(flatten): Flatten(start_dim=1, end_dim=-1)(linear1): Linear(in_features=1024, out_features=64, bias=True)(linear2): Linear(in_features=64, out_features=10, bias=True)
)
torch.Size([64, 10])

Sequential的使用

        当模型中只是简单的前馈网络时,即上一层的输出直接作为下一层的输入,这时可以采用torch.nn.Sequential()模块来快速搭建模型,而不必手动在forward()函数中一层一层地前向传播。因此,如果想快速搭建模型而不考虑中间过程的话,推荐使用torch.nn.Sequential()模块。

接下来用torch.nn.Sequential()改写示例 1,示例 2 如下。
示例2:

# 导入需要用到的库
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential# 搭建CIFAR10模型网络
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.model1 = Sequential(Conv2d(3, 32, 5, padding=2),  # 第一个卷积层MaxPool2d(2),  # 第一个最大池化层Conv2d(32, 32, 5, padding=2), # 第二个卷积层MaxPool2d(2), # 第二个最大池化层Conv2d(32, 64, 5, padding=2),  # 第三个卷积层MaxPool2d(2),  # 第三个最大池化层Flatten(),  # 展平层# 两个线性层Linear(1024, 64),  # 第一个线性层Linear(64, 10)  # 第二个线性层)def forward(self, x):x = self.model1(x)return xtudui = Tudui() # 实例化
print(tudui) # 观察网络信息
input = torch.ones((64, 3, 32, 32)) # 为网络创建假想输入,目的是检查网络是否正确
output = tudui(input) # 输出
print(output.shape) # torch.Size([64, 10]),结果与图片结果一致

运行结果:

# 两个print出来的结果分别为:
Tudui((model1): Sequential((0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))(5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(6): Flatten(start_dim=1, end_dim=-1)(7): Linear(in_features=1024, out_features=64, bias=True)(8): Linear(in_features=64, out_features=10, bias=True))
)
torch.Size([64, 10])

        我们发现,使用Sequential之后得到的结果(示例2)与按照前向传播一层一层搭建得到的结果(示例1)一致,使用Sequential之后可以使得forward函数中的内容得以简化。

使用tensorboard实现网络结构可视化

# 导入需要用到的库
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.tensorboard import SummaryWriter# 搭建CIFAR10模型网络class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.conv1 = Conv2d(3, 32, 5, padding=2) # 第一个卷积层self.maxpool1 = MaxPool2d(2) # 第一个最大池化层self.conv2 = Conv2d(32, 32, 5, padding=2) # 第二个卷积层self.maxpool2 = MaxPool2d(2) # 第二个最大池化层self.conv3 = Conv2d(32, 64, 5, padding=2) # 第三个卷积层self.maxpool3 = MaxPool2d(2) # 第三个最大池化层self.flatten = Flatten() # 展平层# 两个线性层self.linear1 = Linear(1024, 64) # 第一个线性层self.linear2 = Linear(64, 10) # 第二个线性层def forward(self, x):x = self.conv1(x)x = self.maxpool1(x)x = self.conv2(x)x = self.maxpool2(x)x = self.conv3(x)x = self.maxpool3(x)x = self.flatten(x)x = self.linear1(x)x = self.linear2(x)return xtudui = Tudui() # 实例化
print(tudui) # 观察网络信息
input = torch.ones((64, 3, 32, 32)) # 为网络创建假想输入,目的是检查网络是否正确
output = tudui(input) # 输出
print(output.shape) # torch.Size([64, 10]),结果与图片结果一致# 使用tensorboard实现网络可视化
writer = SummaryWriter("./log_sequential")
writer.add_graph(tudui, input)
writer.close()

运行上述代码,则会在项目文件夹CIFAR10model中出现对应的日志文件夹log_sequential。

随后打开Terminal,如下图所示。

 输入tensorboard --logdir=log_sequential,如下图所示。

按下Enter键,得到一个网址,如下图所示。

 打开这个网址,得到可视化界面。

我们点开搭建好的网络Tudui,可以得到更具体的网络每一层,如下图所示。

我们将其放大,如下图所示。 

网络中的每一层

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

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

相关文章

SpringCloud(十)——ElasticSearch简单了解(一)初识ElasticSearch和RestClient

文章目录 1. 初始ElasticSearch1.1 ElasticSearch介绍1.2 安装并运行ElasticSearch1.3 运行kibana1.4 安装IK分词器 2. 操作索引库和文档2.1 mapping属性2.2 创建索引库2.3 对索引库的查、删、改2.4 操作文档 3. RestClient3.1 初始化RestClient3.2 操作索引库3.3 操作文档 1. …

网络技术二十二:NATPPP

NAT 转换流程 产生背景 定义 分类 常用命令 PPP PPP会话建立过程 认证 PPP会话流程

第 3 章 栈和队列(循环队列的顺序存储结构实现)

1. 背景说明 和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外, 尚需附设两个指针 front 和 rear 分别指示队列头元素及队列尾元素的位置。约定:初始化建空队列时&#x…

qt nodeeditor编译安装

目录 1. 下载源码 2. Qt creator编译源码 2.1 编译debug模式 (MinGW) 2.2 编译release模式 (MinGW) 1. 下载源码 https://github.com/paceholder/nodeeditor/archive/refs/tags/3.0.10.zip 2. Qt creator编译源码 解压文件…

Java 数据库改了一个字段, 前端传值后端接收为null问题解决

前端传值后端为null的原因可能有很多种,我遇到一个问题是,数据库修改了一个字段,前端传值了,但是后台一直接收为null值, 原因排查: 1、字段没有匹配上,数据库字段和前端字段传值不一致 2、大…

c语言 4.0

💂 个人主页: 程序员爱摸鱼🤟 版权: 本文由【程序员爱摸鱼】原创、在CSDN首发、需要转载请联系博主💬 如果文章对你有帮助、欢迎关注点赞收藏(一键三连)哦💅 想寻找共同成长的小伙伴,可以互粉哦 💬文章目录…

软件架构设计(六) 软件架构风格-MDA(模型驱动架构)

概念 模型驱动架构MDA, 全称叫做Model Driven Architecture。 Model:表示客观事物的抽象表示Architecture:表示构成系统的部件,连接件及其约束的规约Model Driven: 使用模型完成软件的分析,设计,构建,部署和维护等 开发活动MDA起源于分离系统规约和平台实现的思想。之前…

stable diffusion实践操作-复制-清空-保存提示词

系列文章目录 stable diffusion实践操作 stable diffusion实践操作-webUI教程 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、右上生成图标附近按钮介绍1. 箭头介绍(复现别人的…

视频汇聚/视频云存储/视频监控管理平台EasyCVR启动时打印starting server:listen tcp,该如何解决?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同,可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成,…

JSON是什么?认识 json

目录 一 Json定义 二 Json语法规则 三 json 的代码演示 一 Json定义 轻量级的文本数据交换格式具有自我描述性【看到某个Json数据就能知道它的特点】比xml传输速度快【跨平台】 二 Json语法规则 (1)语法 两种数据结构:对象和数组 大括号…

Qt6中使用Qt Charts

官方文档:Qt Charts 6.5.2 如果你是使用 CMake 构建的,则应在 CMakeLists.txt 中添加如下两行代码: find_package(Qt6 REQUIRED COMPONENTS Charts)target_link_libraries(mytarget PRIVATE Qt6::Charts) 其中 mytarget 为你的项目名称。一共…

SpringBoot初级开发--服务请求(GET/POST)所有参数的记录管理(8)

服务端在定位错误的时候,有时候要还原现场,这就要把当时的所有入参参数都能记录下来,GET还好说,基本NGINX都会记录。但是POST的请求参数基本不会被记录,这就需要我们通过一些小技巧来记录这些参数,放入日志…

天津web前端培训班 前端是否适合零基础学?

随着HTML 5和ECMAScript 6的正式发布,大量的前端业务逻辑,极大地增加了前端的代码量,前端代码的模块化、按需加载和依赖管理势在必行,因此Web前端越来越被人们重视。 Web前端的就业前景 Web前端开发工程师薪资持续走高&#xff…

小红书下一个爆款趋势锁定 | 秋冬种草指南

今夏「多巴胺」风靡全网,现秋日又捎来一股名为「美拉德」的风……俨然一副“新晋顶流”的架势。 如何抓住这一新趋势?本期千瓜将锁定小红书下一个爆款内容——「美拉德」,剖析笔记与底层逻辑,助力品牌洞见先机,运筹布…

长胜证券:主板或以震荡整理为主 结构性行情持续

长胜证券指出,技术面看,沪指3150点上方谨慎看多,缩量横盘整理代表强势,向上打破需市场放量且权重配合,后市若打破并站稳3230点可视为强势回转行情开启,考虑到短期人民币弱势格局,主板或以震动整…

【PCL-11】提取平面上层的目标物,剔除平面下层目标物

因项目需求,需提取平面上的物体,不提取平面下的物体,尝试采用超体聚类+LCCP分割的方式,但由于上层点云模型一侧有空洞,导致分割效果不理想。 这里采用pcl::ExtractPolygonalPrismData类,实现平面上物体的提取。 pcl::ExtractPolygonalPrismData类是通过设定处于同一平面模…

React三属性之:props

作用 将父组件的参数传递给子组件 父组件 import ./App.css; import React from react; import PropsTest from ./pages/propsTest class App extends React.Component{render(){return(<div><h2>App组件</h2><PropsTest obj{{name:王惊涛,age:27}}>…

基于qt软件的网上聊天室软件

1.服务器: 1).功能: 用于创建一个客户端&#xff0c;通过文本编辑器来获得端口号&#xff0c;根据获得的端口号创建服务器&#xff0c;等待客户端连接 创建成功会提示服务器创建成功 在收到客户端发送的信息时&#xff0c;把这条信息发送给其他所有客户端&#xff0c;实现群…

【Linux-Day9-进程间通信】

进程间通信 前提引入&#xff1a; 我们之前接触过管道 | 将前一个命令的输出结果作为后一个命令的输入 如&#xff1a;ps | grep “sleep” 其实就是将 ps 的结果写入到一个区域&#xff0c;在从这个区域读出目标数据 有名管道 mkfifo 创建管道文件 : mkfifo fifo ->创…

单片机采集传感器数据(整形,浮点型)modbus上传

浮点型数据 占两个寄存器&#xff08;四个字节&#xff09; short 整形 占一个寄存器 &#xff08;两个字节&#xff09; 注意&#xff01;&#xff01;&#xff01;&#xff01; stm32 是小端模式&#xff0c;而modbus解析数据是大端模式 所以先发送高字节 如int a16777220…