基于MindSpore Lite的模型转换
迁移推理业务的整体流程如下:
主要通过MindSpore Lite(简称MSLite)进行模型的转换,进一步通过MindSpore Runtime支持昇腾后端的能力来将推理业务运行到昇腾设备上。
模型准备
MindSpore Lite提供的模型convertor工具可以支持主流的模型格式到MindIR的格式转换,用户需要导出对应的模型文件,推荐导出为ONNX格式。
- 如何导出ONNX模型
- 如何导出PTH模型
PyTorch模型导出时需要包含模型的结构信息,需要利用jit.trace方式完成模型的导出与保存。
# If you are instantiating the model with *from_pretrained* you can also easily set the TorchScript flag model = BertModel.from_pretrained("bert-base-uncased", torchscript=True) # Creating the trace traced_model = torch.jit.trace(model, [tokens_tensor, segments_tensors]) torch.jit.save(traced_model, "traced_bert.pt")
转换关键参数准备
对应的模型转换成MindIR格式,通过后端绑定的编译形式来运行以达到更好的性能(类似静态图的运行模式),所以需要提前准备以下几个重点参数。
- 输入的inputShape,包含batch信息。
MSLite涉及到编译优化的过程,不支持完全动态的权重模式,需要在转换时确定对应的inputShape,用于模型的格式的编译与转换,可以在netron官网进行查看,或者对于模型结构中的输入进行shape的打印,并明确输入的batch。
一般来说,推理时指定的inputShape是和用户的业务及推理场景是紧密相关的,可以通过原始模型推理脚本或者网络模型进行判断。需要把Notebook中的模型下载到本地后,再放入netron官网中,查看其inputShape。
如果netron中没有显示inputShape,可能由于使用了动态shape模型导致,请确保使用的是静态shape模型,静态shape模型文件导出方法请参考模型准备。
图1 netron中查看inputShape
- 精度选择。
精度选择需要在模型转换阶段进行配置,执行converter_lite命令时通过--configFile参数指定配置文件路径,配置文件通过precision_mode参数指定精度模式。可选的参数有“enforce_fp32”,“preferred_fp32”,“enforce_fp16”,“enforce_origin”或者“preferred_optimal”,默认为“enforce_fp16”。
[ascend_context] precision_mode= preferred_fp32
模型转换
在ModelArts开发环境中,通过对应的转换预置镜像,直接执行对应的转换过程,对应的转换和评估工具都已经预置了最新版本,详细介绍请见使用说明。inputShape查看方法请见转换关键参数准备。
!converter_lite --modelFile=resnet50.onnx --fmk=ONNX --outputFile=resnet50 --saveType=MINDIR --inputShape="input.1:1,3,224,224" --device=Ascend
为了简化用户使用,ModelArts提供了Tailor工具便于用户进行模型转换,具体使用方式参考Tailor指导文档。
推理应用适配
MindSpore Lite提供了JAVA/C++/Python API,进行推理业务的适配,并且在构建模型时,通过上下文的参数来确定运行时的具体配置,例如运行后端的配置等。下文以Python接口为例。
使用MindSpore Lite推理框架执行推理并使用昇腾后端主要包括以下步骤:
- 创建运行上下文:创建Context,保存需要的一些基本配置参数,用于指导模型编译和模型执行,在昇腾迁移时需要特别指定target为“Ascend”,以及对应的device_id。
context = mslite.Context() context.target = ["ascend"] context.ascend.device_id = 0
- 模型加载与编译:执行推理之前,需要调用Model的build_from_file接口进行模型加载和模型编译。模型加载阶段将文件缓存解析成运行时的模型。模型编译阶段会耗费较多时间所以建议Model创建一次,编译一次,多次推理。
model = mslite.Model() model.build_from_file("./resnet50.mindir", mslite.ModelType.MINDIR, context)
- 输入数据:编译后的模型提供了predict接口用户执行模型推理任务,Inputs输入为List Tensor,这里的Tensor是MSLite的概念,具体的列表长度和tensor类型由转换时的InputShape来确定,由于后端指定了ascend,这些tensor都是在昇腾设备的显存中,用户需要在对应的tensor中填入数据,这些数据也会被搬移到显存中,进一步对于Inputs输入的内容进行处理。
data = convert_img(input_image) in_data = [np.array(data)] inputs = model.get_inputs() for i, _input in enumerate(inputs): _input.set_data_from_numpy(in_data[i])
- 执行推理:使用Model的predict进行模型推理,返回值为Outputs,也是List Tensor类型,具体的长度和类别由模型定义,对应的Tensor数据由于指定了ascend后端,Output的内容在显存中,通过tensor的get_data_to_numpy方法来获取,并将数据读取到内存中使用。
outputs = model.predict(inputs) outputs = [output.get_data_to_numpy() for output in outputs]
更多Python接口的高级用法与示例,请参考Python API。