综述

手写数字识别是每个学习神经网络的人上手操作的必由之路,此次实验基于paddlepaddle框架在百度AI Studio上进行实战,在fork的学习项目基础上做了数据集的修改以及网络结构的改良,最终可正确识别黑底白字及白底黑字的手写数字,在20k张的测试集上呈现99.313%的准确率,基本达到实验目的。

网络结构

本次实验原有基础网络结构为两层全连接层+一层全连接输出层,经过多次调参优化,实验发现在测试集上的准确率始终无法超过98%,实验效果并不理想。

最终,在Lenet-5结构的启发下,实验在原有基础上对图片做了卷积-池化-卷积-池化的处理,即两层卷积-池化层+两层全连接层+全连接输出层。经过多次调参,测试集上表现效果优秀,准确率最终可达 99.313%

其中部分超参数设置如下:

1. 卷积-池化层:滤波器大小5,滤波器数量20,池化层kernel大小2*2,池化层步长2,激活函数“relu”

2. 卷积-池化层:滤波器大小5,滤波器数量20,池化层kernel大小2*2,池化层步长2,激活函数“relu”

3. 全连接层: 神经元数量100,激活函数“relu”

4. 全连接层: 神经元数量100,激活函数“relu”

5. 全连接输出层: 输出神经元数量10,激活函数“softmax”

数据集

本次实验数据集来源有二,其一为黑底白字的minst开源数据集,已由paddlepaddle封装提供,其二为自制白底黑字的压缩包文件(含标签)

数据集大小为,训练集(60k黑底白字+60k白底黑字)+测试集(10k黑底白字+10k白底黑字)

实验结果

共进行五轮训练,每轮训练都会在测试集上测试。

此处只展示第五轮训练结束后最终网络表现: 损失:0.01924  准确率:0.99313

代码简述

1.导入需要的包

import numpy as np
import paddle as paddle
import paddle.fluid as fluid
from PIL import Image
import matplotlib.pyplot as plt
import os
import zipfile
import struct
import re

2.处理数据集zip文件

因本实验采用两个数据集来源,其一是被制作为压缩包的白底黑字数据集,其二是由paddlepaddle官方提供的封装好的paddle.dataset.mnist。因此次步骤目的为处理白底黑字数据集的压缩包,解压至"data/"下以便读取

is_extract_zip = Trueif is_extract_zip:train_zip = zipfile.ZipFile('/home/aistudio/data/data7475/train_examples_labels.zip') test_zip = zipfile.ZipFile('/home/aistudio/data/data7475/test_examples_labels.zip')train_zip.extractall('data/')test_zip.extractall('data/')

3.解析白底黑字数据集的label,并加载

标注训练集与测试集路径

# 训练集标签文件
train_labels_idx1_ubyte_file = 'data/train_examples_labels/train-labels.idx1-ubyte'# 测试集标签文件
test_labels_idx1_ubyte_file = 'data/test_examples_labels/t10k-labels.idx1-ubyte'

定义解析minist数据集idx1文件的通用函数及加载训练集和测试集的函数

def decode_idx1_ubyte(idx1_ubyte_file):"""解析idx1文件的通用函数:param idx1_ubyte_file: idx1文件路径:return: 数据集"""# 读取二进制数据bin_data = open(idx1_ubyte_file, 'rb').read()# 解析文件头信息,依次为魔数和标签数offset = 0fmt_header = '>ii'magic_number, num_images = struct.unpack_from(fmt_header, bin_data, offset)print ('魔数:%d, 图片数量: %d张' % (magic_number, num_images))# 解析数据集offset += struct.calcsize(fmt_header)fmt_image = '>B'labels = np.empty(num_images)for i in range(num_images):if (i + 1) % 10000 == 0:print ('已解析 %d' % (i + 1) + '张')labels[i] = struct.unpack_from(fmt_image, bin_data, offset)[0]offset += struct.calcsize(fmt_image)return labelsdef load_train_labels(idx_ubyte_file=train_labels_idx1_ubyte_file):return decode_idx1_ubyte(idx_ubyte_file)def load_test_labels(idx_ubyte_file=test_labels_idx1_ubyte_file):return decode_idx1_ubyte(idx_ubyte_file)

标注图片路径,加载label

# 图片路径
train_img = 'data/train_examples_labels/train_turn/'
test_img = 'data/test_examples_labels/test_new/'# 加载label
train_labels = load_train_labels()
test_labels = load_test_labels()

4.数据预处理

定义load_image函数用于对图片进行预处理,将RGB转化为灰度图像,L代表灰度图像,灰度图像的像素值在0~255之间。图像大小为28*28,返回新形状的数组,把它变成一个 numpy 数组以匹配数据馈送格式,之后归一化到【-1~1】之间。

def load_image(file):im = Image.open(file).convert('L')                        #将RGB转化为灰度图像,L代表灰度图像,灰度图像的像素值在0~255之间im = im.resize((28, 28), Image.ANTIALIAS)                 #resize image with high-quality 图像大小为28*28im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32)#返回新形状的数组,把它变成一个 numpy 数组以匹配数据馈送格式。im = im / 255.0 * 2.0 - 1.0                               #归一化到【-1~1】之间im = im.reshape((28*28))# print(im.size)return im

加载训练集与测试集入list以便创建reader。因白底黑字数据集中label会出现图片与label对应不一致情况,所以这里使用文件名中的图片序号大小为key进行排序。

# 加载训练data
train_data = []
train_file_names = []
list = os.listdir(train_img)
for i in range(0,len(list)):file = os.path.join(train_img,list[i])train_file_names.append(file)
train_file_names.sort(key = lambda x: int(x[38:-4]))    #按照index排序
for file in train_file_names:train_data.append(load_image(file))# 加载测试data
test_data = []
test_file_names = []
list = os.listdir(test_img)
for i in range(0,len(list)):file = os.path.join(test_img,list[i])test_file_names.append(file)
test_file_names.sort(key = lambda x: int(x[35:-4]))    #按照index排序
for file in test_file_names:test_data.append(load_image(file))

以迭代循环创建reader

def reader_createor(data, label):def reader():for i in  range(len(data)):yield data[i], int(label[i])return reader

调用paddle.batch合并黑底白字reader及白底黑字reader,其中黑底白字reader为paddlepaddle直接提供已封装好的。

train_reader = paddle.batch(paddle.reader.shuffle(paddle.reader.chain(reader_createor(train_data, train_labels),paddle.dataset.mnist.train()),buf_size=512),batch_size=128)
test_reader = paddle.batch(paddle.reader.chain(reader_createor(test_data, test_labels),paddle.dataset.mnist.test()),batch_size=128)

5.定义多层感知机

在此网络结构采用两个卷积-池化层+两个全连接层+一个全连接输出层

def multilayer_perceptron(input):conv_pool_1 = fluid.nets.simple_img_conv_pool(input=input,         # 输入图像filter_size=5,     # 滤波器的大小num_filters=20,    # filter 的数量。它与输出的通道相同pool_size=2,       # 池化层大小2*2pool_stride=2,     # 池化层步长act="relu")        # 激活类型conv_pool_2 = fluid.nets.simple_img_conv_pool(input=conv_pool_1,         # 输入图像filter_size=5,     # 滤波器的大小num_filters=20,    # filter 的数量。它与输出的通道相同pool_size=2,       # 池化层大小2*2pool_stride=2,     # 池化层步长act="relu")        # 激活类型# 第一个全连接层,激活函数为ReLUhidden1 = fluid.layers.fc(input=conv_pool_2, size=100, act='relu')# 第二个全连接层,激活函数为ReLUhidden2 = fluid.layers.fc(input=hidden1, size=100, act='relu')# 以softmax为激活函数的全连接输出层,大小为10prediction = fluid.layers.fc(input=hidden2, size=10, act='softmax')return prediction

6.定义输入输出层

image = fluid.layers.data(name='image', shape=[1, 28, 28], dtype='float32')  #单通道,28*28像素值
label = fluid.layers.data(name='label', shape=[1], dtype='int64')            #图片标签

7.获取分类器

model = multilayer_perceptron(image)

8.获取损失函数和准确率函数

在此使用交叉熵损失函数,描述真实样本标签和预测概率之间的差值

cost = fluid.layers.cross_entropy(input=model, label=label)  #使用交叉熵损失函数,描述真实样本标签和预测概率之间的差值
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=model, label=label)

9.定义优化方法

使用Adam算法进行优化

optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.001)   #使用Adam算法进行优化
opts = optimizer.minimize(avg_cost)

10.定义一个使用CPU的解析器并进行参数初始化

# 定义一个使用CPU的解析器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

11.定义输入数据维度

feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

12.开始训练和测试

共进行五轮训练,每训练一轮,进行一次测试

# 开始训练和测试
for pass_id in range(5):# 进行训练for batch_id, data in enumerate(train_reader()):                        #遍历train_readertrain_cost, train_acc = exe.run(program=fluid.default_main_program(),#运行主程序feed=feeder.feed(data),             #给模型喂入数据fetch_list=[avg_cost, acc])         #fetch 误差、准确率# 每100个batch打印一次信息  误差、准确率if batch_id % 100 == 0:print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' %(pass_id, batch_id, train_cost[0], train_acc[0]))# 进行测试test_accs = []test_costs = []#每训练一轮 进行一次测试for batch_id, data in enumerate(test_reader()):                         #遍历test_readertest_cost, test_acc = exe.run(program=fluid.default_main_program(), #执行训练程序feed=feeder.feed(data),               #喂入数据fetch_list=[avg_cost, acc])           #fetch 误差、准确率test_accs.append(test_acc[0])                                       #每个batch的准确率test_costs.append(test_cost[0])                                     #每个batch的误差# 求测试结果的平均值test_cost = (sum(test_costs) / len(test_costs))                         #每轮的平均误差test_acc = (sum(test_accs) / len(test_accs))                            #每轮的平均准确率print('Test:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, test_cost, test_acc))#保存模型model_save_dir = "/home/aistudio/data/hand.inference.model"# 如果保存路径不存在就创建if not os.path.exists(model_save_dir):os.makedirs(model_save_dir)print ('save models to %s' % (model_save_dir))fluid.io.save_inference_model(model_save_dir,  #保存推理model的路径['image'],      #推理(inference)需要 feed 的数据[model],        #保存推理(inference)结果的 Variablesexe)            #executor 保存 inference model

minst 手写数字识别实战相关推荐

  1. 深度学习(4)手写数字识别实战

    深度学习(4)手写数字识别实战 Step0. 数据及模型准备 1. X and Y(数据准备) 2. out=relu{relu{relu[X@W1+b1]@W2+b2}@W3+b3}out=relu ...

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

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

  3. 深度学习数字仪表盘识别_【深度学习系列】手写数字识别实战

    上周在搜索关于深度学习分布式运行方式的资料时,无意间搜到了paddlepaddle,发现这个框架的分布式训练方案做的还挺不错的,想跟大家分享一下.不过呢,这块内容太复杂了,所以就简单的介绍一下padd ...

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

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

  5. 深度学习入门项目:PyTorch实现MINST手写数字识别

    完整代码下载[github地址]:https://github.com/lmn-ning/MNIST_PyTorch.git 目录 一.MNIST数据集介绍及下载地址 二.代码结构 三.代码 data ...

  6. 【零基础】从零开始学神经网络《python神经网络编程》——手写数字识别实战

    文章目录 前言 一.机器学习是什么,深度学习是什么? 二.对NN,CNN,RNN,GNN,GAN的名词解释 三.详细介绍神经网络(NN) 1.认识神经网络 2.神经元 3.激活函数 4.权重--连接的 ...

  7. Pytorch 学习 (一)Minst手写数字识别(含特定函数解析)

    目录 本人目前在跟随csdn博主 "K同学啊"进行365天深度学习训练营进行学习,这是打卡内容 也作为本人学习的记录. 一.准备部分 三.训练模型 四.正式训练 五.输出 MNIS ...

  8. Pytorch+CNN+MNIST手写数字识别实战

    文章目录 1.MNIST 2.数据预处理 2.1相关包 2.2数据载入和预处理 3.网络结构 4.优化器.损失函数.网络训练以及可视化分析 4.1定义优化器 4.2网络训练 4.3可视化分析 5.测试 ...

  9. matlab实现BP神经网络minst手写数字识别

    按照模式分类课本写的代码,如有错误欢迎指正! main.m %程序运行可能会需要3-5分钟的时间,请耐心等待. clear; %已对lms.mat进行随机打乱,并将Y由标量化为[1,10]矩阵形成da ...

  10. tensorflow2.0基础操作-手写数字识别实战

    import tensorflow as tf from tensorflow import keras from tensorflow.keras import datasets, layers, ...

最新文章

  1. python3版本代码大全_python3中的
  2. 原来腾讯面试题也不难,面试官:给我说一下你理解的分布式架构?
  3. tcp前4字节消息长度_RocketMQ的消息存储格式
  4. MATLAB从入门到精通-MATLAB2021版类似excel的坐标轴标签自动缩放布局
  5. 存储过程里面的语句实在同一个事务中吗_事务降维的几种策略
  6. Creator Upload NFT sequencial diagram
  7. sql创建计算机用户,2015年计算机四级数据库复习要点:SQL Server 登录账户
  8. kafak消费者从头开始消费(消费者组)
  9. python是什么?python该怎么学?一招告诉你!!
  10. centos安装aria2c_Centos 7 编译安装Aria2
  11. 周末内部常用的15款开发者工具
  12. ECCV2020 | CPNDet:Anchor-free两阶段的目标检测框架,详解
  13. 51单片机初学之流水灯程序
  14. coreldraw怎样定数等分_coreldraw 里怎么将线段等分?
  15. 菜鸟教程css事件,【推荐】DIV+CSS入门菜鸟教程
  16. centos7 firewall-cmd 命令报错 ModuleNotFoundError: No module named 'gi'
  17. iOS 设置按钮上图下文的方式
  18. Notification-通知
  19. PCI e 转 PXI 远程 转接 套件 PCI e / PXI 远程控制 器 模块 板卡
  20. CCD摄像头相关知识

热门文章

  1. Office And PDF 病毒分析工具
  2. U盘重新安装Mac OS系统教程
  3. 操作系统原理实验报告——进程控制与描述
  4. 学习韩顺平java基础笔记 (自用)
  5. 恒生校招java笔试数据库语法_2015恒生电子校招笔试详解
  6. python基础语法手册下载-Python学习手册(第4版)pdf
  7. linux如何导入种子文件格式,Linux下磁力链接种子文件下载
  8. C#修改Config文件
  9. DBeaver数据库连接工具的简单操作
  10. 元气骑士机器人的成就皮肤_元气骑士:5把特殊“红武”,想要机器人的皮肤,用它就对了!...