欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 深度学习--mnist数据集实现卷积神经网络的手写数字识别

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

2025/4/24 4:05:33 来源:https://blog.csdn.net/m0_65065095/article/details/147351871  浏览:    关键词:深度学习--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)

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


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词