CNN实现对手写字体的迭代

2023-12-28 19:12
文章标签 实现 cnn 字体 迭代 对手

本文主要是介绍CNN实现对手写字体的迭代,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

导入库

import torchvision
import torch
from torchvision.transforms import ToTensor
from torch import nn
import matplotlib.pyplot as plt

导入手写字体数据

train_ds=torchvision.datasets.MNIST('data/',train=True,transform=ToTensor(),download=True)
test_ds=torchvision.datasets.MNIST('data/',train=False,transform=ToTensor(),download=True)
train_dl=torch.utils.data.DataLoader(train_ds,batch_size=64,shuffle=True)
test_dl=torch.utils.data.DataLoader(test_ds,batch_size=46)
imgs,labels=next(iter(train_dl))
print(imgs.shape)
print(labels.shape)

从上述代码中可以看到,train_dl返回的图片数据是四维的,4个维度分别代表批次、通道数、高度和宽度(batch,channel,height,width),这正是PyTorch下卷积模型所需要的图片输入格式

创建卷积模型并训练

下面创建卷积模型来识别MNIST手写数据集。我们所创建的卷积模型先试用两个卷积层和两个池化层,然后将最后一个池化的输出展平为二维数据形式连接到全连接层,最后是输出层,中间的每一层都是用ReLU函数激活,输出层的输出张量长度为10,与类别数一致。代码如下

class Model(nn.Module):def __init__(self):super().__init__()self.conv1=nn.Conv2d(1,6,5)   #初始化第一个卷积层self.conv2=nn.Conv2d(6,16,5)  #初始化第二个卷积层self.liner_1=nn.Linear(16*4*4,256)  #初始化全连接层16*4*4为输入的特征,256为输出的特征#就是将一个大小为16×4×4的输入特征映射到一个大小为256的输出特征空间中self.liner_2=nn.Linear(256,10)  #初始化输出层def forward(self,input):#调用第一个卷积层和池化层x=torch.max_pool2d(torch.relu(self.conv1(input)),2)#调用第二个卷积层和池化层x=torch.max_pool2d(torch.relu(self.conv2(x)),2)# view()方法将数据展平为二维形式# torch.Size([64,16,4,4])->torch.Size([64,16*4*4])x=x.view(-1,16*4*4)x=torch.relu(self.liner_1(x))  # 全连接层x=self.liner_2(x)  #输出层return x#判断当前可用的device,如果显卡可用,就设置为cuda,否则设置为cpu
device="cuda" if torch.cuda.is_available() else "cpu"
print("Using {} device".format(device))#初始化模型,并使用.to()方法将其上传到device
#如果GPU可以用,会上传到显存,如果device是CPU,依保留在内存
model=Model().to(device)  # 初始化模型并设置设备
print(model)loss_fn=nn.CrossEntropyLoss() # 初始化交叉熵损失函数optimizer=torch.optim.SGD(model.parameters(),lr=0.001) # 初始化优化器def train(dataloader,model,loss_fn,optimizer):size=len(dataloader.dataset)  # 获取当前数据集样本总数量num_batches=len(dataloader)  #获得当前dataloader总批次数# train_loss用于累计所有批次的损失之和,correct用于累计预测正确的样本总数train_loss,correct=0,0for X,y in dataloader:  #对dataloader进行迭代X,y=X.to(device),y.to(device)  #每一批次的数据设置为使用当前device进行预测,并计算一个批次的损失pred=model(X)loss=loss_fn(pred,y)  # 返回的是平均损失#使用反向传播算法,根据损失优化模型参数optimizer.zero_grad()  #将模型参数的梯度全部归零loss.backward()  # 损失反向传播,计算模型参数梯度optimizer.step()  # 根据梯度优化参数with torch.no_grad():# correct 用于累计预测正确的样本总数correct+=(pred.argmax(1)==y).type(torch.float).sum().item()#train_loss用于累计所有批次的损失之和train_loss+=loss.item()#train_loss是所有批次的损失之和,所以计算全部样本的平均损失时需要处于总批次数train_loss/=num_batches#correct是预测正确的样本总是,若计算整个epoch总体正确率,需除以样本总数量correct/=sizereturn train_loss,correctdef test(dataloader,model):size=len(dataloader.dataset)num_batches=len(dataloader)test_loss,correct=0,0with torch.no_grad():for X,y in dataloader:X,y=X.to(device),y.to(device)pred=model(X)test_loss+=loss_fn(pred,y).item()correct+=(pred.argmax(1)==y).type(torch.float).sum().item()test_loss/=num_batchescorrect/=sizereturn test_loss,correctepochs=50  #一个epoch代表对全部数据训练一遍train_loss=[]  #每个epoch训练中训练数据集的平均损失被添加到此列表
train_acc=[] #每个epoch训练中训练数据集的平均正确率被添加到此列表
test_loss=[]  #每个epoch训练中测试数据集的平均损失被添加到此列表
test_acc=[] #每个epoch训练中测试数据集的平均正确率被添加到此列表for epoch in range(epochs):#调用train()函数训练epoch_loss,epoch_acc=train(train_dl,model,loss_fn,optimizer)#调用test()函数测试epoch_test_loss,epoch_test_acc=test(test_dl,model)train_loss.append(epoch_loss)train_acc.append(epoch_acc)test_loss.append(epoch_test_loss)test_acc.append(epoch_test_acc)#定义一个打印模版template=("epoch:{:2d},train_loss:{:.5f},train_acc:{:.1f}%,test_loss:{:.5f},test_acc:{:.1f}%")#输出当前的epoch的训练集损失、训练集正确率、测试集损失、测试集正确率print(template.format(epoch,epoch_loss,epoch_acc*100,epoch_test_loss,epoch_test_acc*100))print("Done!")plt.plot(range(1,epochs+1),train_loss,label="train_loss")
plt.plot(range(1,epochs+1),test_loss,label='test_loss',ls="--")
plt.xlabel('epoch')
plt.legend()
plt.show()plt.plot(range(1, epochs + 1), train_acc, label="train_acc")
plt.plot(range(1, epochs + 1), test_acc, label='test_acc', ls="--")
plt.xlabel('acc')
plt.legend()
plt.show()

函数式API

import torch.nn.functional as Fclass Model(nn.Module):def __init__(self):super().__init__()self.conv1=nn.Conv2d(1,6,5)   #初始化第一个卷积层self.conv2=nn.Conv2d(6,16,5)  #初始化第二个卷积层self.liner_1=nn.Linear(16*4*4,256)  #初始化全连接层16*4*4为输入的特征,256为输出的特征#就是将一个大小为16×4×4的输入特征映射到一个大小为256的输出特征空间中self.liner_2=nn.Linear(256,10)  #初始化输出层def forward(self,input):#调用第一个卷积层和池化层x=F.max_pool2d(F.relu(self.conv1(input)),2)#调用第二个卷积层和池化层x=F.max_pool2d(F.relu(self.conv2(x)),2)# view()方法将数据展平为二维形式# torch.Size([64,16,4,4])->torch.Size([64,16*4*4])x=x.view(-1,16*4*4)x=F.relu(self.liner_1(x))  # 全连接层x=self.liner_2(x)  #输出层return x

这篇关于CNN实现对手写字体的迭代的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/546995

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、