MindSpore 1.2.0实现一个图片分类应用
一、平台环境
CPU:鲲鹏920
内存:16GB
硬盘:500GB
操作系统:Ubuntu 18.04
二、安装Mindspore 1.2.0
安装过程参见官网教程:https://mindspore.cn/install/
使用mindspore.__version查看MindSpore版本
三、前期准备
1.下载数据集
!mkdir -p ./datasets/MNIST_Data/train ./datasets/MNIST_Data/test !wget -NP ./datasets/MNIST_Data/train https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/train-labels-idx1-ubyte !wget -NP ./datasets/MNIST_Data/train https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/train-images-idx3-ubyte !wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-labels-idx1-ubyte !wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-images-idx3-ubyte
2.导入库
import os
3.配置运行信息
from mindspore import context context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
4.数据处理
import matplotlib.pyplot as plt import matplotlib import numpy as np import mindspore.dataset as ds train_data_path = "./datasets/MNIST_Data/train" test_data_path = "./datasets/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() item = next(dic_ds) img = item["image"].asnumpy() label = item["label"].asnumpy() 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)) 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: 4
5. 定义数据集及数据操作
import mindspore.dataset.vision.c_transforms as CV import mindspore.dataset.transforms.c_transforms as C from mindspore.dataset.vision import Inter from mindspore import dtype as mstype def create_dataset(data_path, batch_size=32, repeat_size=1, num_parallel_workers=1): """ 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 # according to the parameters, generate the corresponding data enhancement method 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) hwc2chw_op = CV.HWC2CHW() type_cast_op = C.TypeCast(mstype.int32) # using map to apply operations to a dataset 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 buffer_size = 10000 mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True) mnist_ds = mnist_ds.repeat(repeat_size) 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
6.查看增强后的数据
data = next(ms_dataset.create_dict_iterator(output_numpy=True)) images = data["image"] labels = data["label"] print('Tensor of image:', images.shape) print('Labels:', labels)
Tensor of image: (32, 1, 32, 32)
Labels: [1 1 2 0 8 8 5 7 6 0 6 5 8 8 6 7 5 3 9 2 6 1 3 2 7 9 7 0 4 7 3 3]
7.将张量数据和label对应的值进行可视化
count = 1 for i in images: plt.subplot(4, 8, count) plt.imshow(np.squeeze(i)) plt.title('num:%s'%labels[count-1]) plt.xticks([]) count += 1 plt.axis("off") plt.show()
四、定义网络
1.定义网络
import mindspore.nn as nn from mindspore.common.initializer import Normal class LeNet5(nn.Cell): """Lenet network structure.""" # define the operator required def __init__(self, num_class=10, num_channel=1): super(LeNet5, self).__init__() self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid') self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid') 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)) self.relu = nn.ReLU() self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2) self.flatten = nn.Flatten() # use the preceding operators to construct networks def construct(self, x): x = self.max_pool2d(self.relu(self.conv1(x))) x = self.max_pool2d(self.relu(self.conv2(x))) x = self.flatten(x) x = self.relu(self.fc1(x)) x = self.relu(self.fc2(x)) x = self.fc3(x) return x network = LeNet5() print("layer conv1:", network.conv1) print("*"*40) print("layer fc1:", network.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>
2. 自定义回调函数收集模型的损失值和精度值
from mindspore.train.callback import Callback # custom callback function class StepLossAccInfo(Callback): def __init__(self, model, eval_dataset, steps_loss, steps_eval): self.model = model self.eval_dataset = eval_dataset self.steps_loss = steps_loss self.steps_eval = steps_eval def step_end(self, run_context): cb_params = run_context.original_args() cur_epoch = cb_params.cur_epoch_num cur_step = (cur_epoch-1)*1875 + cb_params.cur_step_num self.steps_loss["loss_value"].append(str(cb_params.net_outputs)) self.steps_loss["step"].append(str(cur_step)) if cur_step % 125 == 0: acc = self.model.eval(self.eval_dataset, dataset_sink_mode=False) self.steps_eval["step"].append(cur_step) self.steps_eval["acc"].append(acc["Accuracy"])
3.定义损失函数及优化器
MindSpore支持的损失函数有SoftmaxCrossEntropyWithLogits、L1Loss、MSELoss等。这里使用SoftmaxCrossEntropyWithLogits损失函数。
MindSpore支持的优化器有Adam
、AdamWeightDecay
、Momentum
等。这里使用流行的Momentum
优化器。
import mindspore.nn as nn from mindspore.nn import SoftmaxCrossEntropyWithLogits lr = 0.01 momentum = 0.9 # create the network network = LeNet5() # define the optimizer net_opt = nn.Momentum(network.trainable_params(), lr, momentum) # define the loss function net_loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
五、训练
import os from mindspore import Tensor, Model from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor from mindspore.nn import Accuracy epoch_size = 1 mnist_path = "./datasets/MNIST_Data" model_path = "./models/ckpt/mindspore_quick_start/" repeat_size = 1 ds_train = create_dataset(os.path.join(mnist_path, "train"), 32, repeat_size) eval_dataset = create_dataset(os.path.join(mnist_path, "test"), 32) # clean up old run files before in Linux os.system('rm -f {0}*.ckpt {0}*.meta {0}*.pb'.format(model_path)) # define the model model = Model(network, net_loss, net_opt, metrics={"Accuracy": 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) steps_loss = {"step": [], "loss_value": []} steps_eval = {"step": [], "acc": []} # collect the steps,loss and accuracy information step_loss_acc_info = StepLossAccInfo(model , eval_dataset, steps_loss, steps_eval) model.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor(125), step_loss_acc_info], dataset_sink_mode=False)
epoch: 1 step: 125, loss is 2.2951596 epoch: 1 step: 250, loss is 2.296546 epoch: 1 step: 375, loss is 2.2990193 epoch: 1 step: 500, loss is 2.3200133 epoch: 1 step: 625, loss is 2.3039348 epoch: 1 step: 750, loss is 2.2943583 epoch: 1 step: 875, loss is 0.5839526 epoch: 1 step: 1000, loss is 0.16641633 epoch: 1 step: 1125, loss is 0.32308063 epoch: 1 step: 1250, loss is 0.17725793 epoch: 1 step: 1375, loss is 0.24122497 epoch: 1 step: 1500, loss is 0.32769728 epoch: 1 step: 1625, loss is 0.17113523 epoch: 1 step: 1750, loss is 0.025801359 epoch: 1 step: 1875, loss is 0.012723763
训练完成后会产生一些ckpt文件
六、查看模型损失值随着训练步数的变化情况
steps = steps_loss["step"] loss_value = steps_loss["loss_value"] steps = list(map(int, steps)) loss_value = list(map(float, loss_value)) plt.plot(steps, loss_value, color="red") plt.xlabel("Steps") plt.ylabel("Loss_value") plt.title("Change chart of model loss value") plt.show()
七、验证模型
from mindspore import load_checkpoint, load_param_into_net # 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/mindspore_quick_start/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.9597355769230769} ==============
可视化验证结果
def eval_show(steps_eval): plt.xlabel("step number") plt.ylabel("Model accuracy") plt.title("Model accuracy variation chart") plt.plot(steps_eval["step"], steps_eval["acc"], "red") plt.show() eval_show(steps_eval)
八、推理预测
ds_test = create_dataset(test_data_path).create_dict_iterator() data = next(ds_test) images = data["image"].asnumpy() labels = data["label"].asnumpy() output = model.predict(Tensor(data['image'])) pred = np.argmax(output.asnumpy(), axis=1) err_num = [] index = 1 for i in range(len(labels)): plt.subplot(4, 8, i+1) color = 'blue' if pred == labels else 'red' plt.title("pre:{}".format(pred), color=color) plt.imshow(np.squeeze(images)) plt.axis("off") if color == 'red': index = 0 print("Row {}, column {} is incorrectly identified as {}, the correct value should be {}".format(int(i/8)+1, i%8+1, pred, labels), '\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 3, column 5 is incorrectly identified as 7, the correct value should be 8
[5 4 5 3 4 9 6 9 1 4 9 7 8 3 3 5 6 9 3 2 7 1 1 8 6 5 6 1 9 4 0 1] <--Predicted figures
[5 4 5 3 4 9 6 9 1 4 9 7 8 3 3 5 6 9 3 2 8 1 1 8 6 5 6 1 9 4 0 1] <--The right number
构建一个分析饼图
import numpy as np # define the pie drawing function of probability analysis prb = output.asnumpy() def plot_pie(prbs): dict1 = {} # remove the negative number and build the dictionary dict1. The key is the number and the value is the probability value for i in range(10): if prbs > 0: dict1[str(i)] = prbs label_list = dict1.keys() size = dict1.values() colors = ["red", "green", "pink", "blue", "purple", "orange", "gray"] color = colors[: len(size)] plt.pie(size, colors=color, labels=label_list, labeldistance=1.1, autopct="%1.1f%%", shadow=False, startangle=90, pctdistance=0.6) plt.axis("equal") plt.legend() plt.title("Image classification") plt.show() print("The probability of corresponding numbers [0-9] in Figure 1:\n", list(map(lambda x:1/(1+np.exp(-x)), prb[0]))) plot_pie(prb[0])
The probability of corresponding numbers [0-9] in Figure 1:
[0.013787607394849927, 0.007575208530339499, 0.0028451085500773576, 0.9852382873716746, 0.13068974067662964, 0.9999823593626983, 0.5067418267147699, 0.0055385518228474725, 0.9551294581161474, 0.989552912451914]
至此,所有的Mindspore1.2体验图片分类的Demo算是完成了