MNIST手写数字识别 —— ResNet-经典卷积神经网络

了解ResNet18的网络结构;掌握模型的保存和加载方法;掌握批量测试图片的方法。

结合图像分类任务,使用典型的图像分类网络ResNet18,实现手写数字识别。

ResNet作为经典的图像分类网络有其明显的优点:

  • 首先,它足够深,常见的有34层,50层,101层。通常层次越深,表征能力越强,分类准确率越高。

  • 其次,可学习,采用了残差结构,通过shortcut连接把低层直接跟高层相连,解决了反向传播过程中因为网络太深造成的梯度消失问题。

  • 此外,ResNet网络的性能很好,既表现为识别的准确率,也包括它本身模型的大小和参数量。

1. 加载并处理数据集

import os
import sys
import moxing as mox

datasets_dir = '../datasets'
if not os.path.exists(datasets_dir):
    os.makedirs(datasets_dir)
    
if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
    mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip', 
                  os.path.join(datasets_dir, 'MNIST_Data.zip'))
    os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
    
sys.path.insert(0, os.path.join(os.getcwd(), '../datasets/MNIST_Data'))
from load_data_all import load_data_all
from process_dataset import process_dataset

mnist_ds_train, mnist_ds_test, train_len, test_len = load_data_all(datasets_dir)  # 加载数据集
mnist_ds_train = process_dataset(mnist_ds_train, batch_size= 64, resize= 28)  # 处理训练集,分批加载
mnist_ds_test = process_dataset(mnist_ds_test, batch_size= 32, resize= 28)  # 处理测试集, 分批加载

训练集规模:60000,测试集规模:10000 

2. 下载构建好的resnet18网络源码文件

为了让开发者更好地体验MindSpore框架优势,MindSpore Model Zoo已经添加了更多典型网络和相关预训练模型,涉及到计算机视觉、自然语言处理、推荐系统、图神经网络等领域。其中的ResNet系列网络模型也已经使用MindSpore实现。

2.1. 下载网络源码文件

采用ResNet-18 实现手写数字识别任务,需要将resnet.py下载下来,才可以使用MindSpore定义好的网络结构。

# 下载构建好的网络源文件,只需执行一次即可。
!wget -N https://modelarts-labs-bj4-v2.obs.cn-north-4.myhuaweicloud.com/course/mindspore/mnist_recognition/src/resnet.py --no-check-certificate

2.2.修改网络文件中通道数

由于使用的是单通道的灰度图像数据,这里需要将原网络结果中的第一层卷积层的输入通道 3改为1,即将resnet.py中的第387行的 3 改为 1 即可,这里使用linux中的sed命令来编辑文本。

# 此命令执行后将直接在原文件中修改,不会有任何输出
!sed -i '387s/3/1/g' ./resnet.py

 3. 载入resnet18网络

from resnet import resnet18

network = resnet18(class_num=10)  

4. 定义损失函数和优化器 

import mindspore
import mindspore.nn as nn

lr = 0.01
momentum = 0.9

net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')  # 损失函数
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)  # 优化器

5. 配置运行信息 

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")

6. 调用Model高阶API进行训练和保存模型文件

        模型训练包含两层迭代,数据集的多轮迭代(epoch)和一轮数据集内按分组(batch)大小进行的单步迭代。

为了简化训练过程,MindSpore封装了Model高阶接口:

  • 用户输入网络、损失函数和优化器完成Model的初始化;

  • 调用train接口进行训练,train接口参数包括迭代次数(epoch)和数据集(dataset);

  • 调用Model的eval接口预测新图像类别;

  • 模型保存是对训练参数进行持久化的过程。Model类中通过回调函数(callback)的方式进行模型保存。

这里对数据进行一轮迭代,训练耗时约30秒

import os,time
from mindspore import Model
from mindspore import load_checkpoint, load_param_into_net
from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor

model = Model(network, loss_fn=net_loss, optimizer=net_opt, metrics={'acc'})  # 完成Model初始化

# 训练参数
batch_num = mnist_ds_train.get_dataset_size()
max_epochs = 1

model_path = "./models/ckpt/"
os.system('rm -f {0}*.ckpt {0}*.meta {0}*.pb'.format(model_path))

# 定义回调函数
config_ck = CheckpointConfig(save_checkpoint_steps=batch_num, keep_checkpoint_max=35)
ckpoint_cb = ModelCheckpoint(prefix="train_resnet_mnist", directory=model_path, config=config_ck)

loss_cb = LossMonitor(batch_num)  # 用于输出损失
start_time = time.time()
model.train(max_epochs, mnist_ds_train, callbacks=[ckpoint_cb, loss_cb])  # 训练
res = model.eval(mnist_ds_test)  # 验证测试集
print("result: ", res)
cost_time = time.time() - start_time
print("训练总耗时: %.1f s" % cost_time)
epoch: 1 step: 937, loss is 0.039122876

result:  {'acc': 0.9818709935897436}

训练总耗时: 16.7 s

        从上面的输出结果,可以看到ResNet18模型仅训练一个epoch,耗时仅17秒左右,就在手写数字识别任务的测试集上达到了0.98以上的准确率。该准确率可以达到应用水平,下面将保存模型、并加载模型进行批量图片预测,看看真实的预测效果如何。

查询训练过程中,保存好的模型

!tree ./models/ckpt/
./models/ckpt/

├── train_resnet_mnist-1_937.ckpt

└── train_resnet_mnist-graph.meta



0 directories, 2 files

        每937个step保存一次模型权重参数.ckpt文件,一共保存了1个,另外.meta文件保存模型的计算图信息。

7. 批量图片的预测显示

import numpy as np
from PIL import Image
import mindspore
import mindspore.ops as ops
from mindspore import Tensor

dic_ds_test = mnist_ds_test.create_dict_iterator(output_numpy=True)
ds_test = next(dic_ds_test)
images_test = ds_test["image"]
labels_test = ds_test["label"]
output = model.predict(Tensor(images_test))
pred_labels = ops.Argmax(output_type=mindspore.int32)(output)
print("预测值 -- > ", pred_labels)  # 打印预测值
print("真实值 -- > ", labels_test)  # 打印真实值
batch_img = np.squeeze(images_test[0])
for i in range(1, len(labels_test)):
    batch_img = np.hstack((batch_img, np.squeeze(images_test[i])))  # 将一批图片水平拼接起来,方便下一步进行显示
Image.fromarray((batch_img*255).astype('uint8'), mode= "L")  # 显示真实值
预测值 -- >  [0 3 8 5 2 0 1 2 8 5 0 3 4 5 4 5 6 2 9 4 8 0 1 1 7 5 6 7 8 5 9 4]

真实值 -- >  [0 3 1 5 2 0 1 2 8 5 0 3 4 5 4 5 6 2 4 4 8 0 1 1 7 5 6 7 8 5 9 4]

        从预测结果可以看出,32张图片只有一张错误预测:1预测成了8,说明模型的预测效果还是不错的。 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于基于卷积神经网络mnist手写数字识别,我们可以使用以下步骤: 1. 加载数据集:使用Python中的Keras库加载MNIST数据集。 2. 数据预处理:将像素值缩放到0到1之间,并将标签进行one-hot编码。 3. 构建模型:使用Keras库构建卷积神经网络模型。 4. 编译模型:指定损失函数、优化器和评估指标。 5. 训练模型:使用训练集训练模型,并在验证集上进行验证。 6. 评估模型:使用测试集评估模型的性能。 7. 使用模型:使用训练好的模型对新的手写数字图像进行分类。 以下是一个简单的基于卷积神经网络mnist手写数字识别的代码示例: ```python from keras.datasets import mnist from keras.utils import to_categorical from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense # 加载数据集 (train_images, train_labels), (test_images, test_labels) = mnist.load_data() # 数据预处理 train_images = train_images.reshape((60000, 28, 28, 1)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape((10000, 28, 28, 1)) test_images = test_images.astype('float32') / 255 train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) # 构建模型 model = Sequential() model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(Flatten()) model.add(Dense(64, activation='relu')) model.add(Dense(10, activation='softmax')) # 编译模型 model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(train_images, train_labels, epochs=5, batch_size=64, validation_data=(test_images, test_labels)) # 评估模型 test_loss, test_acc = model.evaluate(test_images, test_labels) print('Test accuracy:', test_acc) # 使用模型 predictions = model.predict(test_images) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值