深度学习4 -- 卷积神经网络(代码实现篇+付详细流程文件)

news2024/11/19 0:27:56

引言

  • 本文是使用pytorch对卷积神经网络(Convolutional Neural Network, CNN)的代码实现,作为之前介绍CNN原理的一个代码补充。
  • 本文代码相关介绍相对较为详细,也为自己的一个学习过程,有错误的地方欢迎指正。
  • 本人介绍CNN原理的链接:CNN原理介绍1
    CNN原理介绍2

简述CNN结构

  • 为方便理解,如下图所示(详细介绍看上方链接)

  • 结构:一个卷积神经网络由若干卷积层、Pooling层、全连接层组成
  • 流程通俗理解(卷积):输入图片通过卷积核提取特征参数Feature Maps,此为卷积层的操作;
  • 流程通俗理解(池化):得到的特征参数经过池化层进行化简减少参数量,此为池化层的操作
  • 流程通俗理解(全连接):将最终提取到的特征信息输入到全连接神经网络进行计算
  • 上面图中一张图变成了3张Feature Maps是因为Feature Maps数量跟图片通道数有关,卷积核也同样是对应的,一个通道对应一个卷积核
  • 具体名称的介绍可以见:名称介绍

完整流程:

step1 导入需要的包

import torch
import torch.nn as nn
import torch.utils.data as Data
from torch.autograd import Variable
import torchvision # pytorch的一个视觉处理工具包(需单独安装)
  • PyTorch中主要的包
    • torch.nn :包含用于构建神经网络的模块和可扩展类的子包。
    • torch.autograd :支持PyTorch中所有的可微张量运算的子包
    • torch.nn.functional :一种功能接口,包含用于构建神经网络的典型操作,如损失函数、激活函数和卷积运算
    • torch.optim :包含标准优化操作(如SGD和Adam)的子包。
    • torch.utils :工具包,包含数据集和数据加载程序等实用程序类的子包,使数据预处理更容易
    • torchvision :一个提供对流行数据集、模型架构和计算机视觉图像转换的访问的软件包
  • 这些包可能代码中并未用到;参考资料1

step2 数据预处理

首先是关于将数据转换成tensor的原因

  • Tensor的意义:Tensor之于PyTorch就好比是array之于Numpy或者DataFrame之于Pandas,都是构建了整个框架中最为底层的数据结构;
  • Tensor的区别:Tensor又与普通的数据结构不同,具有一个极为关键的特性——自动求导而且它表示一个多维矩阵,在计算方面还可以在GPU上使用以加速计算.
  • PyTorch中对于数据集的处理有三个非常重要的类:Dataset、Dataloader、Sampler,它们均是 torch.utils.data 包下的模块(类)
    • Dataloader是数据的加载类,它是对于Dataset和Sampler的进一步包装,用于实际读取数据,可以理解为它是这个工作的真正实践者。参考资料2

关于torchvision中的数据集

  • torchvision中datasets中所有封装的数据集都是torch.utils.data.Dataset的子类,它们都可以用torch.utils.data.DataLoader进行数据加载。以datasets.MNIST类为例,具体参数和用法如下所示:
CLASS torchvision.datasets.MNIST(
          root: str, 
          train: bool = True, 
          transform: Optional[Callable] = None, 
          target_transform: Optional[Callable] = None, 
          download: bool = False
)
  • root (string): 表示数据集的根目录,其中根目录存在MNIST/processed/training.pt和MNIST/processed/test.pt的子目录(其实就是对下载的文件指定位置)
  • train (bool, optional): 如果为True,则从training.pt创建数据集,否则从test.pt创建数据集
  • download (bool, optional): 如果为True,则从internet下载数据集并将其放入根目录。如果数据集已下载,则不会再次下载
  • transform (callable, optional): 接收PIL图片并返回转换后版本图片的转换函数(就是把图片或者numpy中的数组转换成tensor)
  • target_transform (callable, optional): 接收PIL接收目标并对其进行变换的转换函数
  • 具体参考:参考资料3

什么是Variable?

  • variable是tensor的封装,在神经网络中,常需要反向传播这些的,所以需要各个节点是连接在一起的,是个计算图,tensor的数据格式就好比星星之火,但是无法汇聚一起;等变成variable之后就可以慢慢燎原了。
  • 关于Variable

代码分析

  • Data.DataLoader:加载数据
    • shuffle:表示打乱数据顺序
  • torch.unsqueeze:个人理解就是改变数据shape,此处就是把训练数据本来是一维的给"竖"起来作为一条一条数据进行训练(等以后我想起来更通俗的再修改,具体函数用法看下面参考资料)
    • 详情介绍:参考资料4 参考资料5
    • 图像尺寸是28*28的,具体验证可见最下面我jupyter转成的html结果

step3 定义网络结构

  • Net需要继承自nn.Module,通过super(python中的超类)完成父类的初始化,个人理解类比于python中定义类要继承Object类,这样很多基础定义就可以略去了
    • nn.Module是nn中十分重要的类,包含网络各层的定义及forward方法参考资料6
  • nn.Sequential返回的是一个序列容器用于搭建神经网络的模块,按照被传入构造器的顺序添加到nn.Sequential()容器中,比如con1中就是进行封装先进行第一层的卷积和池化,conv2同理,然后定义前向传播(注意是卷积两次) 参考资料7
    • nn.Conv2d: 在Pytorch的nn模块中,封装了nn.Conv2d()类作为二维卷积的实现,二维卷积应该是最常用的卷积方式了 参考资料8

关于网络结构中流程梳理

  • 关于卷积层nn.Conv2d中的参数介绍:in_channels 输入图片的通道数,同理out_channels为输出图片的通道数(都为自定义的,我搜集资料看到有1,3,16,32等等);kernel_size为卷积核大小,5 * 5可以直接简写,如果是3 * 5就要写成元组的形式;stride为卷积核移动的步长;padding为填充的大小,具体意义可见文章顶部原理介绍

  • nn.ReLU()为激活函数,使用ReLU激活函数有解决梯度消失的作用(具体作用看文章顶部原理中有介绍)

  • nn.MaxPool2d:maxpooling有局部不变性而且可以提取显著特征的同时降低模型的参数,从而降低模型的过拟合,具体操作看下图,除了最大值,还可以取平均值

  • nn.Linear主要是用于全连接层 参考资料8

  • x.view()就是对tensor进行reshape:参考资料9

  • 关于卷积时候图片size的变化

    • 首先输入通道为1,尺寸大小为28 * 28,即(1,28,28)
    • 经过卷积后因为自定义输出通道为16,那么尺寸为(16,28,28)
    • 经过池化层,因为卷积核是2 * 2的,所以尺寸降低为(16,14,14)
    • 继续conv2卷积,池化后就尺寸变成了(32,7,7)
    • nn.Linear具体用法(10是因为这个识别结果是0-9,为10个类别):参考资料10
  • 关于输出尺寸的计算公式

    • O = (I - K + 2P)/ S +1
    • I输入尺寸,K是卷积核大小,P是padding大小,S是步长

step4 训练模型

  • 关于优化器torch.optim.Adam,个人也还不是特别理解详细的作用,此处待补充链接
  • 交叉熵损失函数(适合分类模型): 个人之前的总结
  • optimizer.zero_grad()关于优化器清空上层的梯度
    • 有介绍是为了优化内存的 : 参考资料11
    • 有介绍是一种tips故意不清零来进行梯度优化的
    • 总之还是那句,优化器我搞懂了再补上…
    • 其实单纯论反向传播得时候梯度的更新貌似没有提及是否需要清空上层梯度:梯度下降与反向传播
  • loss.backward()反向传播上面介绍Variable的时候已经讲过,已经封装好了(看CNN原理部分反向传播求各个参数不同层级参数的偏导求得相似,结果在这里只需要调用api…)
  • torch.max 通俗讲就是返回列表中最大的数,具体用法可以见最下方html文件

完整代码

  • 参考资料12
  • 参考资料13
import torch
import torch.nn as nn
import torchvision 
import torch.utils.data as Data
 
torch.manual_seed(1)  # 设置随机种子, 用于复现
 
# 超参数
EPOCH = 1       # 前向后向传播迭代次数
LR = 0.001      # 学习率 learning rate 
BATCH_SIZE = 50 # 批量训练时候一次送入数据的size
DOWNLOAD_MNIST = True 
 
# 下载mnist手写数据集
# 训练集
train_data = torchvision.datasets.MNIST(  
    root = './MNIST/',                      
    train = True,                            
    transform = torchvision.transforms.ToTensor(),                                                
    download=DOWNLOAD_MNIST 
)
 
# 测试集
test_data = torchvision.datasets.MNIST(root='./MNIST/', train=False)  # train设置为False表示获取测试集
 
# 一个批训练 50个样本, 1 channel通道, 图片尺寸 28x28 size:(50, 1, 28, 28)
train_loader = Data.DataLoader(
    dataset = train_data,
    batch_size=BATCH_SIZE,
    shuffle=True
) 
#  测试数据预处理;只测试前2000个
test_x = torch.unsqueeze(test_data.data,dim=1).float()[:2000] / 255.0
# shape from (2000, 28, 28) to (2000, 1, 28, 28)
test_y = test_data.targets[:2000]
 
class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
 
        self.conv1 = nn.Sequential(
            nn.Conv2d(                      # 输入的图片 (1,28,28)
                in_channels=1,
                out_channels=16,            # 经过一个卷积层之后 (16,28,28)
                kernel_size=5,
                stride=1,                    # 如果想要 con2d 出来的图片长宽没有变化, padding=(kernel_size-1)/2 当 stride=1
                padding=2
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)      # 经过池化层处理,维度为(16,14,14)
        )
 
        self.conv2 = nn.Sequential(
            nn.Conv2d(                         # 输入(16,14,14)
                in_channels=16,
                out_channels=32,
                kernel_size=5,
                stride=1,
                padding=2
            ),                                 # 输出(32,14,14)
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)        # 输出(32,7,7)
        )
 
        self.out = nn.Linear(32*7*7,10)
 
    def forward(self, x):
        x = self.conv1(x)                     #(batch_size,16,14,14)
        x = self.conv2(x)                     # 输出(batch_size,32,7,7)
        x = x.view(x.size(0),-1)              # (batch_size,32*7*7)
        out = self.out(x)                     # (batch_size,10)
        return out
 
cnn = CNN()
optimizer = torch.optim.Adam(cnn.parameters(),lr=LR) # 定义优化器
loss_func = nn.CrossEntropyLoss() # 定义损失函数
 
for epoch in range(EPOCH):
 
    for step,(batch_x,batch_y) in enumerate(train_loader):
        pred_y = cnn(batch_x)
        loss = loss_func(pred_y,batch_y)
        optimizer.zero_grad() # 清空上一层梯度
        loss.backward() # 反向传播
        optimizer.step() # 更新优化器的学习率,一般按照epoch为单位进行更新
 
        if step % 50 == 0:
            test_output = cnn(test_x)
            pred_y = torch.max(test_output, 1)[1].numpy()  # torch.max(test_out,1)返回的是test_out中每一行最大的数)
                                                                # 返回的形式为torch.return_types.max(
                                                                #           values=tensor([0.7000, 0.9000]),
                                                                #           indices=tensor([2, 2]))
                                                                # 后面的[1]代表获取indices
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy())
 
 
# 打印前十个测试结果和真实结果进行对比
test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].numpy()
print(pred_y, 'prediction number')
print(test_y[:10].numpy(), 'real number')

补充一个测试过程掌握的小tips

  • 比如使用anaconda中的jupyter测试,但是anaconda中又很多虚拟环境,怎么将jupyter切换到测试用的虚拟环境呢
    • 需要注册,具体参考: 参考资料14
    • 比如我创建CNN测试环境是名称是python36,而默认是python3也就是base环境,按照上述安装并注册后就可以切换啦

附件

  • 测试CNN代码的详细步骤html文件
  • 待资源审核通过补充上

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

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

相关文章

【Ai工具合集,一定有你需要的!】

花费了一天的时间测试了市面上各大Ai工具,然后帮大家整理总结出来了这些工具,一定记得点赞收藏保存,后面肯定会用到! 使用说明 1.部分Ai工具需要魔法上网,请自行解决;部分工具需要收费,可以尝…

图神经网络:(处理点云)PointNet++的实现

文章说明: 1)参考资料:PYG官方文档。超链。 2)博主水平不高,如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 简单前置工作学习文献阅读PointNet的实现模型问题 简单前置工作…

convLSTM2D 层使用方法解析(Keras库)

最近在研究时序图像分类问题,需要用到convLSTM层提取特征,所以在此仔细分析一下keras.layers.ConvLSTM2D层的使用方法。深度学习框架是tensorflow 官方文档:recurrent/#convlstm2d - Keras 中文文档 下面这部分内容摘自官方文档 ConvLSTM2D…

Axure 轮播图如何制作

近来在学习axure,用的版本为Axure 9,给大家讲一下怎么使用轮播图,老规矩保姆式教学法 一、作图 1.创建新的页面,方便我们做图 2.在元件库搜索“动态面板”字样,设置一个动态面板,为什么要设置呢&#xff…

IIC总线通讯协议学习

​ IIC(最简单的总线通讯,简单意味着通用和普适性) iic通讯一般采用一主多从的方式.同一时间要么在发送信息,要么在读取信息(半双工通讯) ​​​​​​​​​​​​​​ ​​​​ ​​​ 标准的写数据帧(主机向从机写数据) 解释以上的写数据帧 S:起始信号(在SCL…

Linux学习---VMWare安装和CentOS7安装

1、 VMWare安装 1、VMware16安装包 链接:https://pan.baidu.com/s/1TKf5szN6k5Hk4HH4zqBgrg 提取码:zhm6 –来自百度网盘超级会员V1的分享 2、VMWare安装流程 (1)找到下载好的安装包,双击运行程序 (2&…

云贝餐饮连锁V2-2.7.7 【新增】外卖新订单提醒

独立版:云贝餐饮连锁V2、版本更新至2.7.7,小程序、公众号版本,全插件,包含微信公众号小程序;包更新,独立版; 带商家端,修复收银台、排队点餐、堂食点餐;最新版更新了&…

【pytorch损失函数(3)】nn.L1Loss()和nn.SmoothL1Loss()

文章目录 【回归损失函数】L1(MAE)、L2(MSE)、Smooth L1 Loss详解1. L1 Loss(Mean Absolute Error,MAE)1.1 数学定义1.2 、使用场景与问题1.3 、如何使用 2. L2 Loss(Mean Squared E…

最流行的开源 LLM (大语言模型)整理

本文对国内外公司、科研机构等组织开源的 LLM 进行了全面的整理。 Large Language Model (LLM) 即大规模语言模型,是一种基于深度学习的自然语言处理模型,它能够学习到自然语言的语法和语义,从而可以生成人类可读的文本。 所谓"语言模…

MTK平台的SWT异常的简单总结(1)——WatchDog

SWT系列资料很多来源于Google (1)概念相关 SWT是SoftWare Watchdog Timeout的缩写,在Android系统中,为了监控SystemServer是否处于正常运行状态,加入了SWT线程来监控SystemServer中重要线程和Service的运行情况。判断…

多线程-程序、进程、线程与并行、并发的概念

多线程 本章要学习的内容: 专题1:相关概念的理解专题2:多线程创建方式一:继承Thread类专题3:多线程创建方式二:实现Runnable接口专题4:Thread类的常用方法专题5:多线程的优点、使用…

合肥工业大学信息隐藏实验报告

✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :信息隐藏实验报告 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台&#xff…

OpenCV基础操作(1)图片及视频基础操作、常用绘图函数

OpenCV基础操作(1)图片、视频、绘图函数 import cv2 as cv import numpy as np1、图像的读取、显示、保存 使用函数 cv2.imread() 读入图像。 第一个参数是幅图路径, 第二个参数是要告诉函数应该如何读取这幅图片。 • cv2.IMREAD_COLOR(1):读入一副彩色…

模板字符串、startsWith()方法和endsWith()方法、repeat()、Set数据结构、Set对象实例方法、遍历Set

模版字符串 ES6新增的创建字符串的方式,使用反引号定义 示例 <script>// 1.模板字符串可以解析变量 ${}显示变量的值let name 张三;let sayHello HEllo,我的名字叫${name};console.log(name);console.log(sayHello);let result {name: "zhangsan",age: 20…

激光切割机在使用过程中常见故障有哪些(一)

由于不少客户在使用光纤激光切割机的过程中&#xff0c;因为操作不当等原因&#xff0c;造成激光切割机出现一些小故障&#xff0c;这些故障虽然不大&#xff0c;但是却会对正常使用工期造成延误&#xff0c;甚至造成损失&#xff0c;所以了解光纤激光切割机的常见故障迫在眉睫…

本地电脑远程服务器,复制大文件报:未指定错误的解决办法

1、本地电脑快捷键WINR 打开运行窗口 2、输入 \\IP地址\磁盘$。如下&#xff1a; 3、上一步点击确定&#xff0c;即远程到了相应的磁盘&#xff0c;可在本地进行复制粘贴。

北京打响大模型地方战第一枪:公布通用人工智能发展21项措施

21项&#xff01;北京就促进AGI创新发展措施征集意见。 作者 | 李水青 来源 | 智东西 ID | zhidxcom 智东西5月16日消息&#xff0c;近日&#xff0c;《北京市促进通用人工智能创新发展的若干措施&#xff08;2023-2025年&#xff09;&#xff08;征求意见稿&#xff09;》…

【C++】基础知识--程序的结构(1)

C简介&#xff1a; C 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言&#xff0c;支持过程化编程、面向对象编程和泛型编程。 C 被认为是一种中级语言&#xff0c;它综合了高级语言和低级语言的特点。 C 是由 Bjarne Stroustrup 于 1979 年在新泽西州…

Codeforces Round 873 (Div. 2) 题解

5.18晚VP&#xff0c;共AC三题&#xff0c;ABC题&#xff0c;感觉难度还是挺大的&#xff0c;做起来一点也不顺手。。。A题秒出&#xff0c;卡在了B题&#xff0c;在B题花费了好多时间&#xff0c;还没有C题做得顺利。。。B题开始想错了&#xff0c;思路不对&#xff0c;但确实…

LeetCode225.用队列实现栈

&#x1f4ad;前言&#xff1a; 建议本题和LeetCode232对比实现 syseptember的个人博客&#xff1a;LeetCode232.栈模拟队列http://t.csdn.cn/HCEDg 题目 思路 ❗注意&#xff1a;本题的逻辑结构是栈&#xff0c;物理结构是队列&#xff0c;我们需要通过2个队列模拟栈的操作。…