tnblog
首页
视频
资源
登录

Pytorch 识别手写数字(易化学习笔记三)

1311人阅读 2024/6/9 20:11 总访问:3475667 评论:0 收藏:0 手机
分类: python

Pytorch 识别手写数字(易化学习笔记三)

识别手写数字

LeNet-5


手写数字识别的非常高效的卷积神经网络。
高效原因:
1.用卷积核(局部连接,共享权重,平移不变性) -> 提取关键特征,参数大幅减少
2.不断降维后,仍能保留关键特征(识别成功)
64*28*28 -> 6*28*28 -> 6*14*14 -> 16*10*10 -> 16*5*5 -> 120 -> 84 -> 10
用卷积 减少图片张数(64 -> 6) 用池化减少图片大小(28->14 -> 10 -> 5 -> 1)
用全连接层 把三维的矩阵降为 一维 (1655 ->120)
两层全连接层,是借鉴
softmax 取10个中做大概率的。

训练模型


创建一个q1.py的文件。

  1. import torch
  2. import torchvision
  3. import torch.nn as nn
  4. # 超参数设置
  5. # 训练轮数
  6. EPOCH = 8
  7. # 批处理尺寸(每批用64个图片)
  8. BATCH_SIZE = 64
  9. # 学习率
  10. LR = 0.001
  11. ## 数据载入
  12. # 归一化,转为[0,1.0] shape[C,H,W]的张量
  13. # trans = torchvision.transforms.ToTensor()
  14. #(优化方式) 3.正则化 -> 加弹性余量
  15. # 在输入数据的预处理里,加入正则化Normalize
  16. trans = torchvision.transforms.Compose( # 转换的集合
  17. [
  18. torchvision.transforms.ToTensor(), # 归一化,转为[0,1.0] shape[C,H,W]的张量
  19. torchvision.transforms.Normalize([0.5], [0.5]) # 正则化(均值=0.5,标准差=0.5)
  20. ]
  21. )
  22. # 获取手写数字的训练集(pytorch已整理好的,其中都是28*28的图片)
  23. train_data = torchvision.datasets.MNIST(
  24. root="./data", # 设置数据集的所在目录
  25. train=True, # 是训练集
  26. transform=trans, # 设置转换函数
  27. download=True # True:无则下载数据集
  28. )
  29. # 获取手写数字的测试集
  30. test_data = torchvision.datasets.MNIST(
  31. root="./data/",
  32. train=False, # 是测试集
  33. transform=trans,
  34. download=True
  35. )
  36. # 载入训练集
  37. train_loader = torch.utils.data.DataLoader(
  38. dataset=train_data, # 指定数据集载入
  39. batch_size=BATCH_SIZE, # 每批数目(每次从数据集中取出 送入模型的训练的样本数)
  40. shuffle=True) # 乱序(取样本时)
  41. # 载入测试集
  42. test_loader = torch.utils.data.DataLoader(
  43. dataset=test_data,
  44. batch_size=BATCH_SIZE,
  45. shuffle=True)
  46. ## 构建模型
  47. # 定义网络结构
  48. class LeNet(nn.Module):
  49. def __init__(self):
  50. super(LeNet, self).__init__()
  51. # 卷积层: 由下面3层添加到顺序容器Sequential中而成
  52. self.conv1 = nn.Sequential(
  53. nn.Conv2d(1, 6, 5, 1, 2), # /*2维卷积层: input_size=(1*28*28) -> 特征过滤(降维)
  54. # 右键可查看API,参数未输入的将采用默认值
  55. # 如 class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
  56. # 输入通道: 1张灰度图 input_size=(1*28*28),图片需是28*28的
  57. # 输出通道: 6张特征图 (从不同角度看,得到不同特征图,如从轮廓,明暗效果,纹理等,可定义许多个)
  58. # 一个卷积核 ,过滤出一张特征图,输出6张特征图,就对应6个卷积核
  59. # 卷积核大小: 5x5 高宽相等可只写一个
  60. # 滑动步长: 1步
  61. # 填充: 2 -> 图边用2圈0填充(卷积后尺寸会变小,图边可用零填充,保证尺寸相同)
  62. # 注:为维持输出图片尺寸不变 由公式 O=(I-F+2P)/S+1=(28-5+2*2)/1+1 = 28
  63. # 如是32*32图片 需公式来O=(I-F+2P)/S+1调整 变为Conv2d(1, 6, 5)
  64. # */
  65. nn.ReLU(), # 激活层: input_size=(6*28*28) -> 引入非线性(可挑选信息)
  66. nn.MaxPool2d(kernel_size=2, stride=2),#/*池化层(最值):
  67. # output_size=(6*14*14) -> 舍去非显著特征,减少参数,缓解过拟合
  68. # O=(I-F+2P)/S+1 = (28-2+2*0)/2 + 1 = 14
  69. #*/
  70. )
  71. self.conv2 = nn.Sequential(
  72. nn.Conv2d(6, 16, 5), # input_size=(6*14*14) O=(I-F+2P)/S+1=(14-5+2*0)/1+1 = 10
  73. nn.ReLU(), # input_size=(16*10*10)
  74. nn.MaxPool2d(2, 2) # output_size=(16*5*5) O=(I-F+2P)/S+1=(10-2+2*0)/2+1 = 5
  75. )
  76. # 全连接层 (in:16*5*5 out:120)
  77. self.fc1 = nn.Sequential(
  78. nn.Linear(16 * 5 * 5, 120),
  79. # (优化方案)2.加入dropout 随机断开 -> 增加随机性(防过拟合)
  80. nn.Dropout(0.5), # 随机50%的断开
  81. nn.ReLU()
  82. )
  83. self.fc2 = nn.Sequential(
  84. nn.Linear(120, 84),
  85. nn.ReLU()
  86. )
  87. self.fc3 = nn.Linear(84, 10)
  88. # 前向传播函数: 一旦构建前向传播网络成功,反向传播函数也会自动生成(autograd)
  89. def forward(self, x):
  90. x = self.conv1(x)
  91. x = self.conv2(x)
  92. # print(x.shape) torch.Size([64, 16, 5, 5]) 每批64张图片 输出16张 5*5的特征图
  93. # 扁平化:行64张 列-1自动推导,把16张 5*5的特征图压平为一维的点 -> 方便对接全连接层
  94. x = x.view(x.shape[0], -1)
  95. x = self.fc1(x)
  96. x = self.fc2(x)
  97. x = self.fc3(x)
  98. return x
  99. # 没有gpu则使用cpu
  100. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  101. # 新建模型到设备上(gpu/cpu)
  102. net = LeNet().to(device)
  103. # 使用交叉熵损失函数(通常用于多分类问题上)
  104. criterion = nn.CrossEntropyLoss()
  105. # 采用SGD的优化器
  106. # 在优化器中加L2正则化(weight_decay=0.01 指权重衰减 惩罚%1)
  107. optimizer = torch.optim.Adam(net.parameters(), lr=LR)
  108. ## 训练评估
  109. for epoch in range(EPOCH):
  110. sum_loss = 0.0
  111. # enumerate 遍历列表对象,加上序号i
  112. for i, data in enumerate(train_loader):
  113. # 准备
  114. # inputs:手写数字图片 labels:图片对应的数字标签
  115. inputs, labels = data
  116. # 把数据传入设备中(如GPU)
  117. inputs, labels = inputs.to(device), labels.to(device)
  118. # 梯度清零: 每次迭代都需梯度清零,因pytorch默认会累积梯度
  119. optimizer.zero_grad()
  120. # 向前传播
  121. # 模型对输入进行预测
  122. preds = net(inputs)
  123. # 计算损失
  124. loss = criterion(preds, labels)
  125. # 向后传播
  126. # 反向传播,计算梯度
  127. loss.backward()
  128. # 按学习率减去少量梯度来调整权重
  129. optimizer.step()
  130. # 每训练100个batch打印一次平均loss
  131. sum_loss += loss.item()
  132. if i % 100 == 99:
  133. print('[%d, %d] loss: %.03f'%(epoch + 1, i + 1, sum_loss / 100))
  134. sum_loss = 0.0
  135. # 每跑完一次epoch测试一下准确率
  136. with torch.no_grad():
  137. correct = 0
  138. total = 0
  139. for data in test_loader:
  140. images, labels = data
  141. images, labels = images.to(device), labels.to(device)
  142. outputs = net(images)
  143. # 取得分最高的那个类
  144. _, predicted = torch.max(outputs.data, 1)
  145. # 标签总数: 累加每批取的标签数
  146. total += labels.size(0)
  147. # 预测正确的样本数
  148. correct += (predicted == labels).sum()
  149. # 统计正确率
  150. print('第%d个epoch的识别准确率为:%d%%' % (epoch + 1, (100 * correct / total)))
  151. torch.save(net.state_dict(), "mnist_2d.pth") # 保存模型参数(推荐)
  152. # 优点: 速度快,占空间少,
  153. # 缺点: 重加载时需自定义model,且参数需与保存的模型的一致,
  154. # 可以只是部分网络,相对灵活,便于对网络进行修改
  155. # torch.save(net, 'net_model.pth') # 可直接保存模型(不建议),这里略过

数据预处理


从网上找一张图片,然后编写q2.py文件。

  1. ## 数据预处理
  2. import cv2 # 导入opencv库
  3. import matplotlib.pyplot as plt
  4. #pic ='8.bmp' # 待识别的图片名
  5. pic ='4.jpeg'
  6. img = cv2.imread(pic) # 读取图片
  7. # 数据预处理(转换为与训练集相同的格式)
  8. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 彩色图片转为灰度图片
  9. img = 255 - img # 黑白反转(官方mnist集合里黑白是反的)
  10. img = cv2.resize(img,(28,28),interpolation = cv2.INTER_AREA) # 转换为与训练集图片相同的尺寸
  11. img = img.reshape(1,28,28) # 转换为与训练集相同格式 1个 28*28像素的 测试图像
  12. img =img/255.0 # 除以255为了归一化,加.0 转为浮点数 ->避免数据溢出
  13. # 查看图片数据
  14. print(img.shape)
  15. for i in range(28):
  16. for j in range(28):
  17. print(format(img[0][i][j],'.1f'),end="") # 0:0号图 i:图的行号 j:图的列号 end=""不换行
  18. # .1f: 限制float小数点后的显示位数为1位
  19. print('E')
  20. # 显示图片
  21. plt.imshow(img[0], cmap=plt.get_cmap('gray')) # cmap: 颜色图谱 gray:黑白色
  22. plt.show()

预测数据


接着我们刚刚的代码添加如下代码进行预测数据。

  1. ## 载入模型参数
  2. # 定义网络结构
  3. class LeNet(nn.Module):
  4. def __init__(self):
  5. super(LeNet, self).__init__()
  6. self.conv1 = nn.Sequential(
  7. nn.Conv2d(1, 6, 5, 1, 2),
  8. nn.ReLU(),
  9. nn.MaxPool2d(kernel_size=2, stride=2),
  10. )
  11. self.conv2 = nn.Sequential(
  12. nn.Conv2d(6, 16, 5),
  13. nn.ReLU(),
  14. nn.MaxPool2d(2, 2)
  15. )
  16. self.fc1 = nn.Sequential(
  17. nn.Linear(16 * 5 * 5, 120),
  18. nn.Dropout(0.5),
  19. nn.ReLU()
  20. )
  21. self.fc2 = nn.Sequential(
  22. nn.Linear(120, 84),
  23. nn.ReLU()
  24. )
  25. self.fc3 = nn.Linear(84, 10)
  26. def forward(self, x):
  27. x = self.conv1(x)
  28. x = self.conv2(x)
  29. x = x.view(x.shape[0], -1)
  30. x = self.fc1(x)
  31. x = self.fc2(x)
  32. x = self.fc3(x)
  33. return x
  34. # 没有gpu则使用cpu
  35. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  36. # 新建模型到设备上(gpu/cpu)
  37. model = LeNet().to(device)
  38. # 加载已训练好的模型参数
  39. model.load_state_dict(torch.load('mnist_2d.pth'))
  40. # 可用载入模型torch.load('模型名'),一般不推荐使用,略过
  41. ## 预测评估
  42. # 评估模式
  43. model.eval()
  44. # 转为torch 的张量格式
  45. img = torch.tensor(img)
  46. # 升维为 torch.Size([1, 1, 28, 28]) -> 满足model对输入格式要求
  47. img = img.unsqueeze(0)
  48. # 需与模型的元素类型匹配
  49. images =img.to(torch.float32)
  50. images = images.to(device)
  51. print("image shap=",images.shape)
  52. print("image dtype=",images.dtype)
  53. outputs = model(images) # 用模型预测,
  54. # 注:输入数据要求是4维,如 torch.Size([64, 1, 28, 28])
  55. # 输出10个数字的概率
  56. print(outputs)
  57. # 取概率最高的
  58. _, predicted = torch.max(outputs.data, 1)
  59. # 预测值
  60. print(predicted)


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

Pytorch 初探

Pytorch 初探[TOC] Pytorch简介PyTorch由 Facebook 的 AI 研究团队开发的一个开源的机器学习库,它提供了张量(tensor)计...

Pytorch 自动求导与简单的线性回归

Pytorch 自动求导与简单的线性回归[TOC] 环境安装安装pytorch%pip install torch torchvision torchaudio 自动计算反向...

Pytorch Tensor 常见的形式

Pytorch Tensor 常见的形式[TOC] 值 描述 scalar 0维张量 vector 1维张量 matrix 2维张量 ...

Pytorch 气温预测

Pytorch 气温预测[TOC] 准备数据集下载temps.csv数据集。# 下载包 !wget https://raw.githubusercontent.com/AiDaShi/lea...

Pytorch Mnist分类任务

Pytorch Mnist分类任务[TOC] Mnist分类任务了解目标——网络基本构建与训练方法,常用函数解析——torch.nn.functional...

Pytorch 卷积神经网络效果

Pytorch 卷积神经网络效果[TOC] 数据与在线实践数据链接: https://pan.baidu.com/s/1VkrHDZGukkF900zLncMn5g 密码: 3lom...

Pytorch 基于经典网络架构训练图像分类模型

Pytorch 基于经典网络架构训练图像分类模型[TOC] 数据预处理部分:数据增强:torchvision中transforms模块自带功能,比较...

Pytorch 卷积神经网络效果

Pytorch 卷积神经网络效果[TOC] 数据集Dataloader制作如何自定义数据集:1.数据和标签的目录结构先搞定(得知道到哪读数据)...

Pytorch 新闻分类任务学习笔记

Pytorch 新闻分类任务(学习笔记)[TOC] 目录结构 models文件夹该文件夹显示搭建的网络结构。里面有TextCNN.py和TextRNN....

Pytorch Flask服务部署图片识别学习笔记

Pytorch Flask服务部署图片识别(学习笔记)[TOC] Flask 简介Flask是一个用Python编写的轻量级Web应用框架。它简单易用,...

Pytorch 预测产量易化学习笔记一

Pytorch 预测产量(易化学习笔记一)[TOC] 实验目的(二维)通过温度进行产量预测。 实验代码导入数据集import torch im...

Pytorch 曲线拟合易化学习笔记二

Pytorch 曲线拟合(易化学习笔记二)[TOC] 感染与天数预测import matplotlib.pyplot as plt import torch import torch....

Pytorch cifar10识别普适物体易化学习笔记四

Pytorch cifar10识别普适物体(易化学习笔记四)[TOC] CIFAR-10简介CIFAR-10(Canadian Institute For Advanced Research...

Pytorch loguru日志收集易化学习笔记五

Pytorch loguru日志收集(易化学习笔记五)[TOC] loguru日志简介Loguru 是一个 Python 日志库,旨在简化日志记录的设置和...

Pytorch TensorBoard运用易化学习笔记六

Pytorch TensorBoard运用(易化学习笔记六)[TOC] TensorBoard简介TensorBoard是TensorFlow的可视化工具包,旨在帮助研究...
这一世以无限游戏为使命!
排名
2
文章
636
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术