当前位置: 首页 > news >正文

【新手适用】手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN一: 创建model模块和加载数据集

教程:j从零开始实现一个基于Pytorch的卷积神经网络 - 知乎

目录

 网络结构

 1 初始化

2 前向传播forward函数

2.1 forward函数定义

2.2 view函数和size函数

 如何获取channels? 

如何获取batchsize? 

2.3 forward实现

2.4 main方法调用


模型命名为LeNet,创建一个名为LeNet的类,该类继承了nn.Module类,写法如下:

class LeNet(nn.Module):

 网络结构

从图中可以看出,其输入32x32的灰度图像,由于MNIST数据集的图像为28x28,因此,我们将输入改为28x28,并依次计算每一层输出的特征图大小。其每一层参数大致如下:

输入层:输入大小28x28,通道数为1。注意:本层不算LeNet-5的网络结构,一般情况下不将输入层视为网络层次结构之一

C1-卷积层:输入大小28x28,通道数为1;输出大小28x28,通道数为6;卷积核大小为5x5;步长为1;边缘补零为2;激活函数为ReLU。注意:为了提升卷积神经网络的效果,在每个卷积层后添加激活函数,本教程使用的激活函数为ReLU。

S2-池化层:输入大小28x28,通道数为6;输出大小14x14,通道数为6;池化核大小为2x2;步长为2;池化方式为最大池化。

C3-卷积层:输入大小14x14,通道数为6;输出大小10x10,通道数为16;卷积核大小为5x5;步长为1;边缘补零为0;激活函数为ReLU。

S4-池化层:输入大小10x10,通道数为16;输出大小5x5,通道数为16;池化核大小为2x2;步长为2;池化方式为最大池化。

C5-卷积层:输入大小5x5,通道数为16;输出大小1x1,通道数为120;卷积核大小为5x5;步长为1;边缘补零为0;激活函数为ReLU。注意:这层也可以看作全连接层,可以通过全连接的方法实现。

F6-全连接层:输入为120维向量;输出为84维向量;激活函数为ReLU。

OUTPUT-输出层:输入为84维向量;输出为10维向量。注意:该层也是全连接层,且不带激活函数。

 1 初始化

 __init__函数即初始化,主要用于定义每一层的构成,如卷积、池化层等;根据网络结构对每一层的参数进行定义。

# 初始化模型def __init__(self):super(LeNet,self).__init__()# 定义每一层的操作和参数self.C1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,stride=1,padding=2)self.R1 = nn.ReLU()self.S1 = nn.MaxPool2d(kernel_size=2)self.C2 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5,stride=1,padding=0)self.R2 = nn.ReLU()self.S2 = nn.MaxPool2d(kernel_size=2)self.C3 = nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5,padding=0,stride=1)self.R3 = nn.ReLU()#F6-全连接层:输入为120维向量;输出为84维向量;激活函数为ReLU。self.f = nn.Linear(in_features=120,out_features=84)self.R4 = nn.ReLU()# OUTPUT-输出层:输入为84维向量;输出为10维向量。注意:该层也是全连接层,且不带激活函数。self.OUT = nn.Linear(in_features=84,out_features=10)

2 前向传播forward函数

forward函数即前向传播,主要用于确定每一层之间的顺序,使得模型可以正常使用。

2.1 forward函数定义

前向传播函数需要传入self和输入的变量,一般写为x,即forward(self, x)。在函数内把之前定义好的层按顺序调用,每一层在计算后会返回结果;

我们需要一个变量进行保存,即c1 = self.C1(x),在最后将最后一步的计算结果返回。当网络中不存在跳跃连接或密集连接等分支结构的情况下,可以直接用x作为中间变量。

 forward函数定义步骤如下:

  1.  依次调用前面定义的网络层
  2. 修改需要变化的张量维度

2.2 view函数和size函数

在pytorch中,图像数据以一个四维张量传入模型,其形状为[batch_size, channels, h, w]

  • batch_size即批大小,我们一般会一次性将一批图像送进网络处理,这一批图像的数量即为批大小;
  • channel即通道数,也就是之前卷积层的channels;
  • h和w分别代表图像的高和宽。

Conv2d和MaxPool2d都接受以上形状的输入,ReLU接受任意形状的输入,而Linear只接受传入一个二维的张量,形状为[batch_size, length]

  • length表示长度,即向量的维度。

因此可以使用view()方法把卷积层输出的四维张量转换为二维张量。

e.g. 最后一个卷积层生成的特征图形状为[batch_size, channels, 1, 1],要将其转换为[batch_size, channels]。-> view(batchsize,channels)

 如何获取channels? 

可直接填入-1。

填写-1会让电脑自动计算这一栏所需参数的大小,这个方法在实际搭建模型的时候非常好用,因此大家一般都会写为-1。

如何获取batchsize? 

 若已知批大小,就可以直接把batch_size填入。但是,在实际使用中batch_size可能会随着超参数的变化而改变。

使用size()方法获取batchsize。

在size方法的括号内填上维度即可返回所在维度的大小,如x是一个形状为[16, 3, 384, 256]的张量,x.size(0)可获取张量中第一个维度的大小,即16,为批大小。

 最后,使用x保存返回值,x = x.view(x.size(0), -1)

2.3 forward实现

    def forward(self,x):x = self.C1(x)x = self.R1(x)x = self.S1(x)x = self.C2(x)x = self.R2(x)x = self.S2(x)x = self.C3(x)x = self.R3(x)# 改变维度x = x.view(x.size(0),-1)x = self.f(x)x = self.R4(x)x = self.OUT(x)return x

2.4 main方法调用

if __name__ == "__main__":model = LeNet()
# 测试数据a = torch.randn(1, 1, 28, 28)b = model(a)print(b)

2.5 代码 

import torch
import torch.nn as nnclass LeNet(nn.Module):# 初始化模型def __init__(self):super(LeNet,self).__init__()# 定义每一层的操作和参数self.C1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,stride=1,padding=2)self.R1 = nn.ReLU()self.S1 = nn.MaxPool2d(kernel_size=2)self.C2 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5,stride=1,padding=0)self.R2 = nn.ReLU()self.S2 = nn.MaxPool2d(kernel_size=2)self.C3 = nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5,padding=0,stride=1)self.R3 = nn.ReLU()#F6-全连接层:输入为120维向量;输出为84维向量;激活函数为ReLU。self.F4 = nn.Linear(in_features=120,out_features=84)self.R4 = nn.ReLU()# OUTPUT-输出层:输入为84维向量;输出为10维向量。注意:该层也是全连接层,且不带激活函数。self.OUT = nn.Linear(in_features=84,out_features=10)# 定义前向传播层def forward(self,x):x = self.C1(x)x = self.R1(x)x = self.S1(x)x = self.C2(x)x = self.R2(x)x = self.S2(x)x = self.C3(x)x = self.R3(x)# 改变维度x = x.view(x.size(0),-1)x = self.F4(x)x = self.R4(x)x = self.OUT(x)return xif __name__ == "__main__":model = LeNet()a = torch.randn(1, 1, 28, 28)b = model(a)print(b)

 

3  数据集

download_dataset.py 

import torchvision
torchvision.datasets.MNIST('./data', download=True)

导入torchvision包,torchvision.dataset中有很多经典的数据集可以下载。

下载MNIST数据集:torchvision.datasets.MNIST(root, train, transform, target_transform, download)

设置root为data文件夹,将download设置为True,运行该文件可完成下载。

 

 

相关文章:

  • MySQL 函数
  • Java后端八股------消息中间件篇
  • 微信小程序云开发教程——墨刀原型工具入门(素材面板)
  • 记录一个编译的LLVM 含clang 和 PTX 来支持 HIPIFY 的构建配置
  • Java的控制流语句详解
  • 网络通信另个角度的认识(进程间通信),端口号(为什么要有,和pid的关系,如何封装,和进程的定位原理+对应关系)客户端如何拿到服务端的port
  • 数据结构奇妙旅程之二叉平衡树进阶---AVL树
  • scrapy的基本使用介绍
  • CUDA入门之统一内存
  • 学习大数据,所需要Java基础(9)
  • taosdb快速入门
  • Docker的基本概念和优势
  • 【鸿蒙 HarmonyOS 4.0】常用组件:List/Grid/Tabs
  • 常见doc命令使用
  • 2024蓝桥杯每日一题(二分)
  • [Vue CLI 3] 配置解析之 css.extract
  • 【css3】浏览器内核及其兼容性
  • Android交互
  • css布局,左右固定中间自适应实现
  • css系列之关于字体的事
  • Druid 在有赞的实践
  • emacs初体验
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Python3爬取英雄联盟英雄皮肤大图
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Wamp集成环境 添加PHP的新版本
  • 前端面试题总结
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 如何用纯 CSS 创作一个货车 loader
  • ​flutter 代码混淆
  • # .NET Framework中使用命名管道进行进程间通信
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (Java数据结构)ArrayList
  • (差分)胡桃爱原石
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (轉)JSON.stringify 语法实例讲解
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .bat文件调用java类的main方法
  • .Net Core和.Net Standard直观理解
  • .net 发送邮件
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @ModelAttribute使用详解
  • [ 数据结构 - C++]红黑树RBTree
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [BZOJ 3680]吊打XXX(模拟退火)
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [html] 动态炫彩渐变背景
  • [ios] IOS文件操作的两种方式:NSFileManager操作和流操作【转】