pytorch入门级项目--基于卷积神经网络的数字识别
文章目录
- 前言
- 1.数据集的介绍
- 2.数据集的准备
- 3.数据集的加载
- 4.自定义网络模型
- 4.1卷积操作
- 4.2池化操作
- 4.3模型搭建
- 5.模型训练
- 5.1选择损失函数和优化器
- 5.2训练
- 6.模型的保存
- 7.模型的验证
- 结语
前言
本篇博客主要针对pytorch入门级的教程,实现了一个基于卷积神经网络(CNN)架构的数字识别,带你了解由数据集到模型验证的全过程。
1.数据集的介绍
MNIST数据集是一个广泛用于机器学习和计算机视觉领域的手写数字图像数据集。它是深度学习入门的经典数据集,常用于图像识别任务,特别是手写数字识别。该数据集分为训练集和测试集:
- 训练集:包含60,000张手写数字图像,用于模型的训练。
- 测试集:包含10,000张手写数字图像,用于模型的评估。
2.数据集的准备
Torchvision在torchvision. datasets
模块中提供了许多内置数据集,其中便包含了MNIST数据集,因此可以直接通过torchvision. datasets
直接下载。
root
代表存储路径,此处采用的是相对路径,保存在当前文件所在文件夹的data文件夹下train
用来区分训练集和测试集download
用来表示是否下载数据集
同时我们可以查看其中一条数据,看看该数据及具体形式
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
类型。
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)进行训练。
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,查看当前批量的图片
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
conda install tensorboard
或者
pip install tensorboard
然后在终端执行
tensorboard --logdir=logs
即可
4.自定义网络模型
这里我们随便选了一张网络结构图,也可以自行设计
来源:图片来源
4.1卷积操作
这里简单介绍一下卷积的运算方式
4.2池化操作
池化层是子采样的一种具体实现方式,这里我们介绍最大池化
4.3模型搭建
- 由图可知,第一层卷积,输入通道数为1(原始图像为灰度图),输出通道数为6,因为图像大小未发生改变,所以padding=2
- 第二层池化,本文使用的是最大池化
- 第三层卷积,输入通道数为6(上一层卷积的输出),输出通道数为16(由图),因为图像大小未发生改变,所以padding=2
- 第四层池化,使用最大池化
- 全连接层,图示定义了两层
- 定义前向传播函数
- 输出网络结构
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训练
我们先对训练集进行一轮训练
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持续下降,我们训练十轮
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数据集一个批次验证
计算整体上的正确率
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模型,实现了对数字的识别,希望对你有所帮助