综述

手写数字识别是每个学习神经网络的人上手操作的必由之路,此次实验基于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. java list原理_Java中ArrayList实现原理
  2. Ural 1018 (树形DP+背包+优化)
  3. 【干货】JMeter BeanShell 应用
  4. 2018 NLP圣经《自然语言处理综述》最新手稿已经发布!
  5. 【android】窗口管理
  6. tp5 日期范围查询_VB实战应用 | 如何巧妙解决日期范围查询问题
  7. android开启服务器配置,Android基于XMPP开发(一)【openfire服务器配置】
  8. xhr get获取文件流下载文件_python爬虫实战——豆瓣电影get初体验
  9. 《程序员面试金典》解题目录(更新完毕)
  10. 行,Python玩大了!​取代Excel,程序员:太牛!你怎么看?
  11. ffmpeg 视频合并
  12. 全站仪坐标计算机公式,全站仪使用方法及坐标计算讲解
  13. hibernate 执行存储过程 方法
  14. UNIX 环境高级编程(八)—— fork 函数
  15. 面向对象闲话(一)——什么是对象
  16. 创建一个简单的MFC程序
  17. 微信小程序调用域名服务器的服务
  18. 单元素/组件的过渡以及过渡钩子的运用
  19. springbus类是做什么用的_SpringCloud-Bus组件的使用
  20. 投资中的N种认知偏差总有一款败你

热门文章

  1. Unity3D中的Update、LateUpdate和FixedUpdate的意义
  2. 瑞友天翼建文件服务器,瑞友天翼简明使用手册
  3. 百度,google等搜索引擎的网络蜘蛛基本原理
  4. 毕业设计论坛,免费毕业设计资源下载
  5. Thinkpad x200 X201拆机换风扇教程 实图
  6. CDH运维常见问题-cloudera-scm-agent 已死,但 pid 文件存在
  7. 在wps里面怎么设置触发器_wps触发器怎么设置
  8. Vue写项目后台SpringBoot 01
  9. linux每天定时开关机,如何实现ubuntu每天定时关机
  10. 带控制面板英伟达驱动下载地址