完整代码下载【github地址】:https://github.com/lmn-ning/MNIST_PyTorch.git

目录

  • 一、MNIST数据集介绍及下载地址
  • 二、代码结构
  • 三、代码
    • dataset.py
    • cnn.py
    • train.py
    • eval.py
  • 四、代码运行命令及测试精度

一、MNIST数据集介绍及下载地址

MNIST手写数字识别可以说是机器学习入门的hello word了, MNIST数据集包含70000张手写数字图像:,其中60000张用于训练,10000张用于测试。

官网下载地址:http://yann.lecun.com/exdb/mnist/

MNIST数据集共有四个文件:

train-images-idx3-ubyte.gz:训练集图片,60000张。

train-labels-idx1-ubyte.gz:训练集图片对应的标签。

t10k-images-idx3-ubyte .gz:测试集图片,10000张。

t10k-labels-idx1-ubyte.gz:测试集图片对应的标签。

图片是0〜9的手写数字图片,共10类,标签是图片的实际数字。每张图片都是28x28的单通道灰度图,且数字居中以减少预处理和加快运行。

可以自己下载数据集并加载迭代器,也可以使用torchvision自带的下载函数进行在线下载。

二、代码结构


data:torchvision在线下载的数据集(程序用的是这个方法)
MNIST:自己下载的数据集(在程序里面没有用到)
save_model:用于存放保存的模型参数的pt文件
dataset.py:数据处理脚本
cnn.py:网络模型脚本
train:训练和测试脚本
eval:验证脚本

三、代码

dataset.py

# 日期:2021年07月17日
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision import transforms as tsf
import cv2batch_size = 64
transform = tsf.Compose([tsf.ToTensor(), tsf.Normalize([0.1307], [0.3081])])
# Normalize:正则化,降低模型复杂度,防止过拟合# 下载数据集
# torchvision已经预先实现了常用的Dataset,包括MINST。可以用datasets.MNIST直接从网上下载,并自动建立名为data的文件夹。
train_set=datasets.MNIST(root="data",train=True,download=True,transform=transform)
test_set=datasets.MNIST(root="data",train=False,download=True,transform=transform)# 加载数据集,将数据集变成迭代器
def get_data_loader():train_loader=DataLoader(dataset=train_set,batch_size=batch_size,shuffle=True)test_loader=DataLoader(dataset=test_set,batch_size=batch_size,shuffle=True)return train_loader,test_loader# 显示数据集中的图片
# with open("data/MNIST/raw/train-images-idx3-ubyte","rb") as f:
#     file=f.read()
#     image1=[int(str(item).encode('ascii'),16) for item in file[16:16+784]]
#     image1_np=np.array(image1,dtype=np.uint8).reshape(28,28,1)
#     cv2.imshow("image1_np",image1_np)
#     cv2.waitKey(0)

cnn.py

# 日期:2021年07月17日
import torch.nn as nn
import torch.nn.functional as Fclass CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.conv1 = nn.Conv2d(in_channels=1, out_channels=10, kernel_size=(5,5))self.conv2 = nn.Conv2d(10, 20, kernel_size=(3,3))self.fc1 = nn.Linear(in_features=20*10*10, out_features=500)self.fc2 = nn.Linear(500, 10)def forward(self, x):# x.shape = batch_size * channels( = 1) *28 * 28input_size=x.size(0)   # 获取batch_sizex=self.conv1(x)# input:batch_size * 1 * 28 * 28   (in_channels=1, out_channels=10)# oouput:batch_size * 10 * 24 * 24  (24=28-5+1)x=F.relu(x)# 激活函数保持shape不变# 激活函数使神经网络变成非线性,解决线性模型所不能解决的问题。x=F.max_pool2d(x,kernel_size=2,stride=2)# input:batch_size * 10 * 24 * 24# output:batch_size * 10 * 12 * 12    (stride=2,因此尺寸减半)x=self.conv2(x)# input:batch_size * 10 * 12 * 12   (in_channels=1, out_channels=10)# output:batch_size * 20 * 10 * 10  (10=12-3+1)x=F.relu(x)x=x.view(input_size,-1)# view()中,当某一维是-1时,会根据给定维度自动计算它的大小# 因此-1表示的维度是: batch_size * 20 * 10 * 10 / batch_size = 20 * 10 * 10 =2000x=self.fc1(x)# input:batch_size * 2000# output:batch_size * 500x=F.relu(x)x=self.fc2(x)# input:batch_size * 500# output:batch_size * 10    变成十分类output=F.log_softmax(x,dim=1)# 计算x属于每个分类的概率# dim=1表示按行计算return output

train.py

# 日期:2021年07月17日
import torch
import cnn
import torch.nn.functional as F
from dataset import get_data_loader
import torch.optim as optimif __name__ == "__main__":# 超参batch_size=64device=torch.device("cuda" if torch.cuda.is_available() else "cpu")epoch = 5# 选择模型model=cnn.CNN().to(device)# 定义优化器optimizer=optim.Adam(model.parameters())# 加载迭代器train_loader, test_loader = get_data_loader()# 训练def train(epoch_i):model.train()   # 设置为训练模式for batch_i,(digit,label) in enumerate(train_loader):digit,label=digit.to(device),label.to(device)optimizer.zero_grad()    # 梯度初始化为0output=model(digit)     # 训练结果,output是概率loss=F.cross_entropy(output,label)     # 定义损失函数,交叉熵损失函数适用于多分类问题loss.backward()    # 反向传播optimizer.step()    # 更新参数if batch_i % 100 == 0:print("train    epoch_i: {}    batch_i: {}    loss: {: .8f}".format(epoch_i,batch_i,loss.item()))# 测试def test(epoch_i):model.eval()    # 设置为测试模式acc = 0.loss = 0.with torch.no_grad():for digit, label in test_loader:digit, lable = digit.to(device), label.to(device)output = model(digit)  # 模型输出loss += F.cross_entropy(output, lable).item()predict = output.max(dim=1, keepdim=True)[1]# 找到概率最大值的下标,1表示按行计算。# max()返回两个值,第一个是值,第二个是索引,所以取 max[1]acc += predict.eq(label.view_as(predict)).sum().item()accuracy = acc / len(test_loader.dataset) * 100test_loss = loss / len(test_loader.dataset)print("test     epoch_i: {}    loss: {: .8f}    accuracy: {: .4f}%".format(epoch_i,test_loss,accuracy))# train && testfor epoch_i in range(1,epoch+1):train(epoch_i)test(epoch_i)# 保存模型torch.save(model,"save_model/model.pt")

eval.py

# 日期:2021年07月17日
import torch
from dataset import get_data_loaderif __name__ == "__main__":_, eval_loader = get_data_loader()   # 因为没有验证集,所以将测试题作为验证集使用。batch_size = 64device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = torch.load("save_model/model.pt")    # 加载模型# model.eval()  # 设置为验证模式acc = 0.  with torch.no_grad():for digit, label in eval_loader:digit, lable = digit.to(device), label.to(device)output = model(digit)  # 模型输出predict = output.max(dim=1, keepdim=True)[1]# 找到概率最大值的下标,1表示按行计算。# max()返回两个值,第一个是值,第二个是索引,所以取 max[1]acc += predict.eq(label.view_as(predict)).sum().item()acceracy = acc/len(eval_loader.dataset) * 100print("eval accuracy: {: .4f}%".format(acceracy))

四、代码运行命令及测试精度

训练:python train.py
验证:python eval.py

训练精度:

test     epoch_i: 1    loss:  0.00083338    accuracy:  98.2700%
test     epoch_i: 2    loss:  0.00053913    accuracy:  98.8400%
test     epoch_i: 3    loss:  0.00059983    accuracy:  98.8800%
test     epoch_i: 4    loss:  0.00063796    accuracy:  98.7200%
test     epoch_i: 5    loss:  0.00056076    accuracy:  98.8800%

验证精度:

eval accuracy:  98.8800%

因为MNIST数据集没有单独的验证集,所以将测试集当做验证集使用。保存的模型是最后一个epoch的模型。因此eval accuracy与最后一个epoch的test accuracy相同。

这个程序只是为了熟悉pytorch深度学习的基本流程,训练集的选择和精度并不重要。

深度学习入门项目:PyTorch实现MINST手写数字识别相关推荐

  1. 深度学习面试题12:LeNet(手写数字识别)

    目录 神经网络的卷积.池化.拉伸 LeNet网络结构 LeNet在MNIST数据集上应用 参考资料 LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务.自那时起 ...

  2. 深度学习笔记:07神经网络之手写数字识别的经典实现

    神经网络之手写数字识别的经典实现 上一节完成了简单神经网络代码的实现,下面我们将进行最终的实现:输入一张手写图片后,网络输出该图片对应的数字.由于网络需要用0-9一共十个数字中挑选出一个,所以我们的网 ...

  3. 深度学习第一周 tensorflow实现mnist手写数字识别

  4. minst手写数字识别(带界面)

    minst手写数字识别(带界面) 目录 minst手写数字识别(带界面) 一.项目简介 二.项目结构及环境 三.网络结构介绍 四.程序文件介绍 五.使用介绍 六.源代码获取 一.项目简介 1)概述:手 ...

  5. Pytorch实现mnist手写数字识别

    2020/6/29 Hey,突然想起来之前做的一个入门实验,用pytorch实现mnist手写数字识别.可以在这个基础上增加网络层数,或是尝试用不同的数据集,去实现不一样的功能. Mnist数据集如图 ...

  6. 用PyTorch实现MNIST手写数字识别(非常详细)

    ​​​​​Keras版本: Keras入门级MNIST手写数字识别超级详细教程 2022/4/17 更新修复下代码.完善优化下文章结构,文末提供一个完整版代码. 可以在这里下载源码文件(免积分): 用 ...

  7. 深度学习练手项目(一)-----利用PyTorch实现MNIST手写数字识别

    一.前言 MNIST手写数字识别程序就不过多赘述了,这个程序在深度学习中的地位跟C语言中的Hello World地位并驾齐驱,虽然很基础,但很重要,是深度学习入门必备的程序之一. 二.MNIST数据集 ...

  8. 全连接神经网络——MINST手写数字识别

    简介 本文构建了一个全连接神经网络(FCN),实现对MINST数据集手写数字的识别,没有借助任何深度学习算法库,从原理上理解手写数字识别的全过程,包括反向传播,梯度下降等.最终的代码总行数不超过200 ...

  9. Python学习记录 搭建BP神经网络实现手写数字识别

    搭建BP神经网络实现手写数字识别 通过之前的文章我们知道了,构建一个简单的神经网络需要以下步骤 准备数据 初始化假设 输入神经网络进行计算 输出运行结果 这次,我们来通过sklearn的手写数字数据集 ...

最新文章

  1. 下一代搜索引擎长啥样?Google 给出了TA的答案
  2. Docker学习笔记之在开发环境中使用服务发现
  3. mysql 散列存储_什么是数据库散列存储? - 蚂蚁吞大象的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  4. LeetCode(40):组合总和 II
  5. C#执行osql脚本时部分脚本未执行
  6. swift 展示html富文本,Swift HTML富文本显示
  7. 【Luogu1095】守望者的逃离
  8. PostgreSQL视图使用特殊名称作字段时的处理
  9. 机器学习----朴素贝叶斯详解
  10. 使用media player和foobar的DLAN服务
  11. python 提取字幕_使用Python从zimuku下载字幕
  12. ML(5)——神经网络1(神经元模型与激活函数)
  13. 【SDOI2015】寻宝游戏
  14. 联想拯救者Y9000P唤醒修复
  15. Lan9252-FPGA调试笔记
  16. 2020全国计算机考试ps版本,2020年3月计算机等级Photoshop练习题及参考答案
  17. Linux查看DNS地址以及端口,nslookup命令以及更强大的dig命令
  18. vc 2005 express使用
  19. How to add the cracked dlls in GAC---let me tell u
  20. 函数、包,字符串处理,错误处理

热门文章

  1. 【JVM和性能优化】2.垃圾回收器和内存分配策略
  2. MongoDB 复制(副本集)学习
  3. 猫狗大战——数据集创建详细介绍
  4. NX二次开发 UFUN获取当前工作部件tag UF_ASSEM_ask_work_part
  5. 聚类--评估指标--轮廓系数
  6. 加密的VCD,不怕它
  7. 【报告分享】2021年10月汽车产销报告-中国汽车工业协会(附下载)
  8. cloudsim中时间共享调度策略和空间共享调度策略
  9. 用小事例来理解模糊控制、人工神经网络、PID控制等
  10. Unity创建简易小地图(顶视图)