运行方式
概述
执行主要有三种方式:单算子、普通函数和网络训练模型。
本文示例适用于GPU和Ascend环境。
执行单算子
执行单个算子,并打印相关结果。
代码样例如下:
[1]:
import numpy as np
import mindspore.nn as nn
from mindspore import context, Tensor
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
conv = nn.Conv2d(3, 4, 3, bias_init='zeros')
input_data = Tensor(np.ones([1, 3, 5, 5]).astype(np.float32))
output = conv(input_data)
print(output.asnumpy())
[[[[ 0.01647821 0.05310077 0.05310077 0.05310077 0.05118286]
[ 0.03007141 0.0657572 0.0657572 0.0657572 0.04350833]
[ 0.03007141 0.0657572 0.0657572 0.0657572 0.04350833]
[ 0.03007141 0.0657572 0.0657572 0.0657572 0.04350833]
[ 0.01847598 0.04713529 0.04713529 0.04713529 0.03720935]]
[[-0.03362034 -0.06124294 -0.06124294 -0.06124294 -0.04334928]
[-0.02676596 -0.08040315 -0.08040315 -0.08040315 -0.06846539]
[-0.02676596 -0.08040315 -0.08040315 -0.08040315 -0.06846539]
[-0.02676596 -0.08040315 -0.08040315 -0.08040315 -0.06846539]
[-0.00557975 -0.06808633 -0.06808633 -0.06808633 -0.08389233]]
[[-0.01602227 0.02266152 0.02266152 0.02266152 0.06030601]
[-0.06764769 -0.02966945 -0.02966945 -0.02966945 0.04861854]
[-0.06764769 -0.02966945 -0.02966945 -0.02966945 0.04861854]
[-0.06764769 -0.02966945 -0.02966945 -0.02966945 0.04861854]
[-0.06528193 -0.03500666 -0.03500666 -0.03500666 0.02858584]]
[[-0.03102187 -0.03846825 -0.03846825 -0.03846825 -0.00858424]
[-0.04270145 -0.070785 -0.070785 -0.070785 -0.05362675]
[-0.04270145 -0.070785 -0.070785 -0.070785 -0.05362675]
[-0.04270145 -0.070785 -0.070785 -0.070785 -0.05362675]
[-0.01230605 -0.04999261 -0.04999261 -0.04999261 -0.04718029]]]]
由于weight初始化存在随机因素,实际输出结果可能不同,仅供参考。
执行普通函数
将若干算子组合成一个函数,然后直接通过函数调用的方式执行这些算子,并打印相关结果,如下例所示。
代码样例如下:
[2]:
import numpy as np
from mindspore import context, Tensor
import mindspore.ops as ops
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
def add_func(x, y):
z = ops.add(x, y)
z = ops.add(z, x)
return z
x = Tensor(np.ones([3, 3], dtype=np.float32))
y = Tensor(np.ones([3, 3], dtype=np.float32))
output = add_func(x, y)
print(output.asnumpy())
[[3. 3. 3.]
[3. 3. 3.]
[3. 3. 3.]]
执行网络模型
MindSpore的Model接口是用于训练和验证的高级接口。可以将有训练或推理功能的layers组合成一个对象,通过调用train
、eval
、predict
接口可以分别实现训练、推理和预测功能。
MindSpore不支持使用多线程来进行训练、推理和预测功能。
用户可以根据实际需要传入网络、损失函数和优化器等初始化Model接口,还可以通过配置amp_level
实现混合精度,配置metrics
实现模型评估。
执行网络模型会在执行目录下生成
kernel_meta
目录,并在执行过程中保存网络编译生成的算子缓存文件到此目录,包括.o
,.info
和.json
文件。若用户再次执行相同的网络模型,或者仅有部分变化,MindSpore会自动调用kernel_meta
目录下可复用的算子缓存文件,显著减少网络编译时间,提升执行性能。详细内容请参考算子增量编译。
在执行网络之前,先将所需要的数据集下载并解压缩到指定位置,在Jupyter Notebook中执行如下命令:
[3]:
!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 --no-check-certificate
!wget -NP ./datasets/MNIST_Data/train https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/train-images-idx3-ubyte --no-check-certificate
!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-labels-idx1-ubyte --no-check-certificate
!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-images-idx3-ubyte --no-check-certificate
!tree ./datasets/MNIST_Data
./datasets/MNIST_Data
├── test
│ ├── t10k-images-idx3-ubyte
│ └── t10k-labels-idx1-ubyte
└── train
├── train-images-idx3-ubyte
└── train-labels-idx1-ubyte
2 directories, 4 files
执行训练模型
通过调用Model的train接口可以实现训练。
代码样例如下:
[4]:
import os
import mindspore.dataset.vision.c_transforms as CV
from mindspore.dataset.vision import Inter
import mindspore.dataset as ds
import mindspore.dataset.transforms.c_transforms as CT
import mindspore.nn as nn
from mindspore import context, Model
from mindspore import dtype as mstype
from mindspore.common.initializer import Normal
from mindspore.train.callback import LossMonitor, ModelCheckpoint, CheckpointConfig
def create_dataset(data_path, batch_size=32, repeat_size=1,
num_parallel_workers=1):
"""
create dataset for train or test
"""
# define dataset
mnist_ds = ds.MnistDataset(data_path)
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
# define map operations
resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) # Bilinear mode
rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
rescale_op = CV.Rescale(rescale, shift)
hwc2chw_op = CV.HWC2CHW()
type_cast_op = CT.TypeCast(mstype.int32)
# apply map operations on images
mnist_ds = mnist_ds.map(input_columns="label", operations=type_cast_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=resize_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_nml_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=hwc2chw_op, num_parallel_workers=num_parallel_workers)
# apply DatasetOps
buffer_size = 10000
mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) # 10000 as in LeNet train script
mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
mnist_ds = mnist_ds.repeat(repeat_size)
return mnist_ds
class LeNet5(nn.Cell):
"""
Lenet network
Args:
num_class (int): Num classes. Default: 10.
num_channel (int): Num channels. Default: 1.
Returns:
Tensor, output tensor
Examples:
>>> LeNet(num_class=10)
"""
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.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
if __name__ == "__main__":
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
model_path = "./models/ckpt/mindspore_run/"
os.system("rm -rf {0}*.ckpt {0}*.meta {0}*.pb".format(model_path))
ds_train_path = "./datasets/MNIST_Data/train/"
ds_train = create_dataset(ds_train_path, 32)
network = LeNet5(10)
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)
config_ck = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=5)
ckpoint_cb = ModelCheckpoint(prefix="checkpoint_lenet", directory=model_path, config=config_ck)
model = Model(network, net_loss, net_opt)
print("============== Starting Training ==============")
model.train(1, ds_train, callbacks=[LossMonitor(375), ckpoint_cb], dataset_sink_mode=True)
============== Starting Training ==============
epoch: 1 step: 375, loss is 2.2898183
epoch: 1 step: 750, loss is 2.2777305
epoch: 1 step: 1125, loss is 0.27802905
epoch: 1 step: 1500, loss is 0.032973606
epoch: 1 step: 1875, loss is 0.06105463
示例中用到的MNIST数据集的获取方法,可以参照实现一个图片分类应用的下载数据集部分,下同。
使用PyNative模式调试, 请参考使用PyNative模式调试, 包括单算子、普通函数和网络训练模型的执行。
使用自由控制循环的迭代次数、遍历数据集等,可以参照官网编程指南《训练》的自定义循环训练部分。
执行推理模型
通过调用Model的eval接口可以实现推理。为了方便评估模型的好坏,可以在Model接口初始化的时候设置评估指标Metric。
Metric是用于评估模型好坏的指标。常见的主要有Accuracy、Fbeta、Precision、Recall和TopKCategoricalAccuracy等,通常情况下,一种模型指标无法全面的评估模型的好坏,一般会结合多个指标共同作用对模型进行评估。
常用的内置评估指标:
Accuracy
(准确率):是一个用于评估分类模型的指标。通俗来说,准确率是指我们的模型预测正确的结果所占的比例。 公式:\[Accuracy = (TP+TN)/(TP+TN+FP+FN)\]Precision
(精确率):在被识别为正类别的样本中,确实为正类别的比例。公式:\[Precision = TP/(TP+FP)\]Recall
(召回率):在所有正类别样本中,被正确识别为正类别的比例。 公式:\[Recall = TP/(TP+FN)\]Fbeta
(调和均值):综合考虑precision和recall的调和均值。 公式:\[F_\beta = (1 + \beta^2) \cdot \frac{precisiont \cdot recall}{(\beta^2 \cdot precision) + recall}\]TopKCategoricalAccuracy
(多分类TopK准确率):计算TopK分类准确率。
代码样例如下:
[5]:
import mindspore.dataset as ds
import mindspore.dataset.transforms.c_transforms as CT
import mindspore.dataset.vision.c_transforms as CV
import mindspore.nn as nn
from mindspore import context, Model, load_checkpoint, load_param_into_net
from mindspore import dtype as mstype
from mindspore.common.initializer import Normal
from mindspore.dataset.vision import Inter
from mindspore.nn import Accuracy, Precision
class LeNet5(nn.Cell):
"""
Lenet network
Args:
num_class (int): Num classes. Default: 10.
num_channel (int): Num channels. Default: 1.
Returns:
Tensor, output tensor
Examples:
>>> LeNet(num_class=10)
"""
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.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
def create_dataset(data_path, batch_size=32, repeat_size=1,
num_parallel_workers=1):
"""
create dataset for train or test
"""
# define dataset
mnist_ds = ds.MnistDataset(data_path)
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
# define map operations
resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) # Bilinear mode
rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
rescale_op = CV.Rescale(rescale, shift)
hwc2chw_op = CV.HWC2CHW()
type_cast_op = CT.TypeCast(mstype.int32)
# apply map operations on images
mnist_ds = mnist_ds.map(input_columns="label", operations=type_cast_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=resize_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_nml_op, num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(input_columns="image", operations=hwc2chw_op, num_parallel_workers=num_parallel_workers)
# apply DatasetOps
buffer_size = 10000
mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) # 10000 as in LeNet train script
mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
mnist_ds = mnist_ds.repeat(repeat_size)
return mnist_ds
if __name__ == "__main__":
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
model_path = "./models/ckpt/mindspore_run/"
ds_eval_path = "./datasets/MNIST_Data/test/"
network = LeNet5(10)
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
repeat_size = 1
net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)
model = Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy(), "Precision": Precision()})
print("============== Starting Testing ==============")
param_dict = load_checkpoint(model_path+"checkpoint_lenet-1_1875.ckpt")
load_param_into_net(network, param_dict)
ds_eval = create_dataset(ds_eval_path, 32, repeat_size)
acc = model.eval(ds_eval, dataset_sink_mode=True)
print("============== {} ==============".format(acc))
============== Starting Testing ==============
============== {'Accuracy': 0.960136217948718, 'Precision': array([0.95763547, 0.98059965, 0.99153439, 0.93333333, 0.97322348,
0.99385749, 0.98502674, 0.93179724, 0.8974359 , 0.97148676])} ==============
其中:
load_checkpoint
:通过该接口加载CheckPoint模型参数文件,返回一个参数字典。checkpoint_lenet-1_1875.ckpt
:保存的CheckPoint模型文件名称。load_param_into_net
:通过该接口把参数加载到网络中。
checkpoint_lenet-1_1875.ckpt
文件的保存方法,可以参考实现一个图片分类应用的训练网络部分。