一、前言

最近在搞 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 移植的探索相关推荐

  1. linux在开发板LCD上显,W35型LCD驱动移植 - linux-2.6.32在mini2440开发板上移植_Linux编程_Linux公社-Linux系统门户网站...

    编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了集中屏幕的方案,我们这里主要就用一种,也就是开发板自带的W35型号.液晶驱动的源程序在src/drivers/vide ...

  2. 海思开发板上添加ftp功能

    海思开发板上添加ftp功能 前言: 本博客是基于海思3520Dv100开发,编译工具链为:arm-hisiv100nptl-linux-gcc 1.下载stupid-ftpd-1.5beta.tar. ...

  3. 海思开发板上挂载额外的存储空间

    注:海思开发板烧写好系统以后,只能使用90M大小的空间,这是在烧写文件系统时创建的.其实还有很大的存储空间没有用到,需要进行挂载. 一.使用如下命令可以查看开发板的存储空间使用情况 df -h 二.查 ...

  4. 为什么你们说好的程序在我的海思开发板上就是不行呢,难道真的是人品有问题

    就下面的程序,一个利用libpcap做的抓包程序,一个用raw socket 做的抓包程序 海思开发板 是通过映射过来的,被映射的是宝利通mcu rmx1800,终端目前用的是软终端,硬件终端还在路上 ...

  5. 【华为出品】物联网全栈开发实战营第2期来啦!送海思开发板

    物联网一直在改变我们生活的方方面面.可穿戴设备有助于监控我们的偏好.习惯和健康状况.智能家居设备可提高家居的舒适度.安全性和便利性.城市利用连接的数字设备收集的海量数据(数十亿个)来改善城市规划.制造 ...

  6. 海思开发板海图科技测评,海图海思开发板怎么样

    关于海思开发板海图科技的测评,相关关键字:hi3516,hi3519,hi3531,hi3535,hi3536,hi3559,hi3403 最近网络上关于海图的海思开发板宣传的沸沸扬扬,很多人都想要一 ...

  7. mysql移植海思_live555 交叉编译移植到海思开发板

    1.首先到它的主页下载一个源码包: http://www.live555.com/liveMedia/public/ 我下载的是latest的,具体什么版本还真不清楚 2.放到linux目录下解压: ...

  8. vmware虚拟机中ubuntu系统里设置USB串口连接海思开发板

    vmware虚拟机中ubuntu系统里设置USB串口连接海思开发板 作为海思平台的一个新手,在学习海思开发板时,会因为一个很小的问题折腾半天,但是当解决一个小问题时还是很兴奋的,记录下自己学习过程. ...

  9. 配置海思开发板的网络(永久修改)

    刚拿到的海思开发板(我的是hi3516dv300)里面默认的网络配置通常是不可用的(比如默认的网段跟我们自己的不一样.没法ping通外网等),这时候需要我们修改相关的配置文件. 1.可以先用ifcon ...

最新文章

  1. 数据结构与算法:22 精选练习50
  2. 人脸识别百亿蓝海之下,还需解决两方面问题
  3. ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范
  4. jsdk php,jsdk.php · webeautiful/dashpianku - Gitee.com
  5. HDU1285 确定名次 拓扑排序
  6. 一般拦截器 serviceImpl部分
  7. rails i18n模型_Rails国际化的完整指南(i18n)
  8. java String.intern();
  9. 可用于神经网络的一些matlab函数
  10. android制作弹出框样式,Android Dialog 弹出框 自定义 样式
  11. Tensorflow2.0入门教程(一)
  12. VS2017设置C++标准
  13. 与阿里合伙人合影,两年净赚一百万,这个草根姑娘有什么魔力?
  14. 微信自定义分享链接内容,wx.updateAppMessageShareData、wx.updateTimelineShareData、wx.onMenuShareTimeline
  15. numpy相关介绍和基本操作
  16. 强化学习笔记3:RL agent的主要组成部分
  17. JAVA实现Excel文件的导入导出
  18. 开发者模式(一) 各种姿势进入
  19. 斐波那契数列 - 递推公式及通项公式 代码
  20. nginx利用ngx_http_geoip2_module模块对国外ip限制

热门文章

  1. springboot hbase
  2. python初始教程 打印字符串
  3. 淘宝如何满足数据仓库海量数据处理需求
  4. VBA 数组定义,赋值,一维数组
  5. ARM关于标志位影响详解
  6. MYSQL 8.0 出现错误:Illegal argument to a regular expression.非法的正则表达式
  7. mybatis运行时错误Illegal argument exception argument type mismatch
  8. OWASP API安全Top 10
  9. 100句催人奋进的人生格言
  10. linux编译blas,在Linux中lapack / blas / openblas从源代码正确安装 – 用新的系统库替换系统库...