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

深度学习--mnist数据集实现卷积神经网络的手写数字识别


文章目录

  • 一、卷积神经网络CNN
    • 1、什么是CNN
    • 2、核心
    • 3、构造
  • 二、案例
    • 1、下载数据集(训练、测试集)并展示画布
    • 2、打包数据图片
    • 3、判断系统使用的是CPU还是GPU
    • 4、定义CNN神经网络
    • 5、训练和测试模型


一、卷积神经网络CNN

1、什么是CNN

卷积神经网络是一种深度学习模型,主要应用于图像和视频处理任务。它的设计灵感来源于生物视觉系统的工作原理。

2、核心

核心是卷积层,这是一种通过在输入数据上应用滤波器(也称为卷积核)来提取特征的操作。卷积层的输出是一系列的特征图,每个特征图表示一种特定的图像特征,例如边缘、纹理等。这种特征提取的方式可以捕捉到图像中的局部模式,并且在不同位置共享参数,从而提高了模型的效率和泛化能力。

在这里插入图片描述

3、构造

CNN还包括池化层,用于减小特征图的尺寸,降低计算复杂度,增加模型的平移不变性。

卷积神经网络还可以包含多个卷积层和池化层的堆叠,以及全连接层(Fully Connected Layer)用于进行分类或回归等任务。
在这里插入图片描述

二、案例

1、下载数据集(训练、测试集)并展示画布

通过现有的库调用其用法直接去下载现成的手写数字的数据集,这些手写数字集共有70000张图片,这些图片都有其对应的标签,大小为28*28,灰度图,数字居中,直接使用即可。
将这70000张图片,60000张当做训练集,10000张当做测试集。

import torch
from torch import nn # 导入神经网络模块
from torch.utils.data import DataLoader # 数据包管理工具,打包数据
from torchvision import datasets #封装了很多与图像相关的模型,数据集
from torchvision.transforms import ToTensor #数据转换,张量,将其他类型的数据转换为tensor张量 例如numpy array ,dataframe'''下载训练数据集(包含训练图片+标签)'''
training_data = datasets.MNIST(root="data",train=True,download=True,transform=ToTensor()#Tensor是在深度学习中提出并广泛运用的数据类型,它与深度学习框架(如PyTorch,TensorFlow)
) #Numpy 数组只能在cpu上运行。Tensor可以在GPU上运行,这在深度学习中可以显著提高计算速度。
print(len(training_data))'''下载测试数据集(包含训练图片+标签)'''
test_data = datasets.MNIST(root="data",train=False,download=True,transform=ToTensor()
)
print(len(test_data))'''展示手写字图片,把训练数据集中的前59000张图片展示一下'''
from matplotlib import pyplot as plt
figure = plt.figure()
for i in range(9):img, label = training_data[i+59000] #提取第59000张图片figure.add_subplot(3,3,i+1) #图片窗口中创建多个小窗口 ,小窗口用于显示图片 3*3plt.title(label)plt.axis("off") # plt.show(I) #显示矢量,plt.imshow(img.squeeze(),cmap="gray")# 将numpy数组data的数据转化为图像a = img.squeeze()#从张量img中去掉维度最高的也就是1,如果改维度的大小不为1 则张量不会改变
plt.show()

实现结果是:
在这里插入图片描述
取九张图展示在画布上:
在这里插入图片描述

2、打包数据图片

因为图片的数量太多,将其一张一张的放入GPU进行计算太耗费时间,而且还浪费资源,所以将64张图片打包成一份,将这一整个数据包传入GPU使其计算,这样大大增加了运行的效率。

train_dataloader = DataLoader(training_data,batch_size=64)#64张图片为一个包
test_dataloader = DataLoader(test_data,batch_size=64)

3、判断系统使用的是CPU还是GPU

"""判断当前设备是否支持GPU,其中mps是苹果m系列芯片的GPU"""  # 返回cuda,mps,cpu, m1,m2集显CPU+GPU RTX3060
device = "cuda" if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")  # 字符串的格式化。CUDA驱动软件的功能:pytorch能够去执行cuda的命令,cuda通过GPU指令集
# 神经网络的模型也需要传入到GPU,1个batchsize的数据集也需要传入到GPU,才可以进行训练。

我使用的是GPU:
在这里插入图片描述

4、定义CNN神经网络

class CNN(nn.Module):def __init__(self):#输入大小(1,28,28)super(CNN,self).__init__()#初始化父类self.conv1 = nn.Sequential(#将多个层组合到一起,创建了一个容器nn.Conv2d(in_channels=1,out_channels=8,kernel_size=3,stride=1,padding=1,),nn.ReLU(),#(8,28,28)nn.MaxPool2d(kernel_size=2)#(8,14,14))self.conv2 = nn.Sequential(nn.Conv2d(8,16,3,1,1),#(16,14,14)nn.ReLU(),#(16,14,14)nn.MaxPool2d(2)#(16,7,7))self.conv3 = nn.Sequential(nn.Conv2d(16,32,3,1,1),#(32,7,7)nn.ReLU(),)self.out = nn.Linear(32 * 7 * 7,10)def forward(self,x): #前向传播 数据的流向 就是神经网络层连接起来,函数名称不能改。x = self.conv1(x)  #将图像进行展开x = self.conv2(x)x = self.conv3(x) #(32,7,7)x = x.view(x.size(0),-1)x = self.out(x)return xmodel = CNN().to(device)#把刚刚创建的模型传入到GPU
print(model)

运行结果:
在这里插入图片描述

5、训练和测试模型

def train(dataloader,model,loss_fn,optimizer):model.train()# 告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w,在训练过程中,w会被修改的
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train() 和 model.eval().
# 一般用法是:在训练开始之前写model.train() 在测试时写上model.eval()。batch_size_num = 1for X,y in dataloader:                  #其中batch为每一个数据的编号X,y = X.to(device),y.to(device)     #把训练数据集和标签传入cpu或GPUpred = model.forward(X)             #.forward可以被省略,父类中已经对次功能进行了设置。自动初始化wloss = loss_fn(pred,y)              #通过交叉熵损失函数计算损失值loss#Backpropagation 进来一个batch的数据,计算一次梯度,更新一次网络optimizer.zero_grad()               #梯度值清零loss.backward()                     #反向传播计算得到每个参数的梯度值woptimizer.step()                    #根据梯度更新网络w参数loss_value = loss.item()            #从tensor数据中提取数据出来,tensor获取损失值if batch_size_num % 100 == 0:print(f"loss:{loss_value:>7f} [number:{batch_size_num}]")batch_size_num += 1def test(dataloader,model,loss_fn):size = len(dataloader.dataset)#10000num_batches = len(dataloader)#打包的数量model.eval() #测试,w就不能再更新。test_loss,correct = 0,0with torch.no_grad(): #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。for X,y in dataloader:X, y = X.to(device),y.to(device)pred = model.forward(X)test_loss += loss_fn(pred,y).item()#test_loss是会自动累加每一个批次的损失值correct += (pred.argmax(1) == y).type(torch.float).sum().item()a = (pred.argmax(1) == y)   #dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值b = (pred.argmax(1) == y).type(torch.float)test_loss /= num_batches #能来衡量模型测试的好坏correct /= size #平均的正确率print(f"Test result: \n Accuracy:{(100*correct)}%,Avg loss:{test_loss}")loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写数字识别中一共有10个数字,输出会有10个结果optimizer = torch.optim.Adam(model.parameters(),lr=0.01)#创建一个优化器,SGD为随机梯度下降算法
##params:要训练的参数,一般我们传入的都是model.parameters()。
##lr: learning_rate 学习率,也就是步长。#loss表示模型训练后的输出结果与样本标签的差距。如果差距越小,就表示模型训练越好,越逼近真实的模型。
# train(train_dataloader,model,loss_fn,optimizer)
for j in range(10):train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader,model,loss_fn)

运行结果:
在这里插入图片描述


相关文章:

  • 探索大语言模型(LLM):Transformer 与 BERT从原理到实践
  • 【OpenGL】OpenGL学习笔记-1:VS2019配置OpenGL开发环境
  • PR第一课
  • Arduino项目中硬件包括哪些部分
  • 【MATLAB海洋专题】历史汇总
  • 链表面试题
  • 用思维导图解锁计算机科学导论的知识宝库
  • 取值运算符*和地址运算符
  • MYSQL初阶(暂为自用草稿)
  • [密码学基础]GM/T 0018-2023 密码设备应用接口规范深度解析:技术革新与开发者实践
  • 【测试文档】项目测试文档,测试管理规程,测试计划,测试文档模版,软件测试报告书(Word)
  • 使用C语言的cJSON中给JSON字符串添加转义
  • C++中chrono计时器的简单使用示例
  • MCP协议驱动的全自动光催化甲烷偶联实验平台构建及实现方案
  • 【论文推荐|深度学习,冰川测绘,遥感,青藏高原】SAU-Net: 基于多源遥感数据的冰川制图深度学习方法(二)
  • 每日定投40刀BTC(14)20250409 - 20250419
  • windows11安装jitsi-meet视频会议系统
  • 如何使用flatten函数在Terraform 中迭代嵌套map
  • 演讲比赛流程管理项目c++
  • 网络互连与互联网4
  • 人民网评:“中国传递爱而不是关税”
  • “万人大院”重组,上海交大校长丁奎岭:人才培养事关生存发展,再难也要改
  • 42岁北京大学科学技术与医学史系副教授陈昊逝世
  • 新疆大学迎来新校长
  • 国家统计局:一季度房地产止跌回稳的政策效果持续显现,市场交易继续改善
  • 电视直播曝光苏州丝绸展览馆虚假宣传:节目还在播,执法人员已到场查处