PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=113)

环境说明
  • Ubuntu 18.04
  • MLU270 加速卡一张
  • 寒武纪Pytorch-Docker移植环境

前言


  阅读本文前,请务必须知以下前置文章概念:

  经过了前面两篇文章的介绍,我们也对寒武纪加速平台有了一个朴实的了解。为了加深我们对寒武纪平台的理解,我这里将会使用一个分割网络的实例来展示寒武纪平台整个模型移植和部署过程。

  若文中引用部分存在侵权,请及时联系我删除。

实例基本介绍


  这里对这个简单的分割网络做一个简介,这里训练使用的是CamVid数据集。输入是1*3*480*480。输出是480*480。

  这里最终的效果就是分割出输入图片里面的汽车。最终网络效果测试如下图:

  这个时候,我们也得到了一个可以用于移植和测试的pth模型文件。

移植模型基本步骤


  其实Pytorch的模型移植还是比较简单的,按照一定流程进行测试即可。我总结的基本流程如下:

  • 在docker里面,跑cpu版本的模型推理代码。
  • 在docker里面,跑cpu版本的量化模型生成代码,同时进行量化模型的测试。
  • 在docker里面,将量化模型转换为离线模型。
在Docker里运行cpu推理代码

  至今为止,根据寒武纪官方文档描述,现在的docker环境里面存在的是pytorch1.3环境,这个可能和主流模型支持的pytorch 1.7+有差异。所以,为了后续工作的顺利展开,我们不要一上来就开始量化模型,先保证模型能够在pytorch 1.3环境能够正常工作。

  当我们训练好模型后,得到pth文件,然后在训练环境里面还会做一个测试pth文件的脚本,判断模型的效果。同理,我们应该将此测试脚本放到移植环境里面再跑一次,一般来说都会多多少少出点问题。

  至今为止,我们遇到过两大类问题,一类为pytorch1.3某些算子不支持,可以更换为其他类似算子,或者自己实现这个算子。第二类为一些版本问题,比如模型保存的格式在pytorch1.6后使用的是zip格式(详情见torch.save api说明注释里面),旧版本要加载模型,需要使用_use_new_zipfile_serialization=False重新存储一下模型文件。

  一般来说,大致的模型转换代码如下:

# 存在一个模型test.pth(zip格式)
# 存在一个获取的模型网络结构类:TestModel
import torch model = TestModel()
state_dict = torch.load('test.pth', map_location=torch.device('cpu'))
model.load_state_dict(state_dict, strict=True) torch.save(model, 'new_test.pth', _use_new_zipfile_serialization=False)
# 得到了旧版本的pth文件。方便pytorch 1.6以下进行加载
在Docker里处理量化模型

  这里有两个步骤,首先是使用寒武纪的pytorch接口生成量化模型,然后对量化模型进行测试。注意,这里生成的量化模型有两种,一种是INT8,一种是INT16,具体怎么选择,根据实际情况。一般来说,分类、分割算法可以尝试直接使用INT8,目标检测需要测试再下结论。此外INT8由于运算量的减少,也意味着推理速度的提升。如果不特殊说明,后续默认采用的是INT8模式。

  此外,还需要说明的是,量化一般是量化卷积、全连接等这些参数量较大的层,其他的模型参数依旧是FP16或者FP32存在。

  首先生成量化模型:

# 存在一个模型new_test.pth(非zip格式)
# 存在一个获取的模型网络结构类:TestModel
import torch
import torch_mlu.core.mlu_quantize as mlu_quantize model = TestModel()
state_dict = torch.load('new_test.pth', map_location=torch.device('cpu'))
model.load_state_dict(state_dict, False)
mean=[]
std=[]
# 注意此接口,这里不使用firstconv优化,它的作用是将归一化放到第一层去一起加速做,但是有些模型的前处理是不需要这样做的,具体信息,请参考寒武纪官方文档。
net_quantization = mlu_quantize.quantize_dynamic_mlu(model, {'mean':mean, 'std':std, 'firstconv':False}, dtype='int8', gen_quant=True)
torch.save(net_quantization.state_dict(), 'test_quantization.pth') # 得到了INT8的量化模型文件test_quantization.pth

  然后在量化模型上测试,此步骤的内容是验证模型量化之后,使用寒武纪定制的pytorch量化算子能否正常得到结果:

# 存在一个INT8的量化模型文件test_quantization.pth
# 存在一个获取的模型网络结构类:TestModel
import torch_mlu
import torch_mlu.core.mlu_model as ct
import torch_mlu.core.mlu_quantize as mlu_quantize model = TestModel() # step 1
net = mlu_quantize.quantize_dynamic_mlu(model)
# step 2
net.load_state_dict(torch.load('test_quantization.pth'))
# 这里是
input_data=torch.randn((1,3,480,480))
# step 3
net_mlu = net.to(ct.mlu_device())
input_mlu = input_data.to(ct.mlu_device())
# step 4
output=net_mlu(input_mlu)
print(output.cpu())
# output的shape是480*480

  如果这里量化之后的推理结果都是准确无误的,那么基本证明了模型移植成功了。其实从这里可以看出,这里的mlu其实就可以类比cuda,就可以大致猜想mlu是什么样的存在了。

在Docker里生成离线模型

  在之前的基础上,其实我们很快很方便的就生成了离线模型,不过这里的离线模型同样也有两种,还记得前文说的量化只会量化一些特殊层的参数,而模型中的其他层也是用的FP16或者,FP32,因此,离线模型也具备两种,一种是FP16,一种是FP32。通常来说,一个INT8版本的FP16离线模型是最佳的离线模型。

  生成MLU220离线模型:

# 存在一个INT8的量化模型文件test_quantization.pth
# 存在一个获取的模型网络结构类:TestModel
import torch_mlu
import torch_mlu.core.mlu_model as ct
import torch_mlu.core.mlu_quantize as mlu_quantize model = TestModel() # step 1
net = mlu_quantize.quantize_dynamic_mlu(model)
# step 2
net.load_state_dict(torch.load('test_quantization.pth'))
#
input_data=torch.randn((1,3,480,480))
# step 3
net_mlu = net.to(ct.mlu_device())
input_mlu = input_data.to(ct.mlu_device()) # 详细查看文档,一般4
core_number = 4
ct.set_core_number(core_number)
ct.set_core_version('MLU220')
# torch_mlu.core.mlu_model.set_input_format(input_format)
ct.save_as_cambricon('test') net_trace = torch.jit.trace(net_mlu, input_mlu, check_trace=False) net_trace(input_mlu) torch_mlu.core.mlu_model.save_as_cambricon("") # 最终,我们得到了test.cambricon 和 test.cambricon_twins。test.cambricon_twins是离线模型的说明文件,包含输入数据格式通道等信息,也包含输出相关的信息。

  到此,我们已经得到了离线模型,也完成了我们模型移植的前面一半的工作。

  此外,如果想得到MLU270的离线模型,也可以将set_core_version参数改为MLU270。如果将模型和输入tensor调用half()之后,就会得到fp16的模型格式,具体参考寒武纪官方文档。

  .cambricon_twins文件有一个重要的作用就是描述离线模型网络是输入输出格式及通道,毕竟我们的网络一般结果对不上,很大的原因都是预处理和后处理的毛病。下面我会给出.cambricon_twins的两个实例,一个是INT8FP32,一个是INT8FP16。

后记


  模型的移植流程,基本上都是固定的,一旦熟悉之后,其实就不会改了。

  最终一般有6个模型生成,两个INT8和INT16的量化模型。4个离线模型,INT8-FP32,INT8-FP16,INT16-FP32,INT16-FP16。不同的模型对应不同的速度和精度,根据模型实际情况酌情选择。

  注意,寒武纪除了支持Pytorch模型移植外,还支持caffe和tensorflow,因此如果需要转换这些模型,请查看对应文档。

参考文献


打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

寒武纪加速平台(MLU200系列) 摸鱼指南(三)--- 模型移植-分割网络实例的更多相关文章

  1. 寒武纪加速平台(MLU200系列) 摸鱼指南(四)--- 边缘端实例程序分析

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  2. 寒武纪加速平台(MLU200系列) 摸鱼指南(二)--- 模型移植-环境搭建

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  3. 寒武纪加速平台(MLU200系列) 摸鱼指南(一)--- 基本概念及相关介绍

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  4. 春节前“摸鱼”指南——SCA命令行工具助你快速构建FaaS服务

    春节将至,身在公司的你是不是已经完全丧失了工作的斗志? 但俗话说得好:"只要心中有沙,办公室也能是马尔代夫." 职场人如何才能做到最大效能地带薪"摸鱼",成为了 ...

  5. 【转】让Chrome化身成为摸鱼神器,利用Chorme运行布卡漫画以及其他安卓APK应用教程

    下周就是十一了,无论是学生党还是工作党,大家的大概都会有点心不在焉,为了让大家更好的心不在焉,更好的在十一前最后一周愉快的摸鱼,今天就写一个如何让Chrome(google浏览器)运行安卓APK应用的 ...

  6. Thief-Book 上班摸鱼神器

    Thief-Book 上班摸鱼神器 介绍 Thief-Book 是一款真正的摸鱼神器,可以更加隐秘性大胆的看小说. 隐蔽性 自定义透明背景,随意调整大小,完美融入各种软件界面 快捷性 三个快捷键,实现 ...

  7. AI解决方案:边缘计算和GPU加速平台

    AI解决方案:边缘计算和GPU加速平台 一.适用于边缘 AI 的解决方案 AI 在边缘蓬勃发展.AI 和云原生应用程序.物联网及其数十亿的传感器以及 5G 网络现已使得在边缘大规模部署 AI 成为可能 ...

  8. 菜鸡学C语言之摸鱼村村长

    题目描述 摸鱼村要选村长了! 选村长的规则是村里每个人进行一次投票,票数大于人数一半的成为村长. 然鹅摸鱼村的人都比较懒,你能帮他们写一个程序来找出谁当选村长吗? (每名村民的编号都是一个int范围内 ...

  9. [摸鱼]cdq分治 && 学习笔记

    待我玩会游戏整理下思绪(分明是想摸鱼 cdq分治是一种用于降维和处理对不同子区间有贡献的离线分治算法 对于常见的操作查询题目而言,时间总是有序的,而cdq分治则是耗费\(O(logq)\)的代价使动态 ...

  10. HNOI2018 摸鱼记

    HNOI2018 摸鱼记 今天我又来记流水账啦 Day 0 颓废的一天. 我,球爷和杜教在颓膜膜.io ych看起来在搓碧蓝 鬼知道哥达鸭干了什么 学习氛围只局限在机房的一角 后来全体Oier开会,5 ...

随机推荐

  1. Android 相册

  2. Azure - 机器学习:创建机器学习所需资源,配置工作区

    本文中你可以创建使用 Azure 机器学习所需的资源,包含工作区和计算实例. 关注TechLead,分享AI全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团队管理经验,同济本复旦硕,复 ...

  3. 哈希表(HashMap)与字符串哈希

    哈希表 哈希表是一种通过映射来快速查找的数据结构.其通过键值对(key-value)来存储.一个数据通过哈希函数的运算来生成一个属于他自己的键值,尔后将其与键值绑定.当我们想查找这个数据时,就可以直接 ...

  4. NC210520 Min酱要旅行

    题目链接 题目 题目描述 从前有个富帅叫做Min酱,他很喜欢出门旅行,每次出门旅行,他会准备很大一个包裹以及一大堆东西,然后尝试各种方案去塞满它. 然而每次出门前,Min酱都会有个小小的烦恼.众所周知 ...

  5. sensitive word 敏感词(脏词) 如何忽略无意义的字符?达到更好的过滤效果?

    忽略字符 说明 我们的敏感词一般都是比较连续的,比如 傻帽 那就有大聪明发现,可以在中间加一些字符,比如[傻!@#$帽]跳过检测,但是骂人等攻击力不减. 那么,如何应对这些类似的场景呢? 我们可以指定 ...

  6. 快速傅里叶变换(FFT)和小波分析在信号处理上的应用

    1前言 1.1傅里叶变换 函数f(t)为一元连续函数,其傅里叶变换定义为: F(w)的傅里叶逆变换定义为: 其中,i为虚数单位.由欧拉公式: 任意绝对可积的连续函数f(t),都可以用三角函数表示,由于 ...

  7. 【Android】使用MediaExtractor获取关键帧的时间戳

    1 前言 使用MediaExtractor.MediaMuxer去掉视频文件中的音频数据 中介绍了 MediaExtractor 类的主要方法,本文主要将使用其 advance() 和 seekTo( ...

  8. Vue+SpringBoot+ElementUI实战学生管理系统-9.教师管理模块

    1.章节介绍 前一篇介绍了班级管理模块,这一篇编写教师管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 教师列表 修改教师 4.模块 ...

  9. 【libGDX】加载G3DJ模型

    1 前言 ​ libGDX 提供了自己的 3D 格式模型文件,称为 G3D,包含 g3dj(Json 格式)和 g3db(Binary 格式)文件,官方介绍见 → importing-blender- ...

  10. java+文件读写实现的图书管理系统

    一功能 管理员具有的功能 1.增加图书.删除图书.修改图书信息.查询图书.图书列表 2.借阅者管理,通过借阅的书号查询图书信息 3.个人信息修改 读者功能 1.图书借阅 2.图书归还 3.图书查询 4 ...