- 配置运行信息
MindSpore通过context.set_context来配置运行需要的信息,譬如运行模式、后端信息、硬件信息。
import os
import argparse
from mindspore import context
parser = argparse.ArgumentParser(description='MindSpore LeNet Example')
parser.add_argument('--device_target', type=str, default="CPU", choices=['Ascend', 'GPU', 'CPU'])
args = parser.parse_args()
context.set_context(mode=context.GRAPH_MODE,device_target=args.device_target)
在样例中我们配置运行使用图模式,根据实际情况配置硬件信息。
- 数据处理
MindSpore提供了用于数据处理的APImindspore.dataset,用于存储样本和标签。
这里,我们首先通过导入mindspore.dataest和其他需要的模块来定义数据集及数据操作。
import mindspore.dataset as ds
import mindspore.dataset.transforms.c_transforms as C
import mindspore.dataset.vision.c_transforms as CV
from mindspore.dataset.vision import Inter
from mindspore import dtype as mstype
定义数据集通过构造create_dataest来实现
def create_dataset(data_path, batch_size=32,repeat_size=1,num_parallel_workers=1):
# 定义数据集
mnist_ds = ds.MnistDataset(data_path)
同时在这个函数中,我们定义好需要进行的数据增强和处理操作,为之后的map映射做准备
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映射
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)
在这之后,便可使用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)
为了能保证1个epoch内数据不重复,这里我先进行了shuffle、batch操作,再进行repeat操作
buffer_size = 10000
mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)
mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
return mnist_ds
- 创建模型
神经网络的各层需要预先在__init__方法种定义,然后通过定义construct方法来完成神经网络的前向构造,由此我使用了结构较为简单的LeNet网络结构,并且进行实例化
import mindspore.nn as nn
from mindspore.common.initializer import Normal
class LeNet5(nn.Cell):
"""
LeNet5网络结构
"""
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() #用来将输入”压平“,即把多维的输入一维化
def construct(self, x):
#使用定义好的运算构建前向网络
x = self.conv1(x)
x = self.relu(x)
x = self.max_pool2d(x)
x = self.conv2(x)
x = self.relu(x)
x = self.max_pool2d(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
return x
#实例化网络
net = LeNet5()
- 优化模型参数
要训练神经网络模型,需要定义损失函数和优化器,这里我使用了交叉熵损失函数SoftmaxCrossEntropyWithLogits
#定义损失函数
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
对于优化器我采用了Momentum
#定义优化器
net_opt = nn.Momentum(net.trainable_params(), learning_rate=0.01, momentum=0.9)
- 训练及保存模型
这里我以框架提供的ModelCheckpoint为例,它可以保存网络模型和参数,以便进行后续的fine-tuning操作
from mindspore.train.callback import ModelCheckpoint, CheckpointConfig
# 设置模型保存参数
config_ck = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=10)
#应用模型保存参数
ckpoint = ModelCheckpoint(prefix="checkpoint_lenet", config=config_ck)
同时,利用model.train接口可以方便地进行网络训练,LossMonitor可以监控训练过程中Loss的变化
#导入模型训练需要的库
from mindspore.nn.metrics import Accuracy
from mindspore.train.callback import LossMonitor
from mindspore import Model
def train_net(args, model, epoch_size, data_path, repeat_size, ckpoint_cb, sink_mode):
"""定义训练的方法"""
#加载训练数据集
ds_train = create_dataset(os.path.join(data_path, "train"),32, repeat_size)
model.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor()], dataset_sink_mode=sink_mode)
由此,通过模型运行测试数据集得到加过,验证其泛化能力:
1.使用model.eval接口读入测试数据集;
2.使用保存后的模型参数进行推理;
def test_net(network, model, data_path):
"""定义验证方法"""
ds_eval = create_dataset(os.path.join(data_path,"test"))
acc = model.eval(ds_eval, dataset_sink_mode=False)
print("{}".format(acc))
这里把train_epoch设置为1,即对数据集进行一个迭代的训练,在train_net和test_net方法中,我加载了之前下载的训练数据集
train_epoch = 1
mnist_path = "D:\MNIST_Data"
dataset_size = 1
model = Model(net, net_loss, net_opt, metrics={"Accuracy": Accuracy()})
train_net(args, model, train_epoch, mnist_path, dataset_size, ckpoint, False)
test_net(net, model, mnist_path)
- 加载模型
from mindspore.train.serialization import load_checkpoint, load_param_into_net
#加载已经保存的用于测试的模型
param_dict = load_checkpoint("checkpoint_lenet-1_1875.ckpt")
#加载参数到网络中
load_param_into_net(net, param_dict)
- 验证模型
import numpy as np
import mindspore as ms
import matplotlib.pyplot as plt
mnist = Mnist("E:\\MNIST_Data", split="train", batch_size=6, resize=32)
dataset_infer = mnist.run()
ds_test = dataset_infer.create_dict_iterator()
data = next(ds_test)
images = data["image"].asnumpy()
labels = data["label"].asnumpy()
plt.figure()
for i in range(1, 7):
plt.subplot(2, 3, i)
plt.imshow(images[i-1][0], interpolation="None", cmap="gray")
plt.show()
# 使用函数model.predict预测image对应分类
output = model.predict(ms.Tensor(data['image']))
predicted = np.argmax(output.asnumpy(), axis=1)
# 输出预测分类与实际分类
print(f'Predicted: "{predicted}", Actual: "{labels}"')