不知不觉就这样到了2021年2月的最后一个周,距离『第五期MindSpore两日集训营』开课有一个月了,在这段时间里你投资了什么,又收获了什么呢?
人生最值得的投资就是磨练自己,因为生活与服务人群都得靠自己,这是最珍贵的工具。工作本身并不能带来经济上的安全感,具备良好的思考、学习、创造与适应能力,才能立于不败之地;拥有财富,并不代表经济独立,拥有创造财富的能力才真正可靠。
所以需要不断的学习,更新自己,更加重要的是在每个阶段给自己留出回顾和总结的时间,反思这段路的付出与收获,确定下个行程的目标定在何方~
先和大家分享两篇来自第五期集训营学员输出的学习总结,希望对你的生活和工作能有所帮助。
MindSpore 学习心得
经过这几天对MinSpore框架的学习和简单尝试,巩固了我之前学的Pytorch和Tensorflow的知识,并且对开发一个真正高效计算框架有了深刻的认识。
首先说最大的感受:MindSpore不愧是华为开发的深度学习框架。从它诞生起,它的整体架构的思路就是既符合工业界实打实的落地需求(高性能,软硬结合,全栈解决方案、高并发、分布式、面向大数据、面向前后端分离的部署)等等,又对学术界的使用也很友好。在我眼里MindSpore可以说是一个Tensorflow与Pytorch的结合体,一个后起新秀。下面我来从6个角度分别谈谈自己的感受。
MindIR
MindIR可以说是从根本上把之前随意的模型存储格式从原生框架里面给标准化了。MindIR远不只是模型参数的checkpoints,它能兼容任意场景的训练推理,CPU、GPU、Ascend等等。以前写pytorch的代码,总感觉自己训练出来的模型如果要部署很麻烦,总是离实际工业应用很远,而有了MindIR之后,不管是部署在服务器,还是手机都能很快搞定。
MindIR在MindSpore中的位置
MindSpore Lite
这个可以是学习MindSpore中最难的一小块了。写MindSpore Lite的代码,我用了C++代码,把官方的文档东拼西凑,最终终于调通了。还专门用cmake架构了一下整体的代码,Lite的infer库需要在C++代码里面手动链接才行。当然这样也造就了Lite强大的时效性,毕竟移动端最最重要的还是在有限资源下的实时反馈。
MindSpore Lite同时有一个非常有用的小工具:Convert Lite,这个能直接把各种格式的模型给转化成移动端的ms格式模型,同时也附加了一定的量化加速模型的功能,非常好用。
Lite在端侧推理的时序图
不过还是要小小吐槽一下,MindSpore Lite的官方文档写的有点糟糕。r1.1版本的文档里面,没有给x86下C++做infer的完整的样例,只给了Android平台的代码。看的非常费力。希望官方能把Lite这一块的文档再完善完善。
MindSpore Serving
这个功能说实话,让我眼前一亮。碰巧我前段时间做项目的时候也写过将Pytorch及Tensorflow模型代码部署成HTTP服务,用RESTful的方式。但是Pytorch没有原生RESTful及gRPC的支持,当时我花了很久才写好相关的server和client的代码。当然写好只是其中的一小步,后期还涉及并发调用呀,维护,安全等等各种东西,超级麻烦。以及如果想要做实时检测,还要考虑封装batch,batch信息的网络传输,多线程等等超级多的细节。
我没想到的是MindSpore这么快就原生支持了Serving部署,并且封装了RESTful和gRPC两种调用方式。碰巧Serving库就满足了我上面提到的所有需求。尝试了一下样例,写起来没问题,可惜代码跑不了。目前Serving只支持Ascend平台的运行,希望后面MindSpore能尽快推出CPU和GPU上Serving的支持!
PyNative
哈哈,这个功能,通俗的来说,就是通过context的全局设置,一键切换Pytorch模式和Tensorflow模式。为什么这么说呢?众所周知,Tensorflow是静态图利于部署但不利于科研调试。Pytorch是动态图利于科研调试但不利于部署。以前都以为这是水火不容的两件事情,换句话说是鱼与熊掌不可兼得。而MindSpore设计的时候可以说是集两家之长。通过下面的一段代码就能一键切换动态图和静态图两个模式了。
import mindspore as ms
# 静态图
ms.context.set_context(mode=ms.context.GRAPH_MODE, device_target="CPU")
# 动态图
ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target="CPU")
笔者也亲自试了一下,如果使用静态图模式下在model里面打断点是进不去的,而如果是动态图模式,能够断点运行到模型内部infer的部分,这样就非常利于调试了。
当然底层实现起来肯定非常复杂,静态图会将模型先进行预编译,从而加速模型推理和训练的速度。动态图则是在执行过程中搭建计算图,方便用户调试。
Cache缓存服务
这个功能也挺有趣的。以前我在大规模数据下训练网络的时候,经常遇到把硬盘IO占满了,导致了训练速度缓慢。当然有钱人就直接堆固态硬盘。当年我也写过一些底层多线程缓存加载数据的,不过都很麻烦,也容易写错。其实随着数据规模越来越大,训练速度的瓶颈已经不再是矩阵相乘的速度,而是在通信上。比如计算单元间数据汇总的通信,计算单元与数据存储器间硬盘的IO,集群间机器的通讯,等等。庆幸的是MindSpore也看到了这个问题,并且非常重视这个问题,专门开发了Cache Server和Cache Client来加速数据加载,提高整体的训练效率。真棒!
用起来也挺方便的,服务开启之后,直接在代码的数据预处理操作里面传通过session id构建cache类就行啦。代码如下:
import mindspore.dataset as ds
import mindspore.dataset.vision.c_transforms as C
some_cache = ds.DatasetCache(275147964, size=0, spilling=True)
cifar_ds = ds.Cifar10Dataset(data_home, num_parallel_workers=8, shuffle=True)
c_trans = [
C.Resize((224, 224)),
C.Rescale(1.0/255.0, 0.0),
C.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
C.HWC2CHW()
]
cifar_ds = cifar_ds.map(operations=c_trans, input_columns="image", num_parallel_workers=8, cache=some_cache)
some_cache就是构建出来的缓存类,第一个参数是通过命令行运行cache server得到的session id。这段代码将整个c_trans数据预处理进行了缓存加速,通过对数据集进行操作的map函数的cache参数指定了缓存类。
MindSpore 调试器
这个功能也挺酷炫的,不过现在只能装在集群服务器上,希望能尽快对单机GPU服务器进行适配支持。在华为云上简单用了下这个,对整个网络的参数都记录下来可以查看,非常方便。基本不需要在代码里面修改什么东西,以后肯定干得过Tensorboard。
*原文链接:
https://zhuanlan.zhihu.com/p/347636685
在线体验 MindIR 格式模型生成
众所周知,人工智能能有今天的发展离不开数据、算力和算法。作为普通的Copy攻城狮,手头没有良好的硬件支撑AI的学习,焦头烂额,还好有她--ModelArts 。ModelArts是华为云的一站式AI开发平台,其中有个「我的笔记本」功能,是即开即用、用于机器学习的在线集成开发环境,可以轻松的构建、训练、调试、部署机器学习算法与模型。关键是免费!免费!免费!
关于 MindIR
此次 MindSpore 第五期集训营的第一节课主要讲的就是 MindIR 。MindIR是MindSpore提供的中间表达形式,可以帮助我们实现一次训练多处部署,实现端云互通。比如我们可以在Ascend AI处理器、GPU、CPU等不同平台上训练并导出MindIR文件,然后快速部署到手机端或者用MindSpore Serving服务等环境上,体验到MindSpore的全场景能力。MindIR的具体实现细节请阅读《AI框架中图层IR的分析》。因为,Copy攻城狮只关心如何应用:
接下来通过两个具体的在线案例了解一下 MindIR 格式的模型是如何生成的。
MindSpore 调试器
导出LeNet网络的MindIR格式模型
官方文档:
https://www.mindspore.cn/tutorial/training/zh-CN/r1.1/use/save_model.html
云上体验:
https://console.huaweicloud.com/modelarts/?region=cn-north-4#/notebook/loading
这是一个可以在 CPU 环境运行的案例,使用的是 LeNet 网络 和 MNIST 数据集。具体的实现本文不再赘述,总之这个案例详细介绍了 MindSpore 中数据处理、网络定义、模型训练、模型保存、模型验证等相关知识点。本文关注点在「导出MindIR格式文件」。点击上边或者官方文档的 「Run in ModelArts」 就可跳转到华为云一站式AI开发平台,我们进入的其实是 ModelArts 的 「我的笔记本」功能--一个基于 JupyterLab 构建的在线集成开发环境,还可以快速切换不同环境平台。当前案例使用的是 GPU 环境,MindSpore 版本为 1.0.1 。根据文档并执行代码,我们很快就能实现一个 LeNet 网络并得到训练之后的模型。
目前导出 MINDIR 格式模型文件基于前置步骤生成的 CheckPoint 文件。官方文档建议使用.mindir作为MINDIR格式文件的后缀名。导出 MINDIR 格式文件的代码如下:
from mindspore.train.serialization import export, load_checkpoint, load_param_into_net
from mindspore import Tensor
import numpy as np
lenet = LeNet5()
# 返回模型的参数字典
param_dict = load_checkpoint("./models/ckpt/mindspore_save_model/lenet-1_1875.ckpt")
# 加载参数到网络
load_param_into_net(lenet, param_dict)
input = np.random.uniform(0.0, 1.0, size=[32, 1, 32, 32]).astype(np.float32)
# 以指定的名称和格式导出文件
export(lenet, Tensor(input), file_name='lenet-1_1875.mindir', file_format='MINDIR',)
导出完成之后,在当前目录下会生成一个MINDIR格式文件,如下图中名为lenet-1_1875.mindir的文件。
当然如果您想将 LeNet 模型导出为不同格式的文件,建议您进行封装,具体实践请参考链接:
mindspore/model_zoo/official/cv/lenet/export.py
训练ResNet50网络导出MindIR格式模型
官方文档:
https://www.mindspore.cn/tutorial/training/zh-CN/r1.1/advanced_use/cv_resnet50.html
云上体验:
https://notebook01-modelarts-cnnorth4.huaweicloud.com/03483fbf-1c09-4097-8b77-95410161fe60/lab/workspaces/auto-S&clone
有了上一次的在线体验,在进行训练ResNet50网络导出MindIR格式模型的时候,可谓“轻车熟路”,同样的点击「Run in ModelArts」开始我们的云端AI开发之旅。这次我们使用的是ResNet-50网络,CIFAR-10数据集,依旧是 MIndSpore 1.0.1 版本,不过是 GPU 环境的。
目前, ModelArts 中 「我的笔记本」要想使用 GPU 版本的 MIndSpore,好像暂时只有这个入口。当然,这个案例中并没有实现将模型导出为 MindIR 格式,需要我们手动添加,唯一值得注意的是 MindSpore 1.0.1 和 MIndSpore 1.1.0 中 导出的方法「export」放在不同的命名空间下,1.1.0版本的引入方法是
from mindspore import Tensor, export, load_checkpoint, load_param_into_net
而 1.1.0版本中的引入方法是
from mindspore.train.serialization import export, load_checkpoint, load_param_into_net
因此,这里导出ResNet50网络 MindIR 格式的代码为:
from resnet import resnet50
from mindspore.train.serialization import export, load_checkpoint, load_param_into_net
from mindspore import Tensor
import numpy as np
resnet = resnet50(batch_size=32, num_classes=10)
# return a parameter dict for model
param_dict = load_checkpoint("./models/ckpt/mindspore_vision_application/train_resnet_cifar10-10_1562.ckpt")
# load the parameter into net
load_param_into_net(resnet, param_dict)
input = np.random.uniform(0.0, 1.0, size=[32, 3, 224, 224]).astype(np.float32)
export(resnet, Tensor(input), file_name='resnet_cifar10-10_1562.mindir', file_format='MINDIR')
不过这两个在线案例导出之后的 MindIR 格式,我还没来得及验证是否能正常使用。如果您知道快速验证的方法,请您分享与我,感谢大家多多指教!