几个小实践带你两天快速上手MindSpore(下)
上一篇讲到的:>>点我查看 几个小实践带你两天快速上手MindSpore(上)
1.MindSpore端边云统一格式— — MindIR
2.华为智慧终端背后的黑科技— —超轻量AI引擎MindSpore Lite
今天将为继续大家带来:
1.一键部署在线推理服务— —MindSpore Serving
2.AI数据高速加载直通车— —单节点数据缓存
3.快速定位模型精度问题— —MindSpore调试器
一、一键部署在线推理服务
— —MindSpore Serving
MindSpore Serving就是为实现将深度学习部署到生产环境而产生的
MindSpore Serving是一个简单易用、高性能的服务模块,旨在帮助MindSpore开发者在生产环境中高效部署在线推理服务
注:MindSpore Serving当前仅支持Ascend 310和Ascend 910环境。
大家可以在MindSpore官网下载对应版本安装包实践:https://www.mindspore.cn/versions
特点
(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 os
from mindspore_serving import master
from 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 os
from 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 os
from 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 os
from shutil import copyfile
import numpy as np
import mindspore.context as context
import mindspore.nn as nn
import mindspore.ops as ops
import 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请求处理能力,并且也简化了客户端的使用。
主要针对处理图片、文本等包含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的高性能和高扩展性。
华为Ascend主打芯片低功耗、高算力等特性,MindSpore提供高效的内核算法、自动融合,自动并行等能力。支持多模型多卡并发,通过client/master/worker的服务体系架构,实现MindSpore Serving的高性能和高扩展性。
高可靠性设计(某个服务节点宕机,不影响客户端正常服务),负载均衡(如何更合理的使用所有资源信息),弹性扩容缩容(根据业务的高峰低谷,动态调整资源)
二、AI数据高速加载直通车
— —单节点数据缓存
Cache单节点缓存模块可用于缓存预处理后的训练数据,加速数据加载,提升数据复用率,降低数据预处理所需的CPU算力
对于需要重复访问远程的数据集或需要重复从磁盘中读取数据集的情况,可以使用单节点缓存算子将数据集缓存于本地内存中,以加速数据集的读取。 缓存算子依赖于在当前节点启动的缓存服务器,缓存服务器作为守护进程独立于用户的训练脚本而存在,主要用于提供缓存数据的管理,支持包括存储、查找、读取以及发生缓存未命中时对于缓存数据的写入等操作。
对比使用数据缓存和不使用数据缓存的数据加载流程pipeline,第一个,是不使用数据缓存服务的常规数据处理流程
1.缓存加载后的原始数据,用户可以在数据集加载算子中使用缓存。这将把加载完成的数据存到缓存服务器中,后续若需相同数据则可直接从中读取,避免从磁盘中重复加载。
2.缓存经过数据增强操作后的数据,用户也可在Map算子中使用缓存。这将允许我们直接缓存数据增强(如图像裁剪、缩放等)处理后的数据,避免数据增强操作重复进行,减少了不必要的计算量。
3. 以上两种类型的缓存本质上都是为了提高数据复用,以减少数据处理过程耗时,提高网络训练性能。
Cache的三个重要组件
(1)缓存算子
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)缓存服务器
主要负责响应缓存客户端所发送的请求,提供缓存数据的查找、读取,以及发生缓存未命中时对于缓存数据的写入等功能。缓存服务器拥有自己的工作队列,不断循环从工作队列中获取一个请求去执行并将结果返回给客户端。同一个缓存服务器可以为多个缓存客户端提供服务,且缓存服务器通过缓存客户端的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
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
若缓存服务器中不存在缓存会话,则需要创建一个缓存会话,得到缓存会话id:
其中3231564523为端口50052的服务器分配的缓存会话id,缓存会话id由服务器分配。
三、快速定位模型精度问题
--MindSpore调试器
在图模式下,用户难以从Python层获取到计算图中间节点的结果。MindSpore调试器是为图模式训练提供的调试工具,可以用来查看并分析计算图节点的中间结果。
使用MindSpore调试器,可以:
(1)在MindInsight调试器界面结合计算图,查看图节点的输出结果;
(2)设置监测点,监测训练异常情况(比如检查张量溢出),在异常发生时追踪错误原因;
(3)查看权重等参数的变化情况。
一、常见精度问题和定位思路
(1)常见现象
-
loss:跑飞,不收敛,收敛慢
-
metrics:accuracy、precision等达不到预期
-
梯度:梯度消失、梯度爆炸
-
权重:权重不更新、权重变化过小、权重变化过大
-
激活值:激活值饱和、dead relu
(2)常见问题
-
模型结构问题:算子使用错误、权重共享错误、权重冻结错误、节点连接错误、 loss函数错误、优化器错误等
-
超参问题:超参设置不合理等
-
数据问题:缺失值过多、异常值、未归一化等
(3)常用定位思路
(1定位准备
-
回顾算法设计,全面熟悉模型
•算法设计、超参、loss、优化器、数据处理等
•参考论文、其它实现
-
熟悉可视化工具
•安装MindInsight https://www.mindspore.com/install
•加入SummaryCollector callback,收集训练信息
•在summary_dir的父目录中启动MindInsight
•mindinsight start
•熟悉调试器使用
-
熟悉调试器
•MindSpore调试器是为图模式训练提供的调试工具
•在MindInsight调试器界面结合计算图,查看图节点的输出结果;
•设置监测点,监测训练异常情况(比如检查张量溢出),在异常发生时追踪错误原因;
•查看权重等参数的变化情况。
使用指南请见 https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/summary_record.html
•debugger使用指南请见https://www.mindspore.cn/tutorial/training/zh-CN/r1.1/advanced_use/debugger.html
(2检查代码、超参、模型结构
-
走读脚本,检查代码
•小黄鸭调试法
•检查代码同模型设计、论文、参考脚本等是否一致
-
超参常见问题:
•学习率不合理
•权重初始化参数不合理等
-
MindInsight辅助检查:训练列表->训练参数详情
-
模型结构常见问题:
•算子使用错误(使用的算子不适用于目标场景,如应该使用浮点除,错误地使用了整数除),
•权重共享错误(共享了不应共享的权重),
•权重冻结错误(冻结了不应冻结的权重),
•节点连接错误(应该连接到计算图中的block未连接),
•loss函数错误,
•优化器算法错误(如果自行实现了优化器)等。
-
MindInsight辅助检查:训练列表->训练看板->计算图
(3检查输入数据
-
输入数据常见问题:
•数据缺失值过多 •每个类别中的样本数目不均衡 •数据中存在异常值 •数据标签错误
•训练样本不足 •未对数据进行标准化,输入模型的数据不在正确的范围内 •finetune和pretrain的数据处理方式不同
•训练阶段和推理阶段的数据处理方式不同 •数据处理参数不正确等。
-
MindInsight辅助检查:训练列表->训练看板->数据抽样
(4检查loss曲线
-
常见现象
•loss跑飞
回顾脚本、模型结构和数据,
•检查超参是否有不合理的特别大/特别小的取值,
•检查模型结构是否实现正确,特别是检查loss函数是否实现正确,
•检查输入数据中是否有缺失值、是否有特别大/特别小的取值。
使用参数分布图检查参数更新是否有剧烈变化
使用调试器功能对训练现场进行检查
•配置“检查张量溢出”监测点,定位NAN/INF出现位置
•配置“检查过大张量”监测点,定位出现大值的算子
•配置“检查权重变化过大”、“检查梯度消失”、“检查梯度过大”监测点,定位异常的权重或梯度
•loss收敛慢
-
MindInsight辅助检查:训练列表->训练看板->标量曲线/参数分布图
-
调试器定位
(5检查精度是否达到预期
-
回顾代码、模型结构、输入数据和loss曲线,
•检查超参是否有不合理的值
•检查模型结构是否实现正确
•检查输入数据是否正确
•检查loss曲线的收敛结果和收敛趋势是否存在异常
-
尝试使用“溯源分析”和调参器优化超参
•mindoptimizer --config ./config.yaml --iter 10
-
尝试模型解释
-
尝试优化模型算法
注意事项
-
场景支持
•调试器暂不支持分布式训练场景。
•调试器暂不支持推断场景。
•调试器暂不支持单机多卡/集群场景。
•调试器暂不支持连接多个训练进程。
•调试器暂不支持CPU场景。
-
性能影响
•使用调试器时,会对训练性能产生一定影响。
•设置的监测点数目过多时,可能会出现系统内存不足(Out-of-Memory)的异常。
-
GPU场景
•在GPU场景下,只有满足条件的参数节点可以与自身的上一轮次结果作对比:使用下一个节点执行过的节点、使用运行到该节点时选中的节点、作为监测点输入的参数节点。其他情况均无法使用上一轮次对比功能。
•由于GPU上一个轮次是一个子图(而非完整的图),GPU上多图做重新检查时,只能重新检查当前的子图。
-
重新检查只检查当前有张量值的监测点。
-
检查计算过程溢出需要用户开启异步Dump的全部溢出检测功能,开启方式请参照异步Dump功能介绍
-
调试器展示的图是优化后的最终执行图。调用的算子可能已经与其它算子融合,或者在优化后改变了名称。
参考
- 点赞
- 收藏
- 关注作者
评论(0)