当前位置:   article > 正文

MNIST手写数字识别 —— 从二分类到十分类_二分类常用数据集minst

二分类常用数据集minst

将一个二分类模型改成多分类模型的方法

本案例中使用深度学习框架MindSpore,利用其友好的封装模块,模型结构定义、损失函数定义、梯度下降实现等过程,只需简单地函数调用,就能实现模型训练,极大地提高了模型开发的效率。

1.加载数据集

        加载完整的、十个类别的数据集 

  1. import os
  2. import numpy as np
  3. import moxing as mox
  4. import mindspore.dataset as ds
  5. datasets_dir = '../datasets'
  6. if not os.path.exists(datasets_dir):
  7. os.makedirs(datasets_dir)
  8. if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
  9. mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip',
  10. os.path.join(datasets_dir, 'MNIST_Data.zip'))
  11. os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
  12. # 读取完整训练样本和测试样本
  13. mnist_ds_train = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/train"))
  14. mnist_ds_test = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/test"))
  15. train_len = mnist_ds_train.get_dataset_size()
  16. test_len = mnist_ds_test.get_dataset_size()
  17. print('训练集规模:', train_len, ',测试集规模:', test_len)

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

        查看10个样本

  1. from PIL import Image
  2. items_train = mnist_ds_train.create_dict_iterator(output_numpy=True)
  3. train_data = np.array([i for i in items_train])
  4. images_train = np.array([i["image"] for i in train_data])
  5. labels_train = np.array([i["label"] for i in train_data])
  6. batch_size = 10 # 查看10个样本
  7. batch_label = [lab for lab in labels_train[:10]]
  8. print(batch_label)
  9. batch_img = images_train[0].reshape(28, 28)
  10. for i in range(1, batch_size):
  11. batch_img = np.hstack((batch_img, images_train[i].reshape(28, 28))) # 将一批图片水平拼接起来,方便下一步进行显示
  12. Image.fromarray(batch_img)
[0, 2, 2, 7, 8, 4, 9, 1, 8, 8]

 2.处理数据集

        数据集对于训练非常重要,好的数据集可以有效提高训练精度和效率,在使用数据集前,通常会对数据集进行一些处理。

进行数据增强操作

  1. import mindspore.dataset.vision.c_transforms as CV
  2. import mindspore.dataset.transforms.c_transforms as C
  3. from mindspore.dataset.vision import Inter
  4. from mindspore import dtype as mstype
  5. num_parallel_workers = 1
  6. resize_height, resize_width = 28, 28
  7. # according to the parameters, generate the corresponding data enhancement method
  8. resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) # 对图像数据像素进行缩放
  9. type_cast_op = C.TypeCast(mstype.int32) # 将数据类型转化为int32。
  10. hwc2chw_op = CV.HWC2CHW() # 对图像数据张量进行变换,张量形式由高x宽x通道(HWC)变为通道x高x宽(CHW),方便进行数据训练。
  11. # using map to apply operations to a dataset
  12. mnist_ds_train = mnist_ds_train.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers)
  13. mnist_ds_train = mnist_ds_train.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)
  14. mnist_ds_train = mnist_ds_train.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers)
  15. buffer_size = 10000
  16. mnist_ds_train = mnist_ds_train.shuffle(buffer_size=buffer_size) # 打乱训练集的顺序
'
运行

进行数据归一化

        对图像数据进行标准化、归一化操作,使得每个像素的数值大小在(0,1)范围中,可以提升训练效率。

  1. rescale = 1.0 / 255.0
  2. shift = 0.0
  3. rescale_nml = 1 / 0.3081
  4. shift_nml = -1 * 0.1307 / 0.3081
  5. rescale_op = CV.Rescale(rescale, shift)
  6. mnist_ds_train = mnist_ds_train.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers)
  7. rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
  8. mnist_ds_train = mnist_ds_train.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers)
  9. mnist_ds_train = mnist_ds_train.batch(60000, drop_remainder=True) # 对数据集进行分批,此处加载完整的训练集

3. 封装成函数

        到此,我们就完成了训练数据的准备工作,可以将以上操作封装成load_data_all函数和process_dataset函数,以便后面再次用到。

定义数据处理操作

定义一个函数process_dataset来进行数据增强和处理操作:

  • 定义进行数据增强和处理所需要的一些参数。

  • 根据参数,生成对应的数据增强操作。

  • 使用map映射函数,将数据操作应用到数据集。

  • 对生成的数据集进行处理。 

  1. %%writefile ../datasets/MNIST_Data/process_dataset.py
  2. def process_dataset(mnist_ds, batch_size=32, resize= 28, repeat_size=1,
  3. num_parallel_workers=1):
  4. """
  5. process_dataset for train or test
  6. Args:
  7. mnist_ds (str): MnistData path
  8. batch_size (int): The number of data records in each group
  9. resize (int): Scale image data pixels
  10. repeat_size (int): The number of replicated data records
  11. num_parallel_workers (int): The number of parallel workers
  12. """
  13. import mindspore.dataset.vision.c_transforms as CV
  14. import mindspore.dataset.transforms.c_transforms as C
  15. from mindspore.dataset.vision import Inter
  16. from mindspore import dtype as mstype
  17. # define some parameters needed for data enhancement and rough justification
  18. resize_height, resize_width = resize, resize
  19. rescale = 1.0 / 255.0
  20. shift = 0.0
  21. rescale_nml = 1 / 0.3081
  22. shift_nml = -1 * 0.1307 / 0.3081
  23. # according to the parameters, generate the corresponding data enhancement method
  24. resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)
  25. rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
  26. rescale_op = CV.Rescale(rescale, shift)
  27. hwc2chw_op = CV.HWC2CHW()
  28. type_cast_op = C.TypeCast(mstype.int32)
  29. c_trans = [resize_op, rescale_op, rescale_nml_op, hwc2chw_op]
  30. # using map to apply operations to a dataset
  31. mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)
  32. mnist_ds = mnist_ds.map(operations=c_trans, input_columns="image", num_parallel_workers=num_parallel_workers)
  33. # process the generated dataset
  34. buffer_size = 10000
  35. mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)
  36. mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
  37. mnist_ds = mnist_ds.repeat(repeat_size)
  38. return mnist_ds

定义数据加载函数 

  1. %%writefile ../datasets/MNIST_Data/load_data_all.py
  2. def load_data_all(datasets_dir):
  3. import os
  4. if not os.path.exists(datasets_dir):
  5. os.makedirs(datasets_dir)
  6. import moxing as mox
  7. if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
  8. mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip',
  9. os.path.join(datasets_dir, 'MNIST_Data.zip'))
  10. os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
  11. # 读取完整训练样本和测试样本
  12. import mindspore.dataset as ds
  13. datasets_dir = '../datasets'
  14. mnist_ds_train = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/train"))
  15. mnist_ds_test = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/test"))
  16. train_len = mnist_ds_train.get_dataset_size()
  17. test_len = mnist_ds_test.get_dataset_size()
  18. print('训练集规模:', train_len, ',测试集规模:', test_len)
  19. return mnist_ds_train, mnist_ds_test, train_len, test_len

4.加载处理后的测试集

  1. import os, sys
  2. sys.path.insert(0, os.path.join(os.getcwd(), '../datasets/MNIST_Data'))
  3. from process_dataset import process_dataset
  4. mnist_ds_test = process_dataset(mnist_ds_test, batch_size= 10000)

5.定义网络结构和评价函数 

  1. import mindspore
  2. import mindspore.nn as nn
  3. import mindspore.ops as ops
  4. from mindspore.common.initializer import Normal
  5. class Network(nn.Cell):
  6. def __init__(self, num_of_weights):
  7. super(Network, self).__init__()
  8. self.fc = nn.Dense(in_channels=num_of_weights, out_channels=10, weight_init=Normal(0.02)) # 定义一个全连接层
  9. self.nonlinearity = nn.Sigmoid()
  10. self.flatten = nn.Flatten()
  11. def construct(self, x): # 加权求和单元和非线性函数单元通过定义计算过程来实现
  12. x = self.flatten(x)
  13. z = self.fc(x)
  14. pred_y = self.nonlinearity(z)
  15. return pred_y
  16. def evaluate(pred_y, true_y):
  17. pred_labels = ops.Argmax(output_type=mindspore.int32)(pred_y)
  18. correct_num = (pred_labels == true_y).asnumpy().sum().item()
  19. return correct_num

6.定义交叉熵损失函数和优化器

  1. # 损失函数
  2. net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
  3. # 创建网络
  4. network = Network(28*28)
  5. lr = 0.01
  6. momentum = 0.9
  7. # 优化器
  8. net_opt = nn.Momentum(network.trainable_params(), lr, momentum)

7.实现训练函数 

  1. def train(network, mnist_ds_train, max_epochs= 50):
  2. net = WithLossCell(network, net_loss)
  3. net = TrainOneStepCell(net, net_opt)
  4. network.set_train()
  5. for epoch in range(1, max_epochs + 1):
  6. train_correct_num = 0.0
  7. test_correct_num = 0.0
  8. for inputs_train in mnist_ds_train:
  9. output = net(*inputs_train)
  10. train_x = inputs_train[0]
  11. train_y = inputs_train[1]
  12. pred_y_train = network.construct(train_x) # 前向传播
  13. train_correct_num += evaluate(pred_y_train, train_y)
  14. train_acc = float(train_correct_num) / train_len
  15. for inputs_test in mnist_ds_test:
  16. test_x = inputs_test[0]
  17. test_y = inputs_test[1]
  18. pred_y_test = network.construct(test_x)
  19. test_correct_num += evaluate(pred_y_test, test_y)
  20. test_acc = float(test_correct_num) / test_len
  21. if (epoch == 1) or (epoch % 10 == 0):
  22. print("epoch: {0}/{1}, train_losses: {2:.4f}, tain_acc: {3:.4f}, test_acc: {4:.4f}" \
  23. .format(epoch, max_epochs, output.asnumpy(), train_acc, test_acc, cflush=True))

8. 配置运行信息

        在正式训练前,通过context.set_context来配置运行需要的信息,譬如运行模式、后端信息、硬件等信息。        

  1. from mindspore import context
  2. context.set_context(mode=context.GRAPH_MODE, device_target="CPU") # device_target 可选 CPU/GPU, 当选择GPU时mindspore规格也需要切换到GPU
'
运行

 9.开始训练

  1. import time
  2. from mindspore.nn import WithLossCell, TrainOneStepCell
  3. max_epochs = 100
  4. start_time = time.time()
  5. print("*"*10 + "开始训练" + "*"*10)
  6. train(network, mnist_ds_train, max_epochs= max_epochs)
  7. print("*"*10 + "训练完成" + "*"*10)
  8. cost_time = round(time.time() - start_time, 1)
  9. print("训练总耗时: %.1f s" % cost_time)
**********开始训练**********

epoch: 1/100, train_losses: 2.2832, tain_acc: 0.1698, test_acc: 0.1626

epoch: 10/100, train_losses: 2.0465, tain_acc: 0.6343, test_acc: 0.6017

epoch: 20/100, train_losses: 1.8368, tain_acc: 0.7918, test_acc: 0.7812

epoch: 30/100, train_losses: 1.7602, tain_acc: 0.8138, test_acc: 0.8017

epoch: 40/100, train_losses: 1.7245, tain_acc: 0.8238, test_acc: 0.7972

epoch: 50/100, train_losses: 1.7051, tain_acc: 0.8337, test_acc: 0.8044

epoch: 60/100, train_losses: 1.6922, tain_acc: 0.8403, test_acc: 0.8047

epoch: 70/100, train_losses: 1.6827, tain_acc: 0.8454, test_acc: 0.8033

epoch: 80/100, train_losses: 1.6752, tain_acc: 0.8501, test_acc: 0.8051

epoch: 90/100, train_losses: 1.6689, tain_acc: 0.8536, test_acc: 0.8049

epoch: 100/100, train_losses: 1.6635, tain_acc: 0.8569, test_acc: 0.8037

**********训练完成**********

训练总耗时: 430.7 s

到目前为止,基于手写数字二分类的代码进行少量修改,就快速实现了手写数字识别的十分类。

修改的过程是非常简单的,但从上面的结果可以看到,该模型训练100个epoch,在手写数字识别十分类的任务上仅仅达到了80%的准确率,而在上一节二分类任务上,模型训练50个epoch达到了99%的准确率,说明在感知机这样简单的模型上,手写数字识别十分类要比二分类要难。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/936820
推荐阅读
相关标签
  

闽ICP备14008679号