海思开发:海思上对 relu6、hswish、h-sigmoid 移植的探索
一、前言
最近在搞 mobilenet v2、v3,v2的激活函数是 relu6,v3有两个非线性函数:hswish 和 h-sigmoid,二者都用到了relu6,之前都是把它们替换,因为海思没有现成的relu6。当时就在想,能否利用现有op,组合成想要的relu6出来了? 这个想法在脑子里徘徊几天了,今天试着给它变现,结果如下。
二、经过
relu6与relu的最大区别就是前者的值域是[0, 6],而relu的值域是[0, +无穷]。所以对于x>6的值,我们要做个区分,于是看文档,终于发现可用的op,如下图,threshold layer 源码:
用法很明显了,我们可以设阈值为 6,当输入大于6时,输出1,否则输出0,有了这个 threshold 输出 0/1,我们可以写个公式:
公式:
relu6_out = (1 - threshold_out)* input + threshold_out * 6注:
1. input 是上一级的输出,准确的说是 relu 的输出;
2. threshold_out 是 threshold layer 的输出,只有 0 / 1 两种值;
3. 当 input > 6 时,threshold_out = 1 , relu6_out = 6;
4. 当 input < 6 时,threshold_out = 0 , relu6_out = input.
公式里还有些乘、加的 op,本来想用 sclae 层,后来发现 power层 更好用,power layer 博客:
好了,op都齐了,脑海中已经有了大致的结构与流程,给它画了出来,如下,下面所有的 op 作用等同于一个 relu6:
下面是代码编写部分,总体来说不算难写,调试时间也没多久。onnx2caffe转换代码在这里。
老规矩,打开转换代码工程目录下的 onnx2caffe_operators.py 文件,在py文件末尾加上:
# onnx2caffe\_operators.py 下
"Relu6": _convert_relu6 # 建议加在 relu 下面,方便查看
然后在上面添加一个_convert_relu6 函数:
# onnx2caffe\_operators.py 下
def _convert_relu6(node, graph, err):relu6_input_name = str(node.inputs[0])relu6_output_name = str(node.outputs[0])old_name = str(node.name)name = old_name + "_relu6"layers = []# 首先做 relu,node 1relu_name = name + "_relu"layer = myf("ReLU", relu_name, [relu6_input_name], [relu_name + "_out"], in_place=False)graph.channel_dims[relu_name + "_out"] = graph.channel_dims[relu6_input_name] # 输出节点的维度赋值layers.append(layer)# 其次做 threshold,node 2thre_name = name + "_thre"layer = myf("Threshold", thre_name, [relu_name + "_out"], [thre_name + "_out"],in_place=False,threshold_param=dict(threshold=6.0) # 阈值,大于它输出 1,否则为 0)graph.channel_dims[thre_name + "_out"] = graph.channel_dims[relu_name + "_out"]layers.append(layer)# threshold 左输出做线性变化,与x相乘,node 3thre_left_power_name = name + "_thre_left_power"layer = myf("Power", thre_left_power_name, [thre_name + "_out"], [thre_left_power_name + "_out"],in_place=False,power_param=dict(power=1.0,scale=(-1.0),shift=1.0))graph.channel_dims[thre_left_power_name + "_out"] = graph.channel_dims[thre_name + "_out"]layers.append(layer)# relu 后 x 输出处理,node 4x_thre_out_name = name + "_x_mul_thre_out"layer = myf("Eltwise", x_thre_out_name, [relu_name + "_out", thre_left_power_name + "_out"],[x_thre_out_name + "_out"], operation=P.Eltwise.PROD)graph.channel_dims[x_thre_out_name + "_out"] = graph.channel_dims[relu_name + "_out"]layers.append(layer)# threshold 右输出做线性变化,node 5thre_right_power_name = name + "_thre_right_power"layer = myf("Power", thre_right_power_name, [thre_name + "_out"], [thre_right_power_name + "_out"],in_place=False,power_param=dict(power=1.0,scale=6.0,shift=0.0))graph.channel_dims[thre_right_power_name + "_out"] = graph.channel_dims[thre_name + "_out"]layers.append(layer)# 最后结果汇总,node 6add_name = name + "_add"layer = myf("Eltwise", add_name, [x_thre_out_name + "_out", thre_right_power_name + "_out"],[relu6_output_name], operation=P.Eltwise.SUM)graph.channel_dims[relu6_output_name] = graph.channel_dims[relu6_input_name]layers.append(layer)return tuple(layers)
然后在 onnx2caffe_weightloader,py 文件末尾同样加上:
# onnx2caffe\_weightloader.py 下
"Relu6": _convert_relu6 # 建议加在 relu 下面,方便查看
再添加一个 _convert_relu6 函数
# onnx2caffe\_weightloader.py 下
def _convert_relu6(net, node, graph, err): # 因为没有参数,所以写个 pass 就好pass
再在 convertCaffe.py 文件中,加个判断条件,因为 relu6 在 onnx 是 clip,所以要加个条件让程序正确执行:
# convertCaffe.py 下,插入位置看我链接里的 demo 吧,说不清楚if op_type == "Clip":op_type = "Relu6"
之后就改好了,转换前后模型可视化图对比:
转换前:
转换后:
之后做了个pytorch版本与caffe版本的对比,二者除了保留位数不同外,结果一模一样!后面又把我的一个 mobilenet v2-relu6 模型给转换了一下,转换无报错,输出结果一样!所以兄弟们放心使用。
三、后言
仓促之下写成,如有遗漏、错误,还请指出,谢谢!此外,relu6搞定了, hswish 和 h-sigmoid 也可以实现了。我对 hswish 做了一下实现,至于 h-sigmoid 就没搞了,因为它和 hswish 很像。代码和上面放一起了,下面看看转换前后的模型图吧。
转换前:
转换后:
结果我也做了验证,输出一致,各位放心使用!
四、 说明
之所以标题最后是“探索”二字,是因为我并没有在海思板端部署过,只是对其转换成caffe
模型做了工作,具体移植时,恐怕会遇到问题,比如一位热心网友说的:“threshold层的阈值如果设6是有问题的,因为海思平台上6用20.12格式表示就是24576,这是超过了[0,4096]这个范围,海思平台threshhold层的参数范围要求是[0,4096]”
。
对此我的建议是把tensor
整体除以6
,阈值降为1
,这样应该能行。如果我来做,会选择直接替换成relu
函数,一了百了。
海思开发:海思上对 relu6、hswish、h-sigmoid 移植的探索相关推荐
- linux在开发板LCD上显,W35型LCD驱动移植 - linux-2.6.32在mini2440开发板上移植_Linux编程_Linux公社-Linux系统门户网站...
编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了集中屏幕的方案,我们这里主要就用一种,也就是开发板自带的W35型号.液晶驱动的源程序在src/drivers/vide ...
- 海思开发板上添加ftp功能
海思开发板上添加ftp功能 前言: 本博客是基于海思3520Dv100开发,编译工具链为:arm-hisiv100nptl-linux-gcc 1.下载stupid-ftpd-1.5beta.tar. ...
- 海思开发板上挂载额外的存储空间
注:海思开发板烧写好系统以后,只能使用90M大小的空间,这是在烧写文件系统时创建的.其实还有很大的存储空间没有用到,需要进行挂载. 一.使用如下命令可以查看开发板的存储空间使用情况 df -h 二.查 ...
- 为什么你们说好的程序在我的海思开发板上就是不行呢,难道真的是人品有问题
就下面的程序,一个利用libpcap做的抓包程序,一个用raw socket 做的抓包程序 海思开发板 是通过映射过来的,被映射的是宝利通mcu rmx1800,终端目前用的是软终端,硬件终端还在路上 ...
- 【华为出品】物联网全栈开发实战营第2期来啦!送海思开发板
物联网一直在改变我们生活的方方面面.可穿戴设备有助于监控我们的偏好.习惯和健康状况.智能家居设备可提高家居的舒适度.安全性和便利性.城市利用连接的数字设备收集的海量数据(数十亿个)来改善城市规划.制造 ...
- 海思开发板海图科技测评,海图海思开发板怎么样
关于海思开发板海图科技的测评,相关关键字:hi3516,hi3519,hi3531,hi3535,hi3536,hi3559,hi3403 最近网络上关于海图的海思开发板宣传的沸沸扬扬,很多人都想要一 ...
- mysql移植海思_live555 交叉编译移植到海思开发板
1.首先到它的主页下载一个源码包: http://www.live555.com/liveMedia/public/ 我下载的是latest的,具体什么版本还真不清楚 2.放到linux目录下解压: ...
- vmware虚拟机中ubuntu系统里设置USB串口连接海思开发板
vmware虚拟机中ubuntu系统里设置USB串口连接海思开发板 作为海思平台的一个新手,在学习海思开发板时,会因为一个很小的问题折腾半天,但是当解决一个小问题时还是很兴奋的,记录下自己学习过程. ...
- 配置海思开发板的网络(永久修改)
刚拿到的海思开发板(我的是hi3516dv300)里面默认的网络配置通常是不可用的(比如默认的网段跟我们自己的不一样.没法ping通外网等),这时候需要我们修改相关的配置文件. 1.可以先用ifcon ...
最新文章
- 数据结构与算法:22 精选练习50
- 人脸识别百亿蓝海之下,还需解决两方面问题
- ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范
- jsdk php,jsdk.php · webeautiful/dashpianku - Gitee.com
- HDU1285 确定名次 拓扑排序
- 一般拦截器 serviceImpl部分
- rails i18n模型_Rails国际化的完整指南(i18n)
- java String.intern();
- 可用于神经网络的一些matlab函数
- android制作弹出框样式,Android Dialog 弹出框 自定义 样式
- Tensorflow2.0入门教程(一)
- VS2017设置C++标准
- 与阿里合伙人合影,两年净赚一百万,这个草根姑娘有什么魔力?
- 微信自定义分享链接内容,wx.updateAppMessageShareData、wx.updateTimelineShareData、wx.onMenuShareTimeline
- numpy相关介绍和基本操作
- 强化学习笔记3:RL agent的主要组成部分
- JAVA实现Excel文件的导入导出
- 开发者模式(一) 各种姿势进入
- 斐波那契数列 - 递推公式及通项公式 代码
- nginx利用ngx_http_geoip2_module模块对国外ip限制
热门文章
- springboot hbase
- python初始教程 打印字符串
- 淘宝如何满足数据仓库海量数据处理需求
- VBA 数组定义,赋值,一维数组
- ARM关于标志位影响详解
- MYSQL 8.0 出现错误:Illegal argument to a regular expression.非法的正则表达式
- mybatis运行时错误Illegal argument exception argument type mismatch
- OWASP API安全Top 10
- 100句催人奋进的人生格言
- linux编译blas,在Linux中lapack / blas / openblas从源代码正确安装 – 用新的系统库替换系统库...