pytorch mnist手写数字识别,pytorch手写体识别

  pytorch mnist手写数字识别,pytorch手写体识别

  本文主要介绍PyTorch实现手写数字识别的示例代码。本文中的示例代码非常详细,具有一定的参考价值。感兴趣的朋友可以参考BR。

  00-1010加载手写数字的数据加载器(批量加载)建立模型,训练测试集,提取数据,检查预测结果,计算模型的精度,用自己的手写数字进行预测。

  

目录

  补训练集和测试集,这里已经下载了,所以下载是假的。

  进口火炬视觉

  #你支持gpu运算吗?

  # device=torch . device( cuda if torch . cuda . is _ available()else CPU )

  #打印(设备)

  # print(torch.cuda.is_available())

  #加载训练集的数据使用torchvision提供的MNIST数据集。

  train _ dataset=torch vision . datasets . Mn ist(root=。/data1 ,

  train=True,

  transform=torch vision . transforms . totensor(),

  下载=假

  )

  #加载测试集的数据以创建测试集

  test _ dataset=torch vision . datasets . Mn ist(root=。/data1 ,

  train=False,

  transform=torch vision . transforms . totensor(),

  下载=假

  )

  

加载手写数字的数据

  #批量加载数据一个批量有多少条数据?

  批处理大小=100

  # Create data loader shuffle为真。装的时候是炒的。

  train _ loader=data loader(dataset=train _ dataset,

  批处理大小=批处理大小,

  洗牌=真

  )

  test_loader=DataLoader(数据集=test_dataset,

  批处理大小=批处理大小,

  洗牌=真

  )

  #数据加载器生成的对象成为迭代器。

  示例=iter(test_loader)

  #使用下一个方法获取一批数据

  example_data,example_targets=examples.next()

  #遍历并获取6条数据进行展示和观察。

  对于范围(6):中的I

  情节子情节(2,3,11)

  plt.imshow(example_data[i][0],cmap=gray )

  #检查图片尺寸,方便建模时输入尺寸。

  print(example_data[i][0])。形状)

  plt.show()

  

数据加载器(分批加载)

  在建立模型之前,定义分类类别的输入大小和输出大小。

  上面看到的图片尺寸是28*28*1,所以输入尺寸是784。

  数字识别只有0~9,所以是一个10类的多分类问题。

  输入大小

  = 784

  num_classes = 10

  

  创建模型类

  

class NeuralNet(torch.nn.Module):

   def __init__(self, n_input_size, hidden_size, n_num_classes):

   """

   神经网络类初始化

   :param n_input_size: 输入

   :param hidden_size: 隐藏层

   :param n_num_classes: 输出

   """

   # 调用父类__init__方法

   super(NeuralNet, self).__init__()

   self.input_size = input_size

   # 第一层线性模型 传入输入层和隐藏层

   self.l1 = torch.nn.Linear(n_input_size, hidden_size)

   # relu激活函数层

   self.relu = torch.nn.ReLU()

   # 第二层线性模型 传入隐藏层和输出层

   self.l2 = torch.nn.Linear(hidden_size, n_num_classes)

   def forward(self, x):

   """

   重写正向传播函数 获取到预测值

   :param x: 数据

   :return: 预测值

   """

   # 线性模型

   out = self.l1(x)

   # 激活函数

   out = self.relu(out)

   # 线性模型2

   out = self.l2(out)

   # 返回预测值

   return out

  # 获取到gpu设备

  device = torch.device(cuda if torch.cuda.is_available() else cpu)

  # 创建模型并把模型放到当前支持的gpu设备中

  model = NeuralNet(input_size, 500, num_classes).to(device)

  print(model)

  

  

  

  • 可以看出模型一共三层
  • 输入层(节点数量和图小大小相同)
  • 隐藏层(节点数为500)
  • 输出层(输出节点数量为100~9

  定义损失函数和优化器

  

  • 因为是多分类问题,所以使用交叉熵函数的多分类损失函数
  • 因为传统的梯度下降存在一定缺陷,比如学习速率一直不变,所以使用PyTorch中梯度下降的优化算法Adam算法

  

# 定义学习率

  learning_rate = 0.01

  # 损失函数

  criterion = torch.nn.CrossEntropyLoss()

  # 定义优化器 参数1为模型的参数 lr为学习率

  optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

  

  

  

模型训练

  训练步骤:

  

  • 通过模型类正向传播获取到预测结果
  • 通过损失函数传入预测结果和真实值计算损失
  • 通过反向传播获取梯度
  • 通过梯度下降更新模型参数的权重
  • 梯度清空,防止下次梯度累加
  • 循环,降低损失为我们想要的结果(提高模型精度)

  

# 定义训练的次数

  num_epochs = 10

  # 训练集数据的总长度

  total_steps = len(train_loader)

  # 遍历训练次数

  for epoch in range(num_epochs):

   # 每次从数据加载器中取出一批数据 每批次100条

   for i, (images, labels) in enumerate(train_loader):

   # 把图片降维到一维数组 加载到gpu

   images = images.reshape(-1, 28 * 28).to(device)

   # 真实值加载到gpu

   labels = labels.to(device)

   # 正向传播 获取到预测值

   outputs = model(images)

   # 通过损失函数获取到损失值

   loss_val = criterion(outputs, labels)

   # 清空梯度

   optimizer.zero_grad()

   # 进行反向传播

   loss_val.backward()

   # 梯度下降更新参数

   optimizer.step()

   # 打印每次训练的损失值

   if i % 100 == 0:

   print(fLoss:{loss_val.item():.4f})

  print(训练完成)

  # 训练完之后保存模型

  torch.save(model.state_dict(), ./last.pt)

  

  

  

  • 损失值很明显的在收敛
  • 生成了pt模型文件

  

  

  

测试集抽取数据,查看预测结果

  

# 把测试集的数据加载器转为生成器

  examples = iter(test_loader)

  # next()方法获取一批数据

  example_data, example_targets = examples.next()

  # 拿出前三条

  for i in range(3):

   # 画图展示

   plt.subplot(1, 3, i + 1)

   plt.imshow(example_data[i][0], cmap=gray)

  plt.show()

  images = example_data

  # 图片将为加载到GPU

  images = images.reshape(-1, 28 * 28).to(device)

  # 正向传播获取预测结果

  outputs = model(images)

  # 打印结果 detach()方法结果不会计算梯度更新 转为numpy

  print(f真实结果:{example_targets[0:3].detach().numpy()})

  # 预测完的结果为10个数字的概率 使用argmax()根据行归一化并求自变量的概率最大值

  print(f预测结果:{np.argmax(outputs[0:3].cpu().detach().numpy(), axis=1)})

  

  

  

  

  

计算模型精度

  

# 用测试集的数据,校验模型的准确率

  with torch.no_grad():

   n_correct = 0

   n_samples = 0

   # 取出测试集数据

   for images, labels in test_loader:

   # 和训练代码一致

   images = images.reshape(-1, 28 * 28).to(device)

   labels = labels.to(device)

   outputs = model(images)

   # 返1 最大值 返2 索引 0每列最大值 1每行最大值

   _, predicted = torch.max(outputs.data, 1)

   n_samples += labels.size(0)

   n_correct += (predicted == labels).sum().item()

   # 计算模型精度

   acc = 100.0 * n_correct / n_samples

   print(f"准确率:{acc}%")

  

  

  

  

自己手写数字进行预测

  

import cv2

  import numpy as np

  import torch

  from 手写数字神经网络结构 import NeuralNet

  # 获取到gpu设备

  device = torch.device(cuda)

  # 加载保存好的模型

  input_size = 784

  num_classes = 10

  model = NeuralNet(input_size, 500, num_classes)

  # 因为保存模型时在GPU所以要指定map_location=cuda:0

  model.load_state_dict(torch.load(./last.pt, map_location=cuda:0))

  # 加载到gpu上

  model.to(device)

  # 局域内不计算梯度

  with torch.no_grad():

   # cv2读取图片 灰度方式

   images = cv2.imread(./number_four.png, cv2.IMREAD_GRAYSCALE)

   # 使用大津算法进行二值化处理 并反转

   ret, thresh_img = cv2.threshold(images, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)

   # 展示处理过后的图片

   cv2.imshow(png1, thresh_img)

   cv2.waitKey()

   # 图片降维 把拍的图片降维到和训练时的图片大小一样

   my_image = cv2.resize(thresh_img, (28, 28))

   # 转为numpy

   my_image = np.array(my_image, np.float32)

   # 转为torch的张量

   my_image = torch.from_numpy(my_image)

   # 降维

   my_image = my_image.reshape(-1, 28 * 28).to(device)

   # 正向传播获取预测值

   outputs = model(my_image)

   # 取出预测结果

   pred = np.argmax(outputs.cpu().detach().numpy(), axis=1)

   print(f预测结果为:{pred[0]})

  

  

  

  到此这篇关于PyTorch实现手写数字识别的示例代码的文章就介绍到这了,更多相关PyTorch 手写数字识别内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: