首先我们要先了解深度学习的概念和AI计算框架的角色(https://zhuanlan.zhihu.com/p/463019160),本篇文章将演示怎么利用MindSpore来训练一个AI模型。和上一章的场景一致,我们要训练的模型是用来对手写数字图片进行分类的LeNet5模型
请参考(http://yann.lecun.com/exdb/lenet/)。
图1 MindSpore使用流程
安装MindSpore
MindSpore提供给用户使用的是Python接口(什么是Python,请参考:
https://zhuanlan.zhihu.com/p/462756985),所以我们首先需要安装MindSpore的whl包,安装之后就可以导入(import)MindSpore提供的方法接口了。安装whl包有两种方式:
方式一:进入MindSpore官网,根据自己的设备和Python版本选择安装命令。比如我的Python版本是3.7.5,我的设备是笔记本(CPU),那么我就复制下图红框中的命令进行安装:
图2 MindSpore安装界面
安装过程如下:
图3 MindSpore安装过程
注意:由于MindSpore还依赖于其他的Python三方库,所以在安装过程中,系统还会自动下载、安装其他的Python三方库,如numpy、pillow、scipy等等,安装结束后,如果能 import mindspore 成功,说明MindSpore安装成功了:
图4 MindSpore安装成功
方式二:可以在版本列表中找到对应的whl包,点击就能下载:
图5 MindSpore版本下载列表
下载完成后,把whl包放到自己的目录下,执行 pip install xxx.whl:
图6 MindSpore第二种安装方式
定义模型
安装好MindSpore之后,我们就可以导入MindSpore提供的算子(卷积、全连接、池化等函数:https://zhuanlan.zhihu.com/p/463019160)来构建我们的模型了。可以这么比喻:我们构建一个AI模型就像建一个房子,而MindSpore提供给我们的算子就像是砖块、窗户、地板等基本组件。
图7 定义LeNet5模型
如上图所示,我们用到的“砖块”都是mindspore.nn模块提供的。注意:这里用到了Python的类(class),由②和③两部分组成。我们这里定义的类是class LeNet5,它由初始化函数 __init__(self) 和构造函数construct(self, x)组成。初始化函数定义了我们构造模型所需要用到的算子,比如conv算子、relu算子、flatten算子等等,这些算子都是从mindspore.nn获取的;构造函数就是把我们在初始化函数中导入的算子按顺序排放,构成我们最终的模型。construct()函数的输入就是我们这个模型预测的对象,比如第一章讲的黑白图片像素矩阵;而“return y”中的就是预测的结果,对应于第一章讲到的10分类手写数字数据集,就是一个行10列的数组(这里的是指输入图片的数量,AI模型支持多张图片同时推理)。
导入训练数据集
什么是训练数据集?刚刚定义好的模型是不能对图片进行正确分类的,我们要通过“训练”过程来调整模型的参数矩阵的值。训练过程就需要用到训练样本,也就是打上了正确标签的图片。这就好比我们教小孩儿认识动物,需要拿几张图片给他们看,然后告诉他们这是什么、那是什么,教了几遍之后,小孩儿就能认识了。那么我们训练LeNet5模型就需要用到MNIST数据集,请参考(http://yann.lecun.com/exdb/mnist/)。这个数据集由两部分组成:训练集(6万张图片)和测试集(1万张图片),都是0~9的黑白手写数字图片。训练集是用来训练AI模型的,测试集是用来测试训练后的模型分类准确率的。
下载得到的数据集最初是压缩文件,还不能直接传给MindSpore的训练接口使用,我们要先用MindSpore提供的数据处理接口把他们读进来:
import mindspore.dataset as ds
mnist_ds = ds.MnistDataset(data_path) # 导入下载的MNIST数据集
然后进行数据增强(比如把图片大小转化成相同的尺寸、像素值标准化、归一化等操作),提升训练效率:
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): # batch_size是每一步训练使用的图片数量,一般取32
"""
create dataset for train or test
Args:
data_path (str): Data path
batch_size (int): The number of data records in each group
"""
# define dataset
mnist_ds = ds.MnistDataset(data_path) # 导入下载的MNIST数据集
# 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")
mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image")
mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image")
mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image")
mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image")
# 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)
return mnist_ds
训练模型
训练数据集和模型定义完成之后呢,我们就可以开始训练模型了。但是在训练之前,我们还需要从MindSpore导入两个函数:
-
损失函数,也就是衡量预测结果和真实标签之间的差距的函数。看过上一章的同学可能会记得,我们之前用的损失函数是真实值与预测值之差的2-范数:
图8 2-范数损失
在这里,我们使用业界最常用的交叉熵损失函数SoftmaxCrossEntropyWithLogits,对于真实标签
和预测值,它们之间的交叉熵损失计算公式为:
其中J代表数组的下标,。从MindSpore导入损失函数:
from mindspore.nn import SoftmaxCrossEntropyWithLogits
# define the loss function
net_loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
-
优化器,优化器就是用来求解损失函数关于模型参数的更新梯度的,它是整个训练过程中最重要的工具!我们这里用MindSpore提供的Momentum优化器:
import mindspore.nn as nn
lr = 0.01 # 定义学习率
momentum = 0.9 # 定义Momentum优化器的超参
# define the optimizer
net_opt = nn.Momentum(network.trainable_params(), lr, momentum) # 导入mindspore提供
准备好损失函数和优化器之后我们就可以开始训练模型了,也非常简单,我们先把前面定义好的模型、损失函数、优化器封装成一个Model:
from mindspore import Model
net = LeNet5()
model = Model(net, net_loss , net_opt , metrics={'acc', 'loss'})
然后使用model.train接口就可以训练我们定义的LeNet5模型了:
loss_cb = LossMonitor(per_print_times=ds_train.get_dataset_size()) # 用于监控训练过程中损失函数值的变化
ds_train = create_dataset(train_data_dir) # 传入下载的训练集的路径
model.train(num_epochs, ds_train, callbacks=[loss_cb]) # num_epochs是训练的轮数,往往训练多轮才能使模型收敛
测试训练后的模型准确率
训练结束后,调用model.eval()计算训练后的模型在测试集上面的分类准确率:
ds_eval = create_dataset(test_data_dir) # 传入下载的训练集的路径
metrics = model.eval(ds_eval)
小结
祝贺你耐心看完了MindSpore训练模型的完整过程,如果你想动手操作一遍,但是又没有现成的环境,那么你可以使用官网提供的“在线运行”来体验一番:
图9 MindSpore官网提供的免费体验入口
这是体验过程的实操视频:
https://zhuanlan.zhihu.com/p/463229660
欢迎投稿
欢迎大家踊跃投稿,有想投稿技术干货、项目经验等分享的同学,可以添加MindSpore官方小助手:小猫子(mindspore0328)的微信,告诉猫哥哦!
昇思MindSpore官方交流QQ群 : 486831414(群里有很多技术大咖助力答疑!)
MindSpore官方资料
GitHub : https://github.com/mindspore-ai/mindspore
Gitee : https : //gitee.com/mindspore/mindspore
官方QQ群 : 486831
文章出处登录后可见!