找回密码
 立即注册
查看: 554|回复: 0

PaddlePaddle——飞桨深度学习实现手写数字识别任务

[复制链接]

14

主题

0

回帖

57

积分

版主

积分
57
发表于 2023-5-4 18:45:44 | 显示全部楼层 |阅读模式
头条号:人工智能研究所微信号:启示AI科技视频号:启示科技
通过上一期文章的分享,我们介绍了paddlepaddle以及成功安装了paddlepaddle
百度深度学习平台PaddlePaddle——飞桨基础常识介绍
本期我们就来认识一下paddlepaddle的代码,进行一个简单的手写任务的实现
手写数字识别任务

数字识别是计算机从纸质文档、照片或其他来源接收、理解并识别可读的数字的能力,目前斗劲受存眷的是手写数字识别。手写数字识别是一个典型的图像分类问题,已经被广泛应用于汇款单号识别、手写邮政编码识别等范围,大大缩短了业务措置时间,提升了工作效率和质量。
MINIST数据

MINIST的数据分为2个部门:55000份训练数据(mnist.train)和10000份测试数据(mnist.test)。这个划分有重要的象征意义,他展示了在机器学习中如何使用数据。在训练的过程中,我们必需单独保留一份没有用于机器训练的数据作为验证的数据,这才能确保训练的成果的可行性。
前面已经提到,每一份MINIST数据都由图片以及标签组成。我们将图片定名为“x”,将标识表记标帜数字的标签定名为“y”。训练数据集和测试数据集都是同样的布局,例如:训练的图片名为 mnist.train.images 而训练的标签名为 mnist.train.labels。
每一个图片均为28×28像素,我们可以将其理解为一个二维数组的布局:

在措置如下图所示的手写邮政编码的简单图像分类任务时,可以使用基于MNIST数据集的手写数字识别模型。MNIST是深度学习范围尺度、易用的成熟数据集,包含50 000条训练样本和10 000条测试样本。

手写数字识别任务示意图

  • 任务输入:一系列手写数字图片,此中每张图片都是28x28的像素矩阵。
  • 任务输出:颠末了大小归一化和居中措置,输出对应的0~9的数字标签。
模型搭建--代码
  1. import paddle
  2. from paddle.nn import Linear
  3. import paddle.nn.functional as F
  4. import os
  5. import numpy as np
  6. import matplotlib.pyplot as plt
  7. # 设置数据读取器,API自动读取MNIST数据训练集
  8. train_dataset = paddle.vision.datasets.MNIST(mode='train')
  9. train_data0 = np.array(train_dataset[0][0])
  10. train_label_0 = np.array(train_dataset[0][1])
  11. # 显示第一batch的第一个图像
  12. plt.figure("Image") # 图像窗口名称
  13. plt.figure(figsize=(2,2))
  14. plt.imshow(train_data0, cmap=plt.cm.binary)
  15. plt.axis('on') # 关掉坐标轴为 off
  16. plt.title('image') # 图像标题问题
  17. plt.show()
  18. print("图像数据形状和对应数据为:", train_data0.shape)
  19. print("图像标签形状和对应数据为:", train_label_0.shape, train_label_0)
  20. print("\n打印第一个batch的第一个图像,对应标签数字为{}".format(train_label_0))
复制代码
与torchvision 类似paddle也有类似的API接口可以 直接调用一些数据集,
paddle.vision.datasets.MNIST,可以直接获取措置好的MNIST训练集、测试集,当然paddle也封装了其他的数据集,这里我们后期再一一介绍。
加载完成数据集后,我们可以打印一些数据集的形状与参数,当然也可以查看数据集的图像
  1. 图像数据形状和对应数据为: (28, 28)
  2. 图像标签形状和对应数据为: (1,) [5]
  3. 打印第一个batch的第一个图像,对应标签数字为[5]
复制代码

神经网络的搭建
  1. # 定义mnist数据识别网络布局
  2. class MNIST(paddle.nn.Layer):
  3.     def __init__(self):
  4.         super(MNIST, self).__init__()
  5.         # 定义一层全连接层,输出维度是1
  6.         self.fc = paddle.nn.Linear(in_features=784, out_features=1)
  7.     # 定义网络布局的前向计算过程
  8.     def forward(self, inputs):
  9.         outputs = self.fc(inputs)
  10.         return outputs
复制代码
这里我们首先使用一个单层且没有非线性变换的模型,看看此简单的神经网络模型能否正确识别出手写数字

这里由于是一层的神经网络,其跟CNN还是有所差距,这个我们后期进行此方面的代码优化
图像预措置
  1. # 图像归一化函数,将数据范围为[0, 255]的图像归一化到[0, 1]
  2. def norm_img(img):
  3.     # 验证传入数据格式是否正确,img的shape为[batch_size, 28, 28]
  4.     assert len(img.shape) == 3
  5.     batch_size, img_h, img_w = img.shape[0], img.shape[1], img.shape[2]
  6.     # 归一化图像数据
  7.     img = img / 255
  8.     # 将图像形式reshape为[batch_size, 784]
  9.     img = paddle.reshape(img, [batch_size, img_h*img_w])
  10.    
  11.     return img
复制代码
这里我们通过norm函数进行输出图像的措置,把范围为0--255归一化到0--1
神经网络的训练
  1. # 确保从paddle.vision.datasets.MNIST中加载的图像数据是np.ndarray类型
  2. paddle.vision.set_image_backend('cv2')
  3. # 声明网络布局
  4. model = MNIST()
  5. def train(model):
  6.     # 启动训练模式
  7.     model.train()
  8.     # 加载训练集 batch_size 设为 16
  9.     train_loader = paddle.io.DataLoader(paddle.vision.datasets.MNIST(mode='train'),
  10.                                         batch_size=16,
  11.                                         shuffle=True)
  12.     # 定义优化器,使用随机梯度下降SGD优化器,学习率设置为0.001
  13.     opt = paddle.optimizer.SGD(learning_rate=0.001, parameters=model.parameters())
  14.     EPOCH_NUM = 10
  15.     for epoch in range(EPOCH_NUM):
  16.         for batch_id, data in enumerate(train_loader()):
  17.             images = norm_img(data[0]).astype('float32')
  18.             labels = data[1].astype('float32')            
  19.             #前向计算的过程
  20.             predicts = model(images)     
  21.             # 计算损掉
  22.             loss = F.square_error_cost(predicts, labels)
  23.             avg_loss = paddle.mean(loss)
  24.             #每训练了1000批次的数据,打印下当前Loss的情况
  25.             if batch_id % 1000 == 0:
  26.                 print("epoch_id: {}, batch_id: {}, loss is: {}".format(epoch, batch_id, avg_loss.numpy()))
  27.             #后向传布,更新参数的过程
  28.             avg_loss.backward()
  29.             opt.step()
  30.             opt.clear_grad()            
  31. train(model)
  32. paddle.save(model.state_dict(), 'model/mnist.pdparams')   
复制代码
train(model)来进行神经网络的训练,训练过程采用二层循环嵌套方式,训练完成后需要保留模型参数,以便后续使用。

  • 内层循环:负责整个数据集的一次遍历,遍历数据集采用分批次(batch)方式。
  • 外层循环:定义遍历数据集的次数,本次训练中外层循环10次,通过参数EPOCH_NUM设置。
最后我们使用paddle.save(model.state_dict(), 'model/mnist.pdparams')来保留已经训练好的模型,以便后期进行数字的识别,通过训练loss一直下不去,这样我们进行后期优化。
  1. epoch_id: 0, batch_id: 0, loss is: [26.44594]
  2. epoch_id: 0, batch_id: 1000, loss is: [1.5970355]
  3. epoch_id: 0, batch_id: 2000, loss is: [3.3931825]
  4. epoch_id: 0, batch_id: 3000, loss is: [3.6991172]
  5. epoch_id: 1, batch_id: 0, loss is: [2.8589249]
  6. epoch_id: 1, batch_id: 1000, loss is: [4.109815]
  7. epoch_id: 1, batch_id: 2000, loss is: [5.390366]
  8. epoch_id: 1, batch_id: 3000, loss is: [4.619067]
  9. epoch_id: 2, batch_id: 0, loss is: [2.4614942]
  10. epoch_id: 2, batch_id: 1000, loss is: [2.2340536]
  11. epoch_id: 2, batch_id: 2000, loss is: [2.4032607]
  12. epoch_id: 2, batch_id: 3000, loss is: [1.7580397]
  13. epoch_id: 3, batch_id: 0, loss is: [2.8790944]
  14. epoch_id: 3, batch_id: 1000, loss is: [1.5264606]
  15. epoch_id: 3, batch_id: 2000, loss is: [3.5032237]
  16. epoch_id: 3, batch_id: 3000, loss is: [3.4746733]
  17. epoch_id: 4, batch_id: 0, loss is: [2.6894484]
  18. epoch_id: 4, batch_id: 1000, loss is: [2.1867495]
  19. epoch_id: 4, batch_id: 2000, loss is: [3.2445798]
  20. epoch_id: 4, batch_id: 3000, loss is: [8.163915]
  21. epoch_id: 5, batch_id: 0, loss is: [1.6421318]
  22. epoch_id: 5, batch_id: 1000, loss is: [3.7984645]
  23. epoch_id: 5, batch_id: 2000, loss is: [2.2743425]
  24. epoch_id: 5, batch_id: 3000, loss is: [2.3635402]
  25. epoch_id: 6, batch_id: 0, loss is: [5.423148]
  26. epoch_id: 6, batch_id: 1000, loss is: [4.778616]
  27. epoch_id: 6, batch_id: 2000, loss is: [3.4756808]
  28. epoch_id: 6, batch_id: 3000, loss is: [3.926146]
  29. epoch_id: 7, batch_id: 0, loss is: [3.7117333]
  30. epoch_id: 7, batch_id: 1000, loss is: [3.4605653]
  31. epoch_id: 7, batch_id: 2000, loss is: [4.286289]
  32. epoch_id: 7, batch_id: 3000, loss is: [3.027922]
  33. epoch_id: 8, batch_id: 0, loss is: [3.116638]
  34. epoch_id: 8, batch_id: 1000, loss is: [2.687238]
  35. epoch_id: 8, batch_id: 2000, loss is: [4.823868]
  36. epoch_id: 8, batch_id: 3000, loss is: [2.307558]
  37. epoch_id: 9, batch_id: 0, loss is: [1.770024]
  38. epoch_id: 9, batch_id: 1000, loss is: [1.5893741]
  39. epoch_id: 9, batch_id: 2000, loss is: [4.77549]
  40. epoch_id: 9, batch_id: 3000, loss is: [2.1042237]
复制代码
微信搜索小法式:AI人工智能东西,体验纷歧样的AI东西
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|T9AI - 深度人工智能平台 ( 沪ICP备2023010006号 )

GMT+8, 2024-11-23 19:41 , Processed in 0.062765 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表