对于MNIST手写体识别实验 —使用LeNet算法实现手写数字识别代码的理解
MNIST手写体识别实验
—使用LeNet算法实现手写数字识别
姓名:祁蓁倬
一、MindSpore介绍
MindSpore是一个全场景深度学习框架,旨在实现易开发、高效执行、全场景覆盖三大目标
- 易开发表现为API友好、调试难度低,
- 高效执行包括计算效率、数据预处理效率和分布式训练效率,
- 全场景则指框架同时支持云、边缘以及端侧场景。
MindSpore提供了Python编程范式,用户使用Python原生控制逻辑即可构建复杂的神经网络模型,AI编程变得简单
二、特点
目前主流的深度学习框架的执行模式有两种,分别为静态图模式和动态图模式。静态图模式拥有较高的训练性能,但难以调试。动态图模式相较于静态图模式虽然易于调试,但难以高效执行。
MindSpore提供了动态图和静态图统一的编码方式,大大增加了静态图和动态图的可兼容性,用户无需开发多套代码,仅变更一行代码便可切换动态图/静态图模式
三、实验目标
本Notebook将展示如何使用MindSpore在MNIST数据集上开发和训练一个LeNet模型,并将LeNet模型用于手写数字识别。
通过本实验你可以了解到如何使用MindSpore进行简单CNN网络的开发、简单图片分类任务的训和验证。
四、实验步骤
# 确认当前环境的版本
(请给出代码)
import mindspore #导入mindspore AI框架
print(mindspore.__version__) #打印mindspore版本号
>>1.2.0
1. 数据集下载
MNIST是一个手写数字数据集,训练集包含60000张手写数字,测试集包含10000张手写数字,共10类。
从华为云OBS公共桶中下载。
(请给出代码,并且在每一句后面手写解释这一句代码实现的功能)
import os #导入程序与操作系统进行交互的接口模块
import moxing as mox #导入moxing网络模型开发API模块并简名为mox
if not os.path.exists("./MNIST_Data.zip"):
mox.file.copy("obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip", "./MNIST_Data.zip")
#检测os模块路径,若路径不符,重置路径
!unzip -o MNIST_Data.zip -d ./ #解压手写数据集压缩包
!tree ./MNIST_Data/ #以树状图列出目录的内容
运行结果:
>>INFO:root:Using MoXing-v1.17.3-43fbf97f
INFO:root:Using OBS-Python-SDK-3.20.7
Archive: MNIST_Data.zip
inflating: ./MNIST_Data/__pycache__/load_data_zeros_ones.cpython-37.pyc
inflating: ./MNIST_Data/load_data_all.py
inflating: ./MNIST_Data/load_data_zeros_ones.py
inflating: ./MNIST_Data/process_dataset.py
inflating: ./MNIST_Data/test/t10k-images-idx3-ubyte
inflating: ./MNIST_Data/test/t10k-labels-idx1-ubyte
inflating: ./MNIST_Data/train/train-images-idx3-ubyte
inflating: ./MNIST_Data/train/train-labels-idx1-ubyte
./MNIST_Data/
├── load_data_all.py
├── load_data_zeros_ones.py
├── process_dataset.py
├── __pycache__
│ └── load_data_zeros_ones.cpython-37.pyc
├── test
│ ├── t10k-images-idx3-ubyte
│ └── t10k-labels-idx1-ubyte
└── train
├── train-images-idx3-ubyte
└── train-labels-idx1-ubyte
3 directories, 8 files
2、处理MNIST数据集
由于我们后面会采用LeNet这样的卷积神经网络对数据集进行训练,而采用LeNet在训练数据时,对数据格式是有所要求的,所以接下来的工作需要我们先查看数据集内的数据是什么样的,这样才能构造一个针对性的数据转换函数,将数据集数据转换成符合训练要求的数据形式。
步骤1 查看原始数据集数据:
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
from mindspore import context #导入mindspore子模块context,其下有set_context方法来配置运行需要的信息
import matplotlib.pyplot as plt #导入matplotlib子模块pyplot简名为plt,用来处理图像,数据可视化有关操作
import matplotlib #导入matplotlib模块
import numpy as np #导入numpy模块简名为np,包含多维数组用来整理数据
import mindspore.dataset as ds #导入mindspore子数据集模块,这个API模块用于数据处理主,存储样本和标签,同时也集成了一些常见的数据处理方法。
# device_target 可选 CPU/GPU/Ascend, 当选择GPU时mindspore规格也需要切换到GPU
context.set_context(mode=context.GRAPH_MODE, device_target="CPU") #通过set_context方法配置,mode设置运行模式(动态图模式),用CPU运行
train_data_path = "./MNIST_Data/train" #设置训练集路径
test_data_path = "./MNIST_Data/test" #设置测试集路径
mnist_ds = ds.MnistDataset(train_data_path) # 定义数据集
print('The type of mnist_ds:', type(mnist_ds)) #输出得到数据集的数据类型
print("Number of pictures contained in the mnist_ds:", mnist_ds.get_dataset_size()) #输出得到训练集的数据个数
dic_ds = mnist_ds.create_dict_iterator() #用create_dict_iterator创建数据迭代器,迭代访问定义好的训练集
item = next(dic_ds) #返回迭代器的下一个项目
img = item["image"].asnumpy() #将迭代训练集的张量用numpy数组表示
label = item["label"].asnumpy() #将迭代训练集的标签用numpy数组表示
print("The item of mnist_ds:", item.keys()) #输出训练集储存不同数据的变量名
print("Tensor of image in item:", img.shape) #输出迭代对象张量数组的形状
print("The label of item:", label) #输出迭代对象的标签值
plt.imshow(np.squeeze(img)) #调用imshow()函数实现热图绘制,squeeze函数通过降秩使matplotlib能进行数据的可视化
plt.title("number:%s"% item["label"].asnumpy()) #布置图片分布格式,添加标题
plt.show() #进行数据可视化,图片的显示
运行结果:
>>The type of mnist_ds: <class 'mindspore.dataset.engine.datasets.MnistDataset'>
Number of pictures contained in the mnist_ds: 60000
The item of mnist_ds: dict_keys(['image', 'label'])
Tensor of image in item: (28, 28, 1)
The label of item: 1
步骤2 数据处理:
数据集对于训练非常重要,好的数据集可以有效提高训练精度和效率,在加载数据集前,我们通常会对数据集进行一些处理。
定义数据集及数据操作
定义完成后,使用create_datasets对原始数据进行增强操作,并抽取一个batch的数据,查看数据增强后的变化。
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
import mindspore.dataset.vision.c_transforms as CV #导入MindSpore提供的增强数据集模块对图像进行预处理,从而提高模型的广泛性,简名为CV
import mindspore.dataset.transforms.c_transforms as C #导入MindSpore提供的支持常见的图形增强功能的模块对图像进行预处理,简名为C
from mindspore.dataset.vision import Inter #导入MindSpore提供的vision子模块可以调整图像大小
from mindspore import dtype as mstype #导入数据类型转换处理模块
def create_dataset(data_path, batch_size=32, repeat_size=1,
num_parallel_workers=1): #定义函数create_dataset来创建数据集,参数数据路径,抽取数据集大小,设置并行工作口数量
"""
create dataset for train or test
Args:
data_path (str): Data path
batch_size (int): The number of data records in each group
repeat_size (int): The number of replicated data records
num_parallel_workers (int): The number of parallel workers
"""
# define dataset
mnist_ds = ds.MnistDataset(data_path) #定增强义数据集
# define some parameters needed for data enhancement and rough justification
resize_height, resize_width = 32, 32 #设置图像变量高与宽
rescale = 1.0 / 255.0
shift = 0.0 #设置偏移量
rescale_nml = 1 / 0.3081 #设置插值偏移量
shift_nml = -1 * 0.1307 / 0.3081
#定义算法计算变量与参数
#定义需要进行的数据增强和处理操作,为之后进行map映射做准备。
# according to the parameters, generate the corresponding data enhancement method
#定义所需要的操作的map映射
resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) #缩小或者放大函数至预定高与宽,指定像素插值方式为双线性插值
rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
rescale_op = CV.Rescale(rescale, shift) #对图像数据进行标准化、归一化操作,使得每个像素的数值大小在(0,1)范围中,可以提升训练效率,shift增加偏移量
hwc2chw_op = CV.HWC2CHW()#对图像数据张量进行变换,张量形式由高x宽x通道(HWC)变为通道x高x宽(CHW),方便进行数据训练。
type_cast_op = C.TypeCast(mstype.int32) #将数据类型转化为int32
# using map to apply operations to a dataset
#使用map映射函数,将数据操作应用到数据集
mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers) #应用到数据集操作方法数据类型转换,操作列为标签列,并行一接口计算
mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers) #应用到数据集操作方法对图像放大缩小处理,预备插值,操作列为图像列,并行一接口计算
mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers) #应用到数据集操作方法标准化归一化,操作列为图象列,并行一接口计算
mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers) #应用到数据集操作方法编译文件标准化归一化,操作列为图象列,并行一接口计算
mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers) #应用到数据集操作方法张量进行变换,操作列为图象列,并行一接口计算
# process the generated dataset
#先进行shuffle、batch操作,再进行repeat操作,这样能保证1个epoch内数据不重复
buffer_size = 10000
mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) #shuffle用于将数据集随机打乱,不希望有太多的人为因素干扰训练,因为可能MNIST数据集本身是有一定规律的,不希望按照制作这个数据集的前辈的顺序来训练神经网络
mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True) #将整个数据集按照batch_size的大小分为若干批次,每一次训练的时候都是按一个批次的数据进行训练,drop_remainder确定是否删除数据行数小于批大小的最后一个块,这里设置为True就是只保留数据集个数整除
mnist_ds = mnist_ds.repeat(repeat_size) #将数据集重复repeat_size次,注意该操作一般使用在batch操作之后
return mnist_ds #返回数据集
ms_dataset = create_dataset(train_data_path) #将所有训练集创建数据集进行数据增强处理
print('Number of groups in the dataset:', ms_dataset.get_dataset_size()) #输出训练集大小
运行结果:
>> Number of groups in the dataset: 1875
步骤3 进一步查看增强后的数据:
- 从1875组数据中取出一组数据查看其数据张量及
label
。将张量数据和下标对应的值进行可视化。
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
data = next(ms_dataset.create_dict_iterator(output_numpy=True))
#返回迭代器的下一个项目,用create_dict_iterator创建数据迭代器,迭代访问增强后的训练集,并以数组形式输出
images = data["image"] #进行迭代image列并赋值给images变量
labels = data["label"] #进行迭代label列并赋值给labels变量
print('Tensor of image:', images.shape) #输出images形状(四维numpy数组)
print('labels:', labels) #输出labels标签数组
运行结果:
>> Tensor of image: (32, 1, 32, 32)
labels: [0 4 6 2 2 5 5 3 6 5 1 6 4 1 0 1 8 3 0 6 2 2 4 1 4 2 4 2 3 7 8 0]
- 将张量数据和下标对应的值进行可视化。
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
count = 1 #给count变量赋值为1
for i in images: #用变量i对images变量进行迭代循环
plt.subplot(4, 8, count) #分为4*8的网格图,在第count个图上进行图片显示
plt.imshow(np.squeeze(i)) # 调用imshow()函数实现热图绘制,squeeze函数是从数组的形状中删除单维条目,即把shape中为1的维度去掉(通过降秩)使matplotlib能进行数据的可视化
plt.title('num:%s'%labels[count-1]) #为每幅图片撰写标题在labels数组中索引
plt.xticks([]) #x轴不显示任何数据,为空白
count += 1 #count变量自加一
plt.axis("off") #关闭坐标轴
plt.show() #数据的可视化,图片的显示
运行结果:
>>
3、 定义模型
在对手写字体识别上,通常采用卷积神经网络架构(CNN)进行学习预测,最经典的属1998年由Yann LeCun创建的LeNet5架构,
结构示意如下图:
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
import mindspore.nn as nn #创模型,配置网络结构(卷积,压平,全连接,激活函数,最大池化),导入nn子模块简名为nn
from mindspore.common.initializer import Normal # 导入Normal模块类配置初始权重(正态分布)
class LeNet5(nn.Cell): #定义LeNet5类并继承nn.Cell类的属性和方法
"""Lenet network structure.""" #构建Lenet神经网络结构
# define the operator required #定义所需要的运算
def __init__(self, num_class=10, num_channel=1): #定义方法和默认参数与值
super(LeNet5, self).__init__() #声明继承父类nn.cell的__init__方法
self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
#nn.Conv2d的第一个参数是输入图片的通道数为1,即单个过滤器应有的通道数,第二个参数是输出图片的通道数,第三个参数是过滤器的二维属性,它可以是一个int元组,但由于一般过滤器都是a x a形式的,而且为奇数。所以这里填入单个数即可,参数pad_mode为卷积方式,valid卷积即padding为0的卷积
self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
#nn.Conv2d的第一个参数是输入图片的通道数为6,第二个参数是输出图片的通道数,第三个参数是过滤器的二维属性,它可以是一个int元组,但由于一般过滤器都是a x a形式的,而且为奇数。所以这里填入单个数即可,参数pad_mode为卷积方式,valid卷积即padding为0的卷积,现在也比较流行same卷积,即卷积后输出的图片不会缩小。需要注意的是卷积层我们是不需要设置参数的随机方式的,因为它默认会给我们选择为Noremal。
self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))
self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))
#nn.Dense为致密连接层,它的第一个参数为输入层的维度,第二个参数为输出的维度,第三个参数为神经网络可训练参数W权重矩阵的初始化方式,默认为normal,以上代码对号入座即可
self.relu = nn.ReLU() #nn.ReLU()非线性激活函数,它往往比论文中的sigmoid激活函数具有更好的效益
self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
#nn.MaxPool2d为最大池化层的定义,kernel_size为采样器的大小,stride为采样步长,本例中将其都设置为2相当于将图片的宽度和高度都缩小一半
self.flatten = nn.Flatten() #nn.Flatten为输入展成平图层,即去掉那些空的维度
# use the preceding operators to construct networks
#使用定义好的运算构建前向网络
def construct(self, x): #构建输入参数调用方法的方法,输入x,下面即是将x通过LeNet5网络执行前向传播的过程
x = self.max_pool2d(self.relu(self.conv1(x)))
x = self.max_pool2d(self.relu(self.conv2(x)))
#调用max_pool2d最大池化层方法
x = self.flatten(x) #调用flatten方法将输入展成平图层(去掉那些空的维度)
x = self.relu(self.fc1(x))
x = self.relu(self.fc2(x)) #调用relu方法利用非线性激活函数对数据进行处理
x = self.fc3(x) #调用致密连接层算法方法对数据进行处理
return x #返回全部经过算法处理过的数据x
network = LeNet5() #用实例名network对LeNet5类进行实例化
print("layer conv1:", network.conv1) #查看卷积后conv1的参数
print("*"*40) #输出星号行进行作为分隔
print("layer fc1:", network.fc1) #查看卷积后fc1的参数
运行结果:
>> layer conv1: Conv2d<input_channels=1, output_channels=6, kernel_size=(5, 5),stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, has_bias=Falseweight_init=normal, bias_init=zeros, format=NCHW>
****************************************
layer fc1: Dense<input_channels=400, output_channels=120, has_bias=True>
4、搭建训练网络并进行训练
构建完成神经网络后,就可以着手进行训练网络的构建,模型训练函数为Model.train
此步骤案例中使用epoch=1,使用CPU训练大概耗时15分钟,为实现快速训练,可选用更高规格的资源训练。
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
#前面已经定义好了网络的前向传播过程,为了改变可训练参数,即所使用的参数能够预测出更加精确的值。需要定义损失函数即优化器,在MindSpore框架中是封装好了损失函数和优化器的,这使得编程可以更快更加高效
import os #导入程序与操作系统进行交互的接口模块
from mindspore import Tensor, Model #张量的初始化方式有多种,构造张量时,支持传入Tensor、float、int、bool、tuple、list和NumPy.array类型,Tensor的shape,是一个tuple。
from mindspore import load_checkpoint, load_param_into_net # 加载已经保存的用于测试的模型
from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor
from mindspore.nn.metrics import Accuracy
from mindspore.nn.loss import SoftmaxCrossEntropyWithLogits # MindSpore 支持的损失函数有 SoftmaxCrossEntropyWithLogits、L1Loss、MSELoss 等。这里使用 SoftmaxCrossEntropyWithLogits 交叉熵损失函数
#损失函数:又叫目标函数,用于衡量预测值与实际值差异的程度。深度学习通过不停地迭代来缩小损失函数的值。定义一个好的损失函数,可以有效提高模型的性能。常见的有二分类的损失函数L,以及softmax损失函数等。
优化器:用于最小化损失函数,从而在训练过程中改进模型。
lr = 0.01 #learingrate,学习率,可以使梯度下降的幅度变小,从而可以更好的训练参数
momentum = 0.9
epoch_size = 1 #每个epoch需要遍历完成图片的batch数,这里是只要遍历一次
mnist_path = "./MNIST_Data" #使用了流行的Momentum优化器进行优化
model_path = "./models/ckpt/"
# clean up old run files before in Linux
os.system('rm -f {}*.ckpt {}*.meta {}*.pb'.format(model_path, model_path, model_path))
#布置接口在Linux架构上运行
# create the network
network = LeNet5()
#创建手写神经网络
# define the optimizer
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)
#其中grad、lr、p、v和u分别表示梯度、学习率、参数、力矩和动量。
# define the loss function
net_loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
#相当于softmax分类器
#sparse指定标签(label)是否使用稀疏模式,默认为false,reduction为损失的减少类型:mean表示平均值,一般
#情况下都是选择平均地减少
# define the model
model = Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()} )
#调用Model高级API,将LeNet-5网络与损失函数和优化器连接到一起,具有训练和推理功能的对象。metrics 参数是指训练和测试期,模型要评估的一组度量,这里设置的是"Accuracy"准确度
# save the network model and parameters for subsequence fine-tuning
config_ck = CheckpointConfig(save_checkpoint_steps=375, keep_checkpoint_max=16)
# group layers into an object with training and evaluation features
ckpoint_cb = ModelCheckpoint(prefix="checkpoint_lenet", directory=model_path, config=config_ck)
#自定义一个回调类
自定义一个数据收集的回调类StepLossAccInfo该类继承自Callback类。主要用于收集两类信息,step与loss值之间地关系。step与对应模型精度之间联系。
eval_dataset = create_dataset("./MNIST_Data/test")
#创建数据集并使用数据集路径
step_loss = {"step": [], "loss_value": []}
steps_eval = {"step": [], "acc": []}
#回调类中提到的我们要声明的数据格式
repeat_size = 1
ds_train = create_dataset(os.path.join(mnist_path, "train"), 32, repeat_size)
model.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor(125)], dataset_sink_mode=False)
#调用Model类的train方法进行训练,LossMonitor(125)每隔125个step打印训练过程中的loss值,dataset_sink_mode为设置数据下沉模式,但该模式不支持CPU,所以这里我们只能设置为False
运行结果:
>> epoch: 1 step: 125, loss is 2.2997866
epoch: 1 step: 250, loss is 2.3055472
epoch: 1 step: 375, loss is 2.2988715
epoch: 1 step: 500, loss is 2.2939103
epoch: 1 step: 625, loss is 2.3018577
epoch: 1 step: 750, loss is 2.3118253
epoch: 1 step: 875, loss is 1.4138937
epoch: 1 step: 1000, loss is 0.27308625
epoch: 1 step: 1125, loss is 0.18187436
epoch: 1 step: 1250, loss is 0.06290328
epoch: 1 step: 1375, loss is 0.04215096
epoch: 1 step: 1500, loss is 0.43650156
epoch: 1 step: 1625, loss is 0.13031071
epoch: 1 step: 1750, loss is 0.16527386
epoch: 1 step: 1875, loss is 0.061115555
5、测试数据验证模型精度
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
# testing relate modules #测试相关模型
def test_net(network, model, mnist_path): #定义测试神经网络函数
"""Define the evaluation method."""
print("============== Starting Testing ==============") #打印分割线
# load the saved model for evaluation
param_dict = load_checkpoint("./models/ckpt/checkpoint_lenet-1_1875.ckpt") # 加载路径数据集
# load parameter to the network
load_param_into_net(network, param_dict) #加载预测神经网络数据集
# load testing dataset
ds_eval = create_dataset(os.path.join(mnist_path, "test")) #创建测试数据集函数
acc = model.eval(ds_eval, dataset_sink_mode=False)
print("============== Accuracy:{} ==============".format(acc)) #打印分割线
test_net(network, model, mnist_path)
运行结果:
>> ============== Starting Testing ==============
============== Accuracy:{'Accuracy': 0.9669471153846154} ==============
6、推理(训练后)
(请给出代码,并在每一句后面手写解释这一句代码实现的功能,在最后给出代码运行的输出结果)
提取出一个批次的图片,使用已训练好的上面的模型来预测一下每一张图片的标签,并将其可视化。
ds_test = create_dataset(test_data_path).create_dict_iterator() #录入测试数据路径给ds_test变量存储一个字典类型迭代器,
data = next(ds_test) #设置data变量存入ds_test进行迭代的内容
images = data["image"].asnumpy() #设置images变量存入数据集image列转换为数组类型的数据
labels = data["label"].asnumpy() #设置labels变量存入数据集label列转换为数组类型的数据
output = model.predict(Tensor(data['image'])) #利用加载好的模型的predict进行预测,注意返回的是对应的(0到9)的概率
pred = np.argmax(output.asnumpy(), axis=1)
err_num = [] #设置初始空列表
index = 1 #设置初始索引为1
for i in range(len(labels)): #对数据集测试长度判断循环次数并使用range循环进行遍历
plt.subplot(4, 8, i+1) #设置分割图用i循环进行数据可视化
color = 'blue' if pred[i] == labels[i] else 'red' #设置图片颜色
plt.title("pre:{}".format(pred[i]), color=color) #设置标题颜色架构
plt.imshow(np.squeeze(images[i])) #去秩(去掉一维的维度)用来实现图片的二维显示
plt.axis("off") #关闭坐标轴
if color == 'red': #当颜色为红色时,索引为0
index = 0
print("Row {}, column {} is incorrectly identified as {}, the correct value should be {}".format(int(i/8)+1, i%8+1, pred[i], labels[i]), '\n')
if index:
print("All the figures in this group are predicted correctly!")
print(pred, "<--Predicted figures")
print(labels, "<--The right number")
plt.show() #图片进行显示
运行结果:
>>Row 1, column 2 is incorrectly identified as 7, the correct value should be 9
[5 7 7 6 8 1 4 4 0 9 6 3 0 3 5 9 3 4 3 2 8 0 1 6 0 7 0 8 2 1 5 4] <--Predicted figures
[5 9 7 6 8 1 4 4 0 9 6 3 0 3 5 9 3 4 3 2 8 0 1 6 0 7 0 8 2 1 5 4] <--The right number
- 实验分析与结论
本实验展示了如何使用MindSpore进行手写数字识别,以及开发和训练LeNet5模型。通过对LeNet5模型做几代的训练,然后使用训练后的LeNet5模型对手写数字进行识别,识别准确率大于95%。即LeNet5学习到了如何进行手写数字识别。
至此,本案例完成。
- 点赞
- 收藏
- 关注作者
评论(0)