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. ASP.NET Core 6.0+Vue.js 3 实战开发(视频)

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章或视频能成为你成长路上的垫脚石. 录制视频的体验 这是一个收费的视频,很抱歉,让您失望了. 我尝试做点收费的视频,不是因为我不 ...

  2. kafka-Kafka3.4版本创建topic出现zookeeper is not a recognized option

    问题描述:在linux云服务器上搭建了一套kafka3.0集群,然后按照以前的创建topic指令: ./kafka-topics.sh --zookeeper hadoop01:2181,hadoop ...

  3. 探索C语言中的联合体与枚举:数据多面手的完美组合!

    ​ 欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 联合体的定义 联合体又叫共用体,它是一种特殊的数据类型,允许您在相同的内存位置存 ...

  4. Java设计模式-代理模式Proxy

    介绍 代理模式是一种比较好理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. ...

  5. Springboot+Vue+ElementUI实现的宿舍管理系统

    项目说明 doman是一个基于Springboot+Vue实现的前后端分离的宿舍管理系统.项目为本人亲手打造,需要的朋友可以拿去做个修改也是不错的.大神请忽略:) 项目功能 详细请看功能演示: Spr ...

  6. oracle FGAC(细粒度访问控制)介绍

    在ORACLE中,RLS有时也叫做虚拟私有数据库(VPD)或者细粒度访问控制(FGAC). RLS由8i引进,利用这一特性我们可以对表定义安全策略(并且指明对表的操作类型),实现对用户可以看到或者修改 ...

  7. spring boot+layui实现增删改查实战

    说明: 最近在做一个后台,希望用一个现成的前端模板,找了一圈发现Layui比较合适.我知道很多人都有这个需求,为了使大家快速上手,我把自己写的最实用的增删改查案例完整的展示出来. 源码地址: http ...

  8. 在vue项目中使用scss语法的准备步骤

    在vue项目中使用scss语法的准备步骤 个人总结: 在项目根目录cmd控制台中使用以下命令行,安装vue项目中使用scss的相关依赖; 在["项目根目录/build/webpack.bas ...

  9. 用ABP Suite创建Blazor Server的应用程序

    这个应用程序我们取名为BlazorOne,意思是集AuthServer.HttpApi Host和Blazor Server3个功能于一体的应用程序.因为ABP Suite支持另外一种模式,是把上述3 ...

  10. 【Azure 应用服务】Azure Function Python函数部署到Azure后遇见 Value cannot be null. (Parameter 'receiverConnectionString') 错误

    问题描述 使用VS Code创建Python Function,处理Event Hub中的数据.当部署到Azure Function App后,函数无法执行,查看 Function 日志出现 Valu ...