pytorch入门级项目--基于卷积神经网络的数字识别

文章目录

前言

本篇博客主要针对pytorch入门级的教程,实现了一个基于卷积神经网络(CNN)架构的数字识别,带你了解由数据集到模型验证的全过程。

1.数据集的介绍

MNIST数据集是一个广泛用于机器学习和计算机视觉领域的手写数字图像数据集。它是深度学习入门的经典数据集,常用于图像识别任务,特别是手写数字识别。该数据集分为训练集和测试集:

  • 训练集:包含60,000张手写数字图像,用于模型的训练。
  • 测试集:包含10,000张手写数字图像,用于模型的评估。

2.数据集的准备

Torchvision在torchvision. datasets模块中提供了许多内置数据集,其中便包含了MNIST数据集,因此可以直接通过torchvision. datasets直接下载。

  • root代表存储路径,此处采用的是相对路径,保存在当前文件所在文件夹的data文件夹下
  • train用来区分训练集和测试集
  • download用来表示是否下载数据集

同时我们可以查看其中一条数据,看看该数据及具体形式

python 复制代码
import torchvision
trainset=torchvision.datasets.MNIST(root='./data',train=True,download=True)
testset=torchvision.datasets.MNIST(root='./data',train=False,download=True)
trainset[0]

这里我的数据集已经下载好了,所以很快执行好了
(<PIL.Image.Image image mode=L size=28x28>, 5)通过输出我们可以发现,第一条数据是一个元组,第一个元素表示data(灰度图,大小28*28),第二个元素表示label,指的是该图片的类别,下面我们可以查看每个类别的含义

因此我们可以看到第一张图片表示的就是手写数字5,也可以通过trainset[0][0].show()进行显示

在进行后续操作前,需要将图片格式由PIL调整为tensor类型。

python 复制代码
import torchvision
trainset=torchvision.datasets.MNIST(root='./data',train=True,download=True,transform=torchvision.transforms.ToTensor())
testset=torchvision.datasets.MNIST(root='./data',train=False,download=True,transform=torchvision.transforms.ToTensor())
trainset[0][0].shape

至此,数据集准备阶段就算完成了。

3.数据集的加载

在训练深度学习模型时,通常不会一次性将整个数据集输入到模型中,而是将数据集分成多个小批量(mini-batches)进行训练。

python 复制代码
import torch

trainloader=torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2)
testloader=torch.utils.data.DataLoader(testset,batch_size=64,shuffle=False)
type(trainloader),len(trainloader),len(trainset)
  • batch_size:表示批量大小
  • shuffle:表示是否打乱,一般训练集打乱,测试集打乱不打乱都可以
  • num_workers:表示多个进程,windows系统可能报错
    这里提供解决windows系统中多进程报错的可能解决方案:
    加上if __name__ == '__main__':即可,如果你是用的是jupyter,不用此操作

此时,我们取出一条数据查看类型:

此时我们可以看到,一条数据为torch.Size([64, 1, 28, 28]),64表示批量大小,1表示该图像单通道,即为灰度图,28*28表示图像大小

我们可以通过tensorboard,查看当前批量的图片

python 复制代码
from torch.utils.tensorboard import SummaryWriter

writer=SummaryWriter("./logs")
steps=0
for data in trainloader:
    # print(data[0].shape)
    # break
    images,labels=data
    writer.add_images('mnist_images',images,steps)
    steps+=1
writer.close()

此处在环境中需要装tensorboard

powershell 复制代码
conda install tensorboard

或者

powershell 复制代码
pip install tensorboard

然后在终端执行

powershell 复制代码
tensorboard --logdir=logs

即可

4.自定义网络模型

这里我们随便选了一张网络结构图,也可以自行设计

来源:图片来源

4.1卷积操作

这里简单介绍一下卷积的运算方式

4.2池化操作

池化层是子采样的一种具体实现方式,这里我们介绍最大池化

4.3模型搭建

  1. 由图可知,第一层卷积,输入通道数为1(原始图像为灰度图),输出通道数为6,因为图像大小未发生改变,所以padding=2
  2. 第二层池化,本文使用的是最大池化
  3. 第三层卷积,输入通道数为6(上一层卷积的输出),输出通道数为16(由图),因为图像大小未发生改变,所以padding=2
  4. 第四层池化,使用最大池化
  5. 全连接层,图示定义了两层
  6. 定义前向传播函数
  7. 输出网络结构
python 复制代码
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        # 第一层卷积层
        self.conv1=torch.nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,padding=2)
        # 第一层池化层
        self.pool1=torch.nn.MaxPool2d(kernel_size=2,stride=2)
        # 第二层卷积层
        self.conv2=torch.nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5,padding=2)
        # 第二层池化层
        self.pool2=torch.nn.MaxPool2d(kernel_size=2,stride=2)
        # 全连接层
        self.fc1=torch.nn.Linear(in_features=16*7*7,out_features=84)
        self.fc2=torch.nn.Linear(in_features=84,out_features=10)

    def forward(self,x):
        x=self.pool1(torch.nn.functional.relu(self.conv1(x)))
        x=self.pool2(torch.nn.functional.relu(self.conv2(x)))
        x=x.view(-1,16*7*7)
        x=torch.nn.functional.relu(self.fc1(x))
        x=self.fc2(x)
        return x
net=Net()
net

5.模型训练

5.1选择损失函数和优化器

对于分类问题,一般选用交叉熵损失CrossEntropyLoss(),优化器此处我们选用随机梯度下降SGD

5.2训练

我们先对训练集进行一轮训练

python 复制代码
running_loss=0
for i,data in enumerate(trainloader,1):
    inputs,labels=data
    outputs=net(inputs)
    loss=criterion(outputs,labels)
    running_loss+=loss
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if i%100==0:
        print('epoch:{} loss:{}'.format(i,running_loss/100))
        running_loss=0

我们发现loss持续下降,我们训练十轮

python 复制代码
running_loss=0
for epoch in range(10):
    for i,data in enumerate(trainloader,1):
        inputs,labels=data
        outputs=net(inputs)
        loss=criterion(outputs,labels)
        running_loss+=loss
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if i%100==0:
            print('[%d,%5d] loss:%.3f'%(epoch+1,i,running_loss/100))
            running_loss=0.0
print('Finished Training')

6.模型的保存

7.模型的验证

此处我们选择test数据集一个批次验证

计算整体上的正确率

python 复制代码
correct=0
total=0
with torch.no_grad():
    for data in testloader:
        images,labels=data
        outputs=net2(images)
        _,predicted=torch.max(outputs.data,1)
        total+=labels.size(0)
        correct+=(predicted==labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

结语

本篇博客通过训练卷积神经网络CNN模型,实现了对数字的识别,希望对你有所帮助

相关推荐
三声三视10 小时前
75 条文章索引被一条 add 清成 1 条,退出码还是 0:tri-article 的 index.py 我读了 205 行
人工智能·ai·skill·tri-skills·tri-article
蓝速科技11 小时前
医院导诊 AI 数字人一体机场景适配与落地指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理·技术分享
QYR-分析11 小时前
重轨受电弓行业深度报告:市场格局、技术迭代与发展前景
大数据·数据库·人工智能
火山引擎开发者社区11 小时前
# 开发者集结!共探 AI Agent 创新应用新可能
人工智能
牛油果子哥q11 小时前
生产级AI项目上线全流程:Docker容器化、服务编排、监控告警、日志收集、容灾降级、线上运维闭环
人工智能·ai
Pocker_Spades_A11 小时前
视频不用再一张张截图:ClipSketch AI 把关键画面转成漫画,还能顺手生成文案
人工智能·音视频
小小测试开发11 小时前
LLM 结构化输出测试:Schema 契约 + 故障注入,让工具调用的 JSON 不再靠重试赌运气
人工智能·json
阿里云大数据AI技术11 小时前
淘宝直播 AI 分身:基于阿里云 Milvus 的商品知识召回实践
人工智能
猎头南楼11 小时前
大模型后训练与 Agent 自迭代:两类工程能力的观察
人工智能·深度学习·机器学习
镜像视界(浙江)科技有限公司11 小时前
《视频孪生之上:二维展示终结,三维空间计算重构城市逻辑》——跨摄像连续表达 × 三角测量厘米级定位 × 动态轨迹建模,构建新一代城市空间
大数据·人工智能·算法·矩阵·音视频·空间计算