ShuffleNet算法详解

2024-06-10 11:48
文章标签 算法 详解 shufflenet

本文主要是介绍ShuffleNet算法详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原博文:

论文:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices
论文链接:https://arxiv.org/abs/1707.01083

算法详解:
ShuffleNet是Face++的一篇关于降低深度网络计算量的论文,号称是可以在移动设备上运行的深度网络。
这篇文章可以和MobileNet、Xception和ResNeXt结合来看,因为有类似的思想。卷积的group操作从AlexNet就已经有了,当时主要是解决模型在双GPU上的训练。ResNeXt借鉴了这种group操作改进了原本的ResNet。MobileNet则是采用了depthwise separable convolution代替传统的卷积操作,在几乎不影响准确率的前提下大大降低计算量,具体可以参考MobileNets-深度学习模型的加速。Xception主要也是采用depthwise separable convolution改进Inception v3的结构。

该文章主要采用channel shuffle、pointwise group convolutions和depthwise separable convolution来修改原来的ResNet单元,接下来依次讲解。

channel shuffle的思想可以看下面的Figure 1。这就要先从group操作说起,一般卷积操作中比如输入feature map的数量是N,该卷积层的filter数量是M,那么M个filter中的每一个filter都要和N个feature map的某个区域做卷积,然后相加作为一个卷积的结果。假设你引入group操作,设group为g,那么N个输入feature map就被分成g个group,M个filter就被分成g个group,然后在做卷积操作的时候,第一个group的M/g个filter中的每一个都和第一个group的N/g个输入feature map做卷积得到结果,第二个group同理,直到最后一个group,如Figure1(a)。不同的颜色代表不同的group,图中有三个group。这种操作可以大大减少计算量,因为你每个filter不再是和输入的全部feature map做卷积,而是和一个group的feature map做卷积。但是如果多个group操作叠加在一起,如Figure1(a)的两个卷积层都有group操作,显然就会产生边界效应,什么意思呢?就是某个输出channel仅仅来自输入channel的一小部分。这样肯定是不行的的,学出来的特征会非常局限。于是就有了channel shuffle来解决这个问题,先看Figure1(b),在进行GConv2之前,对其输入feature map做一个分配,也就是每个group分成几个subgroup,然后将不同group的subgroup作为GConv2的一个group的输入,使得GConv2的每一个group都能卷积输入的所有group的feature map,这和Figure1(c)的channel shuffle的思想是一样的。

这里写图片描述

pointwise group convolutions,其实就是带group的卷积核为1*1的卷积,也就是说pointwise convolution是卷积核为1*1的卷积。在ResNeXt中主要是对3*3的卷积做group操作,但是在ShuffleNet中,作者是对1*1的卷积做group的操作,因为作者认为1*1的卷积操作的计算量不可忽视。可以看Figure2(b)中的第一个1*1卷积是GConv,表示group convolution。Figure2(a)是ResNet中的bottleneck unit,不过将原来的3*3 Conv改成3*3 DWConv,作者的ShuffleNet主要也是在这基础上做改动。首先用带group的1*1卷积代替原来的1*1卷积,同时跟一个channel shuffle操作,这个前面也介绍过了。然后是3*3 DWConv表示depthwise separable convolution。depthwise separable convolution可以参考MobileNet,下面贴出depthwise separable convolution的示意图。Figure2(c)添加了一个Average pooling和设置了stride=2,另外原来Resnet最后是一个Add操作,也就是元素值相加,而在(c)中是采用concat的操作,也就是按channel合并,类似googleNet的Inception操作。

这里写图片描述

下图就是depthwise separable convolution的示意图,其实就是将传统的卷积操作分成两步,假设原来是3*3的卷积,那么depthwise separable convolution就是先用M个3*3卷积核一对一卷积输入的M个feature map,不求和,生成M个结果,然后用N个1*1的卷积核正常卷积前面生成的M个结果,求和,最后得到N个结果。具体可以看另一篇博文:MobileNets-深度学习模型的加速。

这里写图片描述

Table 1是ShuffleNet的结构表,基本上和ResNet是一样的,也是分成几个stage(ResNet中有4个stage,这里只有3个),然后在每个stage中用ShuffleNet unit代替原来的Residual block,这也就是ShuffleNet算法的核心。这个表是在限定complexity的情况下,通过改变group(g)的数量来改变output channel的数量,更多的output channel一般而言可以提取更多的特征。

这里写图片描述

实验结果:
Table2表示不同大小的ShuffleNet在不同group数量情况下的分类准确率比较。ShuffleNet s*表示将ShuffleNet 1*的filter个数变成s倍。arch2表示将原来网络结构中的Stage3的两个uint移除,同时在保持复杂度的前提下widen each feature map。Table2的一个重要结论是group个数的线性增长并不会带来分类准确率的线性增长。但是发现ShuffleNet对于小的网络效果更明显,因为一般小的网络的channel个数都不多,在限定计算资源的前提下,ShuffleNet可以使用更多的feature map。

这里写图片描述

Table3表示channel shuffle的重要性。

这里写图片描述

Table4是几个流行的分类网络的分类准确率对比。Table5是ShuffleNet和MobileNet的对比,效果还可以。

这里写图片描述

总结:
ShuffleNet的核心就是用pointwise group convolution,channel shuffle和depthwise separable convolution代替ResNet block的相应层构成了ShuffleNet uint,达到了减少计算量和提高准确率的目的。channel shuffle解决了多个group convolution叠加出现的边界效应,pointwise group convolution和depthwise separable convolution主要减少了计算量。


这篇关于ShuffleNet算法详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048080

相关文章

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

Springboot配置文件相关语法及读取方式详解

《Springboot配置文件相关语法及读取方式详解》本文主要介绍了SpringBoot中的两种配置文件形式,即.properties文件和.yml/.yaml文件,详细讲解了这两种文件的语法和读取方... 目录配置文件的形式语法1、key-value形式2、数组形式读取方式1、通过@value注解2、通过

自定义注解SpringBoot防重复提交AOP方法详解

《自定义注解SpringBoot防重复提交AOP方法详解》该文章描述了一个防止重复提交的流程,通过HttpServletRequest对象获取请求信息,生成唯一标识,使用Redis分布式锁判断请求是否... 目录防重复提交流程引入依赖properties配置自定义注解切面Redis工具类controller

Python容器转换与共有函数举例详解

《Python容器转换与共有函数举例详解》Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面:本文主要介绍Python容器转换与共有函数的相关资料,... 目录python容器转换与共有函数详解一、容器类型概览二、容器类型转换1. 基本容器转换2. 高级转换示

HTML5的input标签的`type`属性值详解和代码示例

《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动