写点什么

几个小实践带你快速上手 MindSpore

发布于: 2021 年 02 月 24 日

摘要:本文将带大家通过几个小实践快速上手 MindSpore,其中包括 MindSpore 端边云统一格式及华为智慧终端背后的黑科技。


MindSpore 介绍


MindSpore 是一种适用于端边云场景的新型开源深度学习训练/推理框架。 MindSpore 提供了友好的设计和高效的执行,旨在提升数据科学家和算法工程师的开发体验,并为 Ascend AI 处理器提供原生支持,以及软硬件协同优化。


同时,MindSpore 作为全球 AI 开源社区,致力于进一步开发和丰富 AI 软硬件应用生态。


image


接下来我将带大家通过几个小实践快速上手 MindSpore:


1.MindSpore 端边云统一格式— — MindIR


2.华为智慧终端背后的黑科技— —超轻量 AI 引擎 MindSpore Lite


一、MindSpore 端边云统一格式


— — MindIR


MindIR • 全称 MindSpore IR,是 MindSpore 的一种基于图表示的函数式 IR,定义了可扩展的图 结构以及算子的 IR 表示。它消除了不同后端的模型差异,一般用于跨硬件平台执行推理任务。


(1)MindSpore 通过统一 IR 定义了网络的逻辑结构和算子的属性,将 MindIR 格式的模型文件 与硬件平台解耦,实现一次训练多次部署。


(2)MindIR 作为 MindSpore 的统一模型文件,同时存储了网络结构和权重参数值。同时支持 部署到云端 Serving 和端侧 Lite 平台执行推理任务。


(3)同一个 MindIR 文件支持多种硬件形态的部署:


  • Serving 部署推理

  • 端侧 Lite 推理部署


1-1 导出 LeNet 网络的 MindIR 格式模型


于是我参照着大佬的简单的写了一个 py 解决了这题


1.定义网络


LeNet 网络不包括输入层的情况下,共有 7 层:2 个卷积层、2 个下采样层(池化层)、3 个全连接层。每层都包含不同数量的训练参数,如下图所示:


image


我们对全连接层以及卷积层采用Normal进行参数初始化。


MindSpore 支持TruncatedNormalNormalUniform等多种参数初始化方法,默认采用Normal。具体可以参考 MindSpore API 的mindspore.common.initializer模块说明。


使用 MindSpore 定义神经网络需要继承mindspore.nn.CellCell是所有神经网络(Conv2d等)的基类。


神经网络的各层需要预先在__init__方法中定义,然后通过定义construct方法来完成神经网络的前向构造。按照 LeNet 的网络结构,定义网络各层如下:


import mindspore.nn as nnfrom 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
复制代码


MindSpore 官网为我们提供了 LeNet 的 Checkpoint 文件,提供了不同版本的:https://download.mindspore.cn...


*Checkpoint • 采用了 Protocol Buffers 格式,存储了网络中所有的参数值。一般用于训练任务中断后恢复训练,或训练后的微调(Fine Tune)任务。


image


在这里我选择了 CPU,因为题目说可以不用训练,所以定义完网络我就直接使用了


2.模型转换


import timeimport mindspore.nn as nnfrom datetime import datetimefrom mindspore.common.initializer import Normal
lenet = LeNet5()`# 返回模型的参数字典param_dict = load_checkpoint("./lenet.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.mindir', file_format='MINDIR',)
t = datetime.now().strftime('%Y-%m-%d %H:%M:%S')print(" ")print("============== Model conversion succeeded ==============")print(t)
复制代码


image


1-2 训练一个 ResNet50 网络。使用训练好的 checkpoint 文件,导出 MindIR 格式模型


训练 ResNet50 网络生成 checkpoint


参照着官网的教程使用 MindSpore 训练了一个 ResNet50 网络图像分类模型,官网的教程里那个文档适用于 CPU、GPU 和 Ascend AI 处理器环境。使用 ResNet-50 网络实现图像分类:https://www.mindspore.cn/tuto...


(1)数据集的准备,这里使用的是 CIFAR-10 数据集。


(2)构建一个卷积神经网络,这里使用 ResNet-50 网络。


这里担心自己电脑跑不起来,使用了 ModelArts 平台提供的 Notebook 来跑 8vCPU+64G+1 x Tesla V100-PCIE-32G,不得不说性能很强


image


这里对训练好的 ResNet50 网络导出为 MindIR 格式


`import numpy as npfrom resnet import resnet50
from mindspore.train.serialization import export, load_checkpoint, load_param_into_netfrom mindspore import Tensor
resnet = resnet50(batch_size=32, num_classes=10)# return a parameter dict for modelparam_dict = load_checkpoint("./models/ckpt/mindspore_vision_application/train_resnet_cifar10-10_1562.ckpt")# load the parameter into netload_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_Jack20.mindir', file_format='MINDIR')`
复制代码


image


为了保存数据,我把它下载了下来,结果发现原训练好的 Checkpoint 文件文件过大超过了 100MB 不能直接下载,于是找到了另一种解决方法:


在 Notebook 中,新建一个“ipynb”文件,使用 MoXing 先将大文件从 Notebook 上传到 OBS 中,然后我再从我 OBS 桶了下载不就完了嘛


import moxing as moxmox.file.copy('./train_resnet_cifar10-10_1562.ckpt', 'obs://bucket_name/train_resnet_cifar10-10_1562.ckpt')
复制代码


注:其中"./train_resnet_cifar10-10_1562.ckpt”为文件在 Notebook 中的存储路径,"train_resnet_cifar10-10_1562.ckpt”为该文件上传到 OBS 的存储路径。


二、华为智慧终端背后的黑科技


— —超轻量 AI 引擎 MindSpore Lite


MindSpore Lite 1.1 在端侧模型训练、算子性能优化、模型小型化、加速库自动裁剪工具、语音类模型支持、Java 接口开放、模型可视化等方面进行了全面升级,升级后的版本更轻、更快、更易用


大家可以到官网下载对应的 MindSpore Lite: https://www.mindspore.cn/tuto...


image


一、设计目标


1.端云一体化


端云 IR 统一,云侧训练模型可直接支持端侧重训云侧混合精度训练与端侧推理协同提升推理性能


2.极致性能/轻量化


通过 NPU/CPU/GPU 异构并行最大化发挥硬件算力,高效内核算法+汇编指令优化缩短推理时延不依赖任何第三方库,底层算子库使用 C 语言+汇编开发。


3.快捷部署


支持第三方模型 TensorFlow Lite、Caffe、ONNX 离线转换,使用户可快速切换后端;提供量化工具、图片数据处理等功能方便用户的部署和使用;


4.全场景覆盖


覆盖手机、IoT 等各种智能设备;支持 ARM CPU、GPU、NPU 等多种硬件平台、支持 Android/iOS 操作系统;支持端侧推理及训练;


二、关键特性


1.性能优化


(1)算子融合:支持多达 20+常见的融合,减少内存读写和计算量


(2)算子替换:支持常见的算子替换,通过参数值替换减少计算量


(3)算子前移:移动 slice 相关算动到计算图前,减少冗余计算


2.算子优化


对于 CPU 硬件,影响算子指令执行速度的关键因素包括了 L1/L2 缓存的命中率以及指令的流水布,MindSpore 端侧 CPU 算子优化手段包括:


(1)数据的合理排布:MindSpore CPU 算子采用 NHWC 的数据排布格式,相比 NC4HW,channel 方向不需要补齐至 4,更省内存;相比 NCHW,卷积单元的点更加紧凑,对缓存更友好;此外,算子间也不再涉及 layout 转换。


(2)寄存器的合理分配:将寄存器按照用途,划分为 feature map 寄存器、权重寄存器和输出寄存器,寄存器的合理分配可以减少数据加载的次数。


(3)数据的预存取,通过 prefetch/preload 等指令,可以提前将数据读到 cache 中。


(4)指令重排,尽量减少指令的 pipeline stall。


(5)向量化计算,使用 SIMD 指令,如 ARM NEON 指令,X86 SSE/AVX 指令等


3.训练后量化


丰富的量化策略,精度接近无损


MindSpore Lite 训练后量化工具提供权重量化和全量化两种方法,支持 1~16bit 量化,支持分类,检测,NLP 等多种模型


4.Micro for IoT


移动终端上的推理框架,通过模型解释的方式来进行推理,这样的方式可以支持多个模型以及跨硬件平台,但是需要额外的运行时内存(MCU 中最昂贵的资源)来存储元信息(例如模型结构参数)。MindSpore for Micro 的 CodeGen 方式,将模型中的算子序列从运行时卸载到编译时,并且仅生成将模型执行的代码。它不仅避免了运行时解释的时间,而且还释放了内存使用量,以允许更大的模型运行。这样生成的二进制大小很轻,因此具有很高的存储效率。


5.异构自动并行


6.端云统一


MindSpore 在框架的设计上进行了分层设计,将端云共用的数据结构和模块解耦出来,在满足端侧轻量化的同时,保持了端云架构的一致性


image


(1)统一 IR:MindSpore core 的统一 lR,保证了端云模型/算子定义的一致性,使得云侧训练的模型可以无缝的部署在端侧。同时,对于端侧训练,可以和云侧使用一致的 R 进行模型的重训。


(2)公共 pass:为了提升性能,训练好的模型在执行推理前,需要提前做一些优化手段,这些优化包括了融合、常量折叠、数据排布的调整等等。对于端云共享的优化,同样也是包含在 MindSporecore 模块中,只不过对于云侧推理,这些优化是在线推理时去执行的,而对于移动终端这些优化在执行推理前离线完成。


(3)统一接口:MindSpore 设计了端云统一的 C++接口。统一的 C++接口的用法尽量与 Python 接口保持了一致,降低了学习成本。通过统一接口,用户可以使用一套代码在不同的硬件上进行推理。


7.端侧训练


(1)支持 30+反向算子,提供 SGD、ADAM 等常见优化器及 CrossEntropy/SparsCrossEntropy/MSE 等损失函数;既可从零训练模型,也可指定特定网络层微调,达到迁移学习目的;


(2)已支持 LeNet/AlexNet/ResNet/MobileNetV1/V2/V3 和 EffectiveNet 等网络训练,提供完整的模型加载,转换和训练脚本,方便用户使用和调测;


(3)MindSpore 云侧训练和端侧训练实现无缝对接,云侧模型可直接加载到端侧进行训练;


(4)支持 checkpoint 机制,训练过程异常中断后可快速恢复继续训练;


实践一下:


2-1 在 MindSpore model_zoo 下载模型 mobilenetv2.mindir( https://download.mindspore.cn...), 使用 MindSpore lite converter 转成.ms 模型,请保留所使用的模型转换命令和模型转换截图


1.按要求打开链接找到指定的模型文件下载下来备用


image


2.把文件放到 MindSpore lite converter 文件夹下


因为我这里是直接把文件夹放到了桌面,在 CMD 中进到这个文件环境目录里


cd c: UsersAdministratorDesktopMindSporePetClassificationconverter
复制代码


3.将.mindir 模型转换为.ms 模型


call converter_lite --fmk=MINDIR --modelFile=c:UsersAdministratorDesktopMindSporePetClassificationconvertermobilenetv2.mindir --outputFile=Jack20
复制代码


注意:其中 c:UsersAdministratorDesktopMindSporePetClassificationconvertermobilenetv2.mindir 代表生成的 mindir 文件,而--outputFile 定义转换后 MS 文件的名称。


成功后,会在 converter 文件夹中生成对应的.ms 文件。


image


三、一键部署在线推理服务


— —MindSpore Serving


image


MindSpore Serving 就是为实现将深度学习部署到生产环境而产生的


MindSpore Serving 是一个简单易用、高性能的服务模块,旨在帮助 MindSpore 开发者在生产环境中高效部署在线推理服务


注:MindSpore Serving 当前仅支持 Ascend 310 Ascend 910 环境。


大家可以在 MindSpore 官网下载对应版本安装包实践:https://www.mindspore.cn/vers...


特点


(1)简单易用


提供 Python 接口配置和启动 Serving 服务,对客户端提供 gRPC 和 RESTful 访问接口,提供 Python 客户端接口,通过它,大家可以轻松定制、发布、部署和访问模型服务。


安装:


pip install mindspore_serving-1.1.0-cp37-cp37m-linux_aarch64.whl
复制代码


1.轻量级部署


服务端调用 Python 接口直接启动推理进程(master 和 worker 共进程),客户端直接连接推理服务后下发推理任务。 执行 master_with_worker.py,完成轻量级部署服务:


import osfrom mindspore_serving import masterfrom mindspore_serving import worker
def start(): servable_dir = os.path.abspath(".") worker.start_servable_in_master(servable_dir, "add", device_id=0) master.start_grpc_server("127.0.0.1", 5500) if __name__ == "__main__": start()
复制代码


当服务端打印日志 Serving gRPC start success, listening on 0.0.0.0:5500 时,表示 Serving 服务已加载推理模型完毕。


2.集群部署


服务端由 master 进程和 worker 进程组成,master 用来管理集群内所有的 worker 节点,并进行推理任务的分发。


部署 master:


import osfrom mindspore_serving import master
def start(): servable_dir = os.path.abspath(".") master.start_grpc_server("127.0.0.1", 5500) master.start_master_server("127.0.0.1", 6500) if __name__ == "__main__": start()
复制代码


部署 worker:


import osfrom mindspore_serving import worker
def start(): servable_dir = os.path.abspath(".") worker.start_servable(servable_dir, "add", device_id=0, master_ip="127.0.0.1", master_port=6500, worker_ip="127.0.0.1", worker_port=6600)
if __name__ == "__main__": start()
复制代码


轻量级部署和集群部署启动 worker 所使用的接口存在差异,其中,轻量级部署使用 start_servable_in_master 接口启动 worker,集群部署使用 start_servable 接口启动 worker。


(2)提供定制化服务


支持模型供应商打包发布模型、预处理和后处理,围绕模型提供定制化服务,并一键部署,服务使用者不需要感知模型处理细节。


举个栗子:实现导出两个 tensor 相加操作的模型


import osfrom shutil import copyfileimport numpy as np
import mindspore.context as contextimport mindspore.nn as nnimport mindspore.ops as opsimport mindspore as ms
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")class Net(nn.Cell): """Define Net of add"""
def __init__(self): super(Net, self).__init__() self.add = ops.TensorAdd()
def construct(self, x_, y_): """construct add net""" return self.add(x_, y_)def export_net(): """Export add net of 2x2 + 2x2, and copy output model `tensor_add.mindir` to directory ../add/1""" x = np.ones([2, 2]).astype(np.float32) y = np.ones([2, 2]).astype(np.float32) add = Net() output = add(ms.Tensor(x), ms.Tensor(y)) ms.export(add, ms.Tensor(x), ms.Tensor(y), file_name='tensor_add', file_format='MINDIR') dst_dir = '../add/1' try: os.mkdir(dst_dir) except OSError: pass
dst_file = os.path.join(dst_dir, 'tensor_add.mindir') copyfile('tensor_add.mindir', dst_file) print("copy tensor_add.mindir to " + dst_dir + " success")
print(x) print(y) print(output.asnumpy())if __name__ == "__main__": export_net()
复制代码


构造一个只有 Add 算子的网络,并导出 MindSpore 推理部署模型,该模型的输入为两个 shape 为[2,2]的二维 Tensor,输出结果是两个输入 Tensor 之和。


(3)支持批处理


用户一次请求可发送数量不定样本,Serving 分割和组合一个或多个请求的样本以匹配模型的实际 batch,不仅仅加速了 Serving 请求处理能力,并且也简化了客户端的使用。


image


主要针对处理图片、文本等包含 batch 维度的模型。假设 batch_size=2,当前请求有 3 个实例,共 3 张图片,会拆分为 2 次模型推理,第 1 次处理 2 张图片返回 2 个结果,第 2 次对剩余的 1 张图片进行拷贝做一次推理并返回 1 个结果,最终返回 3 个结果。


对于一个模型,假设其中一个输入是数据输入,包括 batch 维度信息,另一个输入为模型配置信息,没有包括 batch 维度信息,此时在设置 with_batch_dim 为 True 基础上,设置额**数 without_batch_dim_inputs 指定没有包括 batch 维度信息的输入信息。


from mindspore_serving.worker import register# Input1 indicates the input shape information of the model, without the batch dimension information.# input0: [N,3,416,416], input1: [2]register.declare_servable(servable_file="yolov3_darknet53.mindir", model_format="MindIR",                          with_batch_dim=True, without_batch_dim_inputs=1)
复制代码


(4) 高性能高扩展


支持多模型多卡并发,通过 client/master/worker 的服务体系架构,实现 MindSpore Serving 的高性能和高扩展性。


image


华为 Ascend 主打芯片低功耗、高算力等特性,MindSpore 提供高效的内核算法、自动融合,自动并行等能力。支持多模型多卡并发,通过 client/master/worker 的服务体系架构,实现 MindSpore Serving 的高性能和高扩展性。


高可靠性设计(某个服务节点宕机,不影响客户端正常服务),负载均衡(如何更合理的使用所有资源信息),弹性扩容缩容(根据业务的高峰低谷,动态调整资源)


四、AI 数据高速加载直通车


— —单节点数据缓存


Cache 单节点缓存模块可用于缓存预处理后的训练数据,加速数据加载,提升数据复用率,降低数据预处理所需的 CPU 算力


对于需要重复访问远程的数据集或需要重复从磁盘中读取数据集的情况,可以使用单节点缓存算子将数据集缓存于本地内存中,以加速数据集的读取。 缓存算子依赖于在当前节点启动的缓存服务器,缓存服务器作为守护进程独立于用户的训练脚本而存在,主要用于提供缓存数据的管理,支持包括存储、查找、读取以及发生缓存未命中时对于缓存数据的写入等操作。


image


对比使用数据缓存和不使用数据缓存的数据加载流程 pipeline,第一个,是不使用数据缓存服务的常规数据处理流程


1.缓存加载后的原始数据,用户可以在数据集加载算子中使用缓存。这将把加载完成的数据存到缓存服务器中,后续若需相同数据则可直接从中读取,避免从磁盘中重复加载。


2.缓存经过数据增强操作后的数据,用户也可在 Map 算子中使用缓存。这将允许我们直接缓存数据增强(如图像裁剪、缩放等)处理后的数据,避免数据增强操作重复进行,减少了不必要的计算量。


  1. 以上两种类型的缓存本质上都是为了提高数据复用,以减少数据处理过程耗时,提高网络训练性能。


Cache 的三个重要组件


(1)缓存算子


image


1.对于 mappable 的数据集(如 ImageFolder)的 pipeline,Cache 将创建名为 CacheLookupOp 和 CacheMergeOp 的两个缓存算子,并对 pipeline 做出相应的调整。


2.见于上图 Mappable 数据集图示,左边的数据处理 pipeline,当用户在 MapOp 后插入缓存算子后,经过 Cache 变换调整过程,将对 pipeline 进行变换并最终将其调整为右图中包含 CacheLookupOp 和 CacheMergeOp 两个缓存算子的结构


3.对于包含 non-mappable 的数据集(如 TFRecord)的 pipeline,我们将创建名为 CacheOp 的缓存算子,并在 pipeline 相应位置插入 CacheOp。见于上图 Non-mappable 数据集图示,左边的数据处理 pipeline,当用户在 MapOp 后插入缓存算子后,经过 Cache 变换调整过程,将对 pipeline 进行变换并最终将其调整为右图中包含 CacheOp 缓存算子的结构。


(2)缓存服务器


image


主要负责响应缓存客户端所发送的请求,提供缓存数据的查找、读取,以及发生缓存未命中时对于缓存数据的写入等功能。缓存服务器拥有自己的工作队列,不断循环从工作队列中获取一个请求去执行并将结果返回给客户端。同一个缓存服务器可以为多个缓存客户端提供服务,且缓存服务器通过缓存客户端的 session_id 以及该缓存客户端所对应的数据处理 pipeline 的 crc 码来唯一确定该缓存客户端。因此,两个完全一致的 pipeline 可以通过指定相同的 session_id 来共享同一个缓存服务,而不同的 pipeline 若试图共享同一个缓存客户端则会报错。


1.Cache_server 如何启动?


Cache Server 的服务由一个外部守护进程提供,在用户使用 Cache 服务之前,需要先在 mindspore 外部启动一个服务器守护进程,来与缓存客户进行交互沟通;


ms_cache_server start|session [–m <mem_size>] [-d <spill_path>] [-nospill] [-h <host>] [-p <port>]
#Command: start | session#start#– starts the service#session#– creates a new caching session, returning the session_id as output
复制代码


然后启动


cache_admin --start
复制代码


image


2.cache_server 创建时默认的 port 端口号是多少?


默认对 IP 为 127.0.0.1(localhost)且端口号为 50052 的服务器执行操作


(3)缓存客户端


主要负责与缓存服务器建立通讯,向缓存服务器发起数据读取、数据写入、状态查询等请求。缓存客户端与服务器之间通过 gRPC 进行通讯,如下图所示:当客户端需要发起请求时,仅需要将请求添加到 gRPC 函数库所提供的 gRPC 队列,由 gRPC 线程不断循环从 gRPC 队列中获取一个请求并将该请求发送到缓存服务器的工作队列中。当缓存服务器需要将处理后的响应数据返回给客户端时,也通过类似的方式将响应数据添加到 gRPC 队列中,并依赖 gRPC 实际将数据传输至客户端。


3.cache_client 实体在创建时,其<session_id>如何获取?


唯一标识与缓存服务的连接 session。应该从 ms_cache_service session 命令返回的 session_id。当给出该选项时,缓存的大小和溢出行为取自 session。如果未给出值,则假设这是唯一的通道,没有其他通道将共享此缓存。在这种情况下,将自动生成一个 session_id。


ms_cache_server start|session [–m <mem_size>] [-d <spill_path>] [-nospill] [-h <host>] [-p <port>]
#Command: start | session#– creates a new caching session, returning the session_id as output
复制代码


image


其中 3231564523 为端口 50052 的服务器分配的缓存会话 id,缓存会话 id 由服务器分配。

若缓存服务器中不存在缓存会话,则需要创建一个缓存会话,得到缓存会话 id:


五、快速定位模型精度问题


--MindSpore 调试器


在图模式下,用户难以从 Python 层获取到计算图中间节点的结果。MindSpore 调试器是为图模式训练提供的调试工具,可以用来查看并分析计算图节点的中间结果。


使用 MindSpore 调试器,可以:


(1)在 MindInsight 调试器界面结合计算图,查看图节点的输出结果;


(2)设置监测点,监测训练异常情况(比如检查张量溢出),在异常发生时追踪错误原因;


(3)查看权重等参数的变化情况。


image


一、常见精度问题和定位思路


(1)常见现象


  1. loss:跑飞,不收敛,收敛慢

  2. metrics:accuracy、precision 等达不到预期

  3. 梯度:梯度消失、梯度爆炸

  4. 权重:权重不更新、权重变化过小、权重变化过大

  5. 激活值:激活值饱和、dead relu


(2)常见问题


  1. 模型结构问题:算子使用错误、权重共享错误、权重冻结错误、节点连接错误、 loss 函数错误、优化器错误等

  2. 超参问题:超参设置不合理等

  3. 数据问题:缺失值过多、异常值、未归一化等


(3)常用定位思路


image


(1 定位准备


1. 回顾算法设计,全面熟悉模型


•算法设计、超参、loss、优化器、数据处理等


•参考论文、其它实现


2. 熟悉可视化工具


•安装 MindInsight https://www.mindspore.com/ins...


•加入 SummaryCollector callback,收集训练信息


•在 summary_dir 的父目录中启动 MindInsight


•mindinsight start


•熟悉调试器使用


3. 熟悉调试器


•MindSpore 调试器是为图模式训练提供的调试工具


•在 MindInsight 调试器界面结合计算图,查看图节点的输出结果;


•设置监测点,监测训练异常情况(比如检查张量溢出),在异常发生时追踪错误原因;


•查看权重等参数的变化情况。


使用指南请见 https://www.mindspore.cn/tuto...


•debugger 使用指南请见https://www.mindspore.cn/tuto...


(2 检查代码、超参、模型结构


  1. 走读脚本,检查代码


•小黄鸭调试法


•检查代码同模型设计、论文、参考脚本等是否一致


  1. 超参常见问题:


•学习率不合理


•权重初始化参数不合理等


  1. MindInsight 辅助检查:训练列表->训练参数详情

  2. 模型结构常见问题:


•算子使用错误(使用的算子不适用于目标场景,如应该使用浮点除,错误地使用了整数除),


•权重共享错误(共享了不应共享的权重),


•权重冻结错误(冻结了不应冻结的权重),


•节点连接错误(应该连接到计算图中的 block 未连接),


•loss 函数错误,


•优化器算法错误(如果自行实现了优化器)等。


  1. MindInsight 辅助检查:训练列表->训练看板->计算图


(3 检查输入数据


  1. 输入数据常见问题:


•数据缺失值过多


•每个类别中的样本数目不均衡


•数据中存在异常值


•数据标签错误


•训练样本不足


•未对数据进行标准化,输入模型的数据不在正确的范围内


•finetune 和 pretrain 的数据处理方式不同


•训练阶段和推理阶段的数据处理方式不同


•数据处理参数不正确等。


  1. MindInsight 辅助检查:训练列表->训练看板->数据抽样


(4 检查 loss 曲线


  1. 常见现象


•loss 跑飞


回顾脚本、模型结构和数据,


•检查超参是否有不合理的特别大/特别小的取值,


•检查模型结构是否实现正确,特别是检查 loss 函数是否实现正确,


•检查输入数据中是否有缺失值、是否有特别大/特别小的取值。


使用参数分布图检查参数更新是否有剧烈变化


使用调试器功能对训练现场进行检查


•配置“检查张量溢出”监测点,定位 NAN/INF 出现位置


•配置“检查过大张量”监测点,定位出现大值的算子


•配置“检查权重变化过大”、“检查梯度消失”、“检查梯度过大”监测点,定位异常的权重或梯度


image


•loss 收敛慢


  1. MindInsight 辅助检查:训练列表->训练看板->标量曲线/参数分布图


image


  1. 调试器定位


(5 检查精度是否达到预期


  1. 回顾代码、模型结构、输入数据和 loss 曲线,


•检查超参是否有不合理的值


•检查模型结构是否实现正确


•检查输入数据是否正确


•检查 loss 曲线的收敛结果和收敛趋势是否存在异常


  1. 尝试使用“溯源分析”和调参器优化超参


•mindoptimizer --config ./config.yaml --iter 10


  1. 尝试模型解释

  2. 尝试优化模型算法


image


注意事项


1. 场景支持


•调试器暂不支持分布式训练场景。


•调试器暂不支持推断场景。


•调试器暂不支持单机多卡/集群场景。


•调试器暂不支持连接多个训练进程。


•调试器暂不支持 CPU 场景。


2. 性能影响


•使用调试器时,会对训练性能产生一定影响。


•设置的监测点数目过多时,可能会出现系统内存不足(Out-of-Memory)的异常。


3. GPU 场景


•在 GPU 场景下,只有满足条件的参数节点可以与自身的上一轮次结果作对比:使用下一个节点执行过的节点、使用运行到该节点时选中的节点、作为监测点输入的参数节点。其他情况均无法使用上一轮次对比功能。


•由于 GPU 上一个轮次是一个子图(而非完整的图),GPU 上多图做重新检查时,只能重新检查当前的子图。


4. 重新检查只检查当前有张量值的监测点。


5. 检查计算过程溢出需要用户开启异步 Dump 的全部溢出检测功能,开启方式请参照异步 Dump 功能介绍


6. 调试器展示的图是优化后的最终执行图。调用的算子可能已经与其它算子融合,或者在优化后改变了名称。


参考


[1]www.mindspore.cn


[2]gitee.com/mindspore


[3]github.com/mindspore-ai


本文分享自华为云社区《几个小实践带你两天快速上手 MindSpore 》,原文作者:Jack20 。


点击关注,第一时间了解华为云新鲜技术~


发布于: 2021 年 02 月 24 日阅读数: 70
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
几个小实践带你快速上手MindSpore