跑开发板案例太简单?跑个昇腾 CANN 全流程!
开发板到手,当天就将 SD 卡插上进入并狠狠地体验了一把内置的 CANN 案例。但是对着现成的案例沾沾自喜有什么用!我现在就要体验昇腾模型推理全流程!
经过 CANN 训练营的学习,可以肯定的一点是昇腾的推理流程十分易于上手,即便是我这种鲲鹏昇腾小白也可以轻松掌握。
整个流程将分为以下几章节:

另,为开发板插网线时可首先尝试插入下面的端口,因为开启了 DHCP。 
模型选择 - MAN 模型
我从研究记录中选择了 MAN 超分辨率模型进行体验。MAN 是一个较轻量的超分辨率模型,精度较好且性能开销少。代码开源较精简,有预训练模型。


我们这次将专注于 MAN-light 模型。我们将代码仓库克隆并下载预训练模型,即可进行下一步。
将 SR 模型转换为中间格式 (MindIR, ONNX)
MAN 模型是基于 PyTorch 框架的模型,所以我们将转换为 ONNX 中间件格式。
载入 PyTorch 模型网络代码
MAN 的模型类型是通过调整网络的参数来实现切换的,参数说明在 options 文件中有定义。
*# ./options/*test_MAN.yml
# network structures
network_g:
- type: MAN*
- scale: 2 #or 3/4*
- n_resblocks: 36 # 5 for MAN-tiny; 24 for MAN-light; 36 for MAN *
- n_resgroups: 1*
- n_feats: 180 # 48 for MAN-tiny; 60 for MAN-light; 180 for MAN *
导入相关程序库并输入我们要的参数,将仓库内的 MAN_arch.py 单独使用生成模型网络,并转换为推理模式。(内部注释掉 BasicSR 库的 Arch 代码)

使用 Python 载入模型
Python 会打印出模型网络:
MAN(
- (sub_mean): MeanShift(3, 3, kernel_size=(1, 1), stride=(1, 1))*
- (head): Conv2d(3, 60, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))*
- (body): ModuleList(*
……
小贴士:由于不是训练,用于生成数据集以及优化器不需要生成,只关注模型网络,简化代码。
在 GitHub 仓库下载预训练模型,在这使用 PyTorch 的方法 load_state_dict 载入权重。
model.load_state_dict(torch.load("MAN-Light-x2.pth"), strict=True)
打印模型权重的载入情况。
Model's state_dict:
sub_mean.weight ** ** torch.Size([3, 3, 1, 1])
sub_mean.bias ** ** torch.Size([3])
……
生成一个测试张量,这个张量需要和之前训练模型的张量结构相等,你可以通过调试来获取以前的张量结构,一般是 NCHW 格式。MAN 超分辨率模型只对 H, W 参数不敏感。
testTensor = torch.tensor([[[[1.]],[[1.]],[[1.]]]])
# 或者使用 touch.ones 函数,两个相等
testTensor = torch.ones((1, 3, 1, 1), dtype=torch.float32)
小贴士:这里需要注意,张量数据类型 (dtype) 要与模型中偏置 (bias) 的数据类型一致。
使用一行代码将构建好的 PyTorch 模型导出至 ONNX,注意这里要使用 dynamic_axes 使输入图片大小任意。
导出完成,可以使用 Netron 可视化模型,真炫酷。


模型输入节点的名字不一定是 image_in ,可以任意设置。
至此我们就已经转换为了 ONNX 格式,让我们来到转换为昇腾模型的准备阶段。
将中间格式模型转换为昇腾 OM 模型
准备阶段
开始查阅昇腾文档所需的资料。首先我们需要将动态输入在转换为 OM 模型时实现。
设置输入图片的动态分辨率:适用于执行推理时,每次处理图片宽和高不固定的场景。
将解析的shape中的H和W设置为-1,会在shape下方出现Dynamic Image Size参数。在其中的编辑框中输入具体的动态分辨率参数,最少输入两组,每一组参数通过英文分号分隔,组内参数使用英文逗号分隔。最多支持100档配置,例如输入112,112;224,224。
来自 昇腾文档
为了加快模型转换速度,我们后续也会对图片做补边预处理,使一些长宽稍微偏离输入尺寸的图片也能正确进行推理。
我们也需要实现 MAN 模型在训练时的预处理方法。MAN 模型是用 BasicSR 库进行训练的,这是一个通用的超分辨率训练库,图片的预处理会定义在 util 文件夹内,可以从数据的加载方法中看到数据处理方法。
*# From *paired_image_dataset.py
# Load gt and lq images. Dimension order: HWC; channel order: BGR;
# image range: [0, 1], float32.
# BGR to RGB, HWC to CHW, numpy to tensor
看到了颜色通道排列方法是 R, G, B,而最终的张量排布是 NCHW,颜色需要均一化 (0~1),数据精度为32位浮点数,以上就是预处理方式。
还记得开头提到的 CANN 示例吗?里面有我们可以复用的轮子—— ACL 推理流程代码。所以我们只需要在示例的基础上修改部分操作,即可成功运行。
python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/acl_net.py · Ascend/samples - 码云 - 开源中国 (gitee.com)
上述的是 ResNet-50 分类网络模型,里面有完整的 AscendCL 流程。我们将修改:
对于昇腾设备来说它们要做的流程并没有变,只是我们需要使用 PIL 进行 CPU 方式的图片补边,推理后再裁边。
转换流程
因为内存需求,我们将直接使用非昇腾设备 Ubuntu 系统完成转换。转换之前需要安装 CANN 环境。
安装步骤(Ubuntu 18.04)-安装依赖-安装开发环境-软件安装 (命令行)-环境准备-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
首先使用命令迁移,命令按照官方文档来使用
一行命令中的参数:
- 模型路径
- 模型类型(ONNX)
- 输入尺寸(-1为预设动态分辨率)
- 预设动态分辨率
- 输出路径
- 目标芯片

设置的预设越多,读条越久。但等到成功的那一刻还是很开心的。

我们现在已经有了昇腾 OM 模型,可以用于推理了。简化流程,我们下面使用静态分辨率模型。
使用 AscendCL 进行推理
改写示例
启动 A2 开发板,启动 Jupyter Lab 样例,找到“03-resnet”示例,打开即可看到代码。

但很多代码是可以复用的,我们只需修改以下部分:
图片预处理:
打印推理结果:
主函数:
以及适配预设的动态分辨率。
修改完毕,点击开始运行,我们使用 Set5 数据集进行测试。

可以看到成功推理出大图片~
小贴士:如果对 AscendCL 代码全流程较难理解,可转而使用示例 “Unet++”,这个示例将 ACL 封装起来成 acllite_util ,大大简化步骤,更易上手。
(两行代码即可)
总结
简要说明流程:
从研究记录中选择一个模型作为实验(首选 SR 超分辨率模型)
- MAN 轻量
- 有预训练模型
- 开源
将 SR 模型转换为中间格式 (MindIR, ONNX)
- PyTorch 转换为 ONNX
- ONNX 要打开动态输入
将中间格式模型转换为昇腾 OM 模型
- OM 模型需要预设动态分辨率
- 动态分辨率越多转换越久
使用 AscendCL 进行推理
- 改写了昇腾原有示例
整个自身的体验流程就告一段落了。其中最有意思的肯定是平台的推理通过 ATC 将模型网络编译,大大缩短推理时间,算力开销大幅降低,才发现在模型边缘计算推理场景中性能需求可以压缩的如此低。将模型转换为昇腾 OM 模型所用的时间能接受,搭配上开发板的 GPIO 接口则有机会作为物联网的中枢。我自身也打算使用昇腾设备对开发模型进行推理测试,充分验证网络的实际应用性能;以及将昇腾开发板带到户外去,使用真实场景进行推理,所以求求官方赶快出一个外壳吧,把 PCB 螺丝孔设计图公开一下也可以啊(笑)。
感谢大家的观看,未来还会带来其他的进阶操作流程!

链接
安装须知-软件安装 (命令行)-环境准备-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
学习向导-ATC模型转换-推理应用开发-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
导出ONNX模型-保存与导出模型-PyTorch 网络模型迁移和训练-模型开发(PyTorch)-6.3.RC1-CANN商用版-文档首页-昇腾社区 (hiascend.com)
samples: CANN Samples (gitee.com)
跑开发板案例太简单?跑个昇腾 CANN 全流程!
开发板到手,当天就将 SD 卡插上进入并狠狠地体验了一把内置的 CANN 案例。但是对着现成的案例沾沾自喜有什么用!我现在就要体验昇腾模型推理全流程!
经过 CANN 训练营的学习,可以肯定的一点是昇腾的推理流程十分易于上手,即便是我这种鲲鹏昇腾小白也可以轻松掌握。
整个流程将分为以下几章节:

另,为开发板插网线时可首先尝试插入下面的端口,因为开启了 DHCP。
模型选择 - MAN 模型
我从研究记录中选择了 MAN 超分辨率模型进行体验。MAN 是一个较轻量的超分辨率模型,精度较好且性能开销少。代码开源较精简,有预训练模型。
我们这次将专注于 MAN-light 模型。我们将代码仓库克隆并下载预训练模型,即可进行下一步。
将 SR 模型转换为中间格式 (MindIR, ONNX)
MAN 模型是基于 PyTorch 框架的模型,所以我们将转换为 ONNX 中间件格式。
载入 PyTorch 模型网络代码
MAN 的模型类型是通过调整网络的参数来实现切换的,参数说明在 options 文件中有定义。
导入相关程序库并输入我们要的参数,将仓库内的 MAN_arch.py 单独使用生成模型网络,并转换为推理模式。(内部注释掉 BasicSR 库的 Arch 代码)
使用 Python 载入模型
Python 会打印出模型网络:
在 GitHub 仓库下载预训练模型,在这使用 PyTorch 的方法 load_state_dict 载入权重。
model.load_state_dict(torch.load("MAN-Light-x2.pth"), strict=True)打印模型权重的载入情况。
for param_tensor in model.state_dict():` print(param_tensor, "\t", model.state_dict()[param_tensor].size())生成一个测试张量,这个张量需要和之前训练模型的张量结构相等,你可以通过调试来获取以前的张量结构,一般是 NCHW 格式。MAN 超分辨率模型只对 H, W 参数不敏感。
testTensor = torch.tensor([[[[1.]],[[1.]],[[1.]]]])# 或者使用 touch.ones 函数,两个相等
testTensor = torch.ones((1, 3, 1, 1), dtype=torch.float32)小贴士:这里需要注意,张量数据类型 (dtype) 要与模型中偏置 (bias) 的数据类型一致。
使用一行代码将构建好的 PyTorch 模型导出至 ONNX,注意这里要使用 dynamic_axes 使输入图片大小任意。
torch.onnx.export( model, testTensor, ".\\test_onnx1.onnx", verbose=False, input_names=["image_in"], output_names=["image_out"], dynamic_axes={ "image_in": {0: 'batch_size', 2 : 'in_width', 3: 'in_height'}, "image_out": {0: 'batch_size', 2: 'out_width', 3:'out_height'}} )导出完成,可以使用 Netron 可视化模型,真炫酷。
模型输入节点的名字不一定是 image_in ,可以任意设置。
至此我们就已经转换为了 ONNX 格式,让我们来到转换为昇腾模型的准备阶段。
将中间格式模型转换为昇腾 OM 模型
准备阶段
开始查阅昇腾文档所需的资料。首先我们需要将动态输入在转换为 OM 模型时实现。
为了加快模型转换速度,我们后续也会对图片做补边预处理,使一些长宽稍微偏离输入尺寸的图片也能正确进行推理。
我们也需要实现 MAN 模型在训练时的预处理方法。MAN 模型是用 BasicSR 库进行训练的,这是一个通用的超分辨率训练库,图片的预处理会定义在 util 文件夹内,可以从数据的加载方法中看到数据处理方法。
看到了颜色通道排列方法是 R, G, B,而最终的张量排布是 NCHW,颜色需要均一化 (0~1),数据精度为32位浮点数,以上就是预处理方式。
还记得开头提到的 CANN 示例吗?里面有我们可以复用的轮子—— ACL 推理流程代码。所以我们只需要在示例的基础上修改部分操作,即可成功运行。
python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/acl_net.py · Ascend/samples - 码云 - 开源中国 (gitee.com)
上述的是 ResNet-50 分类网络模型,里面有完整的 AscendCL 流程。我们将修改:
对于昇腾设备来说它们要做的流程并没有变,只是我们需要使用 PIL 进行 CPU 方式的图片补边,推理后再裁边。
转换流程
因为内存需求,我们将直接使用非昇腾设备 Ubuntu 系统完成转换。转换之前需要安装 CANN 环境。
安装步骤(Ubuntu 18.04)-安装依赖-安装开发环境-软件安装 (命令行)-环境准备-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
首先使用命令迁移,命令按照官方文档来使用
一行命令中的参数:
设置的预设越多,读条越久。但等到成功的那一刻还是很开心的。
我们现在已经有了昇腾 OM 模型,可以用于推理了。简化流程,我们下面使用静态分辨率模型。
使用 AscendCL 进行推理
改写示例
启动 A2 开发板,启动 Jupyter Lab 样例,找到“03-resnet”示例,打开即可看到代码。

但很多代码是可以复用的,我们只需修改以下部分:
图片预处理:
def preprocess_img(input_path, target_shape_list:tuple): """图片预处理""" input_path = os.path.abspath(input_path) with Image.open(input_path) as image_file: current_image_size = image_file.size padding_image = image_file padding_image.show() # 归一化 img = np.array(padding_image,dtype=np.float32) / 255 # NCHW img = np.expand_dims(np.transpose(img, (2,0,1)), axis=0) result = np.frombuffer(img.tobytes(), np.float32) return result, current_image_size打印推理结果:
def _print_result(self, result): """打印推理结果 在 ResNet50 样例内这里是将 NumPy 转换为置信度 对于超分辨率直接 NumPy 数组转成图像输出好了""" # NumPy 结果转 PIL 图片,NCHW -> HWC for i in result: i = np.transpose(i[0][0:3], (1,2,0)) i = np.clip(i, 0., 1.) * 255 i = i.astype(np.uint8) i = np.clip(i,0,255) i = Image.fromarray(i,"RGB") i.show()主函数:
def main(): device = 0 model_path = 'MAN-light_x2_200x200.om' images_path = './data' targetList = ((200, 200),(300,300)) net = Net(device, model_path, targetList[0]) # 从文件夹读取图片进行流程 images_list = [os.path.join(images_path, img) for img in os.listdir(images_path) if os.path.splitext(img)[1] in IMG_EXT] for image in images_list: print("images:{}".format(image)) img, picSize = preprocess_img(image, targetList[0]) pred_dict = net.run([img]) print("*****run finish******") net.release_resource()以及适配预设的动态分辨率。
修改完毕,点击开始运行,我们使用 Set5 数据集进行测试。
可以看到成功推理出大图片~
小贴士:如果对 AscendCL 代码全流程较难理解,可转而使用示例 “Unet++”,这个示例将 ACL 封装起来成 acllite_util ,大大简化步骤,更易上手。
(两行代码即可)
总结
简要说明流程:
从研究记录中选择一个模型作为实验(首选 SR 超分辨率模型)
将 SR 模型转换为中间格式 (MindIR, ONNX)
将中间格式模型转换为昇腾 OM 模型
使用 AscendCL 进行推理
整个自身的体验流程就告一段落了。其中最有意思的肯定是平台的推理通过 ATC 将模型网络编译,大大缩短推理时间,算力开销大幅降低,才发现在模型边缘计算推理场景中性能需求可以压缩的如此低。将模型转换为昇腾 OM 模型所用的时间能接受,搭配上开发板的 GPIO 接口则有机会作为物联网的中枢。我自身也打算使用昇腾设备对开发模型进行推理测试,充分验证网络的实际应用性能;以及将昇腾开发板带到户外去,使用真实场景进行推理,所以求求官方赶快出一个外壳吧,把 PCB 螺丝孔设计图公开一下也可以啊(笑)。
感谢大家的观看,未来还会带来其他的进阶操作流程!
链接
安装须知-软件安装 (命令行)-环境准备-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
学习向导-ATC模型转换-推理应用开发-6.3.RC2.alpha003-CANN社区版-文档首页-昇腾社区 (hiascend.com)
导出ONNX模型-保存与导出模型-PyTorch 网络模型迁移和训练-模型开发(PyTorch)-6.3.RC1-CANN商用版-文档首页-昇腾社区 (hiascend.com)
samples: CANN Samples (gitee.com)