ghostnet论文解析:ghost
创建日期: 2020-03-02 17:02:54
简介:
GhostNet是2020CVPR录用的一篇对卷积操作进行改进的论文。文章的核心内容是Ghost模块(Ghost Module),可以用来替换任何经典CNN网络中的卷积操作,突出优势是轻量高效,实验证明使用了Ghost Module的MobileNetV3的效果,要比原始的MobileNetV3要好。贴出paper和code地址:
https://arxiv.org/abs/1911.11907huawei-noah/ghostnet
本文不包含GhostNet的实验分析部分,主要介绍核心内容Ghost module的原理,以及在Ghost Module基础上搭建的Ghost BottleNeck的原理,还有在实践过程中部署/移植到其他CNN网络的方法。
1. Ghost Module原理
出发点:通过对比分析ResNet-50网络第一个残差组(Residual group)输出的特征图可视化结果,发现一些特征图高度相似(如Ghost一般,下图中的三组box内的图像对)。如果按照传统的思考方式,可能认为这些相似的特征图存在冗余,是多余信息,想办法避免产生这些高度相似的特征图。
但本文思路清奇,推测CNN的强大特征提取能力和这些相似的特征图(Ghost对)正相关,不去刻意的避免产生这种Ghost对,而是尝试利用简单的线性操作来获得更多的Ghost对。

常规卷积:我们通常使用的卷积是下图这种,运算量约等于 hwcnw'*h' (忽略偏置计算)

Ghost Module:分为常规卷积、Ghost生成和特征图拼接三步(如下图所示):
- 首先用常规卷积得到本征特征图(intrinsic feature maps)
Y_{w'h'm} ,这部分的运算量约等于
hwcmw'*h' (忽略偏置项)。

\2. 然后将 Y’ 每一个通道的特征图
y^{'}i ,用
\Phi{i,j} 操作来产生Ghost特征图
y_{ij} 。

\3. 最后将第一步得到的本征特征图和第二步得到的Ghost特征图拼接(identity连接)得到最终结果OutPut。

(PS: 当然也可以认为(论文中的思路),第2步中的 \Phi_{i,j} 中包含一个单位/恒等映射,即将本征特征图直接输出,则不需用第三部,例如:对于Y’(m通道)中的每一个特征图,对其进行s次映射,s次中包含一次恒等映射,其余s-1次为cheap operate来得到Ghost特征图。所以最终得到m*s通道的输出结果。理论上完全一致。)
对线性操作
\Phi_{i,j} 的理解:论文中表示,可以探索仿射变换和小波变换等其他低成本的线性运算来构建Ghost模块。但是,卷积是当前硬件已经很好支持的高效运算,它可以涵盖许多广泛使用的线性运算,例如平滑、模糊等。 此外,线性运算
\Phi_{i,j} 的滤波器的大小不一致将降低计算单元(例如CPU和GPU)的效率,所以论文中实验中让Ghost模块中的滤波器size取固定值,并利用Depthwise卷积实现
\Phi_{i,j} ,以构建高效的深度神经网络。
所以说,论文中使用的线性操作并不是常见的旋转、平移、仿射变换、小波变换等,而是用的Depthwise卷积。个人猜测可能是传统的线性操作效果没有Depthwise效果好,毕竟CNN可以自动调整filter的权值。那么Ghost Module和深度分离卷积就很类似了,不同之处在于先进行PointwiseConv,后进行DepthwiseConv,另外增加了DepthwiseConv的数量,包括一个恒定映射。
小结:很明显,相比于直接用常规卷积,Ghost Module的计算量大幅度降低。个人认为从另一个角度可以看做是对卷积得到的特征图做了增强/增广,和数据增广似乎有点相似。
2. Ghost BottleNeck原理
Ghost BottleNeck整体架构和Residual Block非常相似,也可以直接认为是将Residual Block中的卷积操作用Ghost Module(GM)替换得到。

上图基本上对Ghost描述的很清楚,第一张图(左,stride=1)主干通路用两个Ghost Module(GM)串联组成,其中第一个GM扩大通道数,第二个GM将通道数降低到与输入通道数一致;跳跃连接通路与ResNet使用方法一样。这样一来,Ghost BottleNeck输入输出维度也一致了,可以和ResBlock一样,很方便地嵌入到其他CNN网络中。
第二张图(右,stride=2)和第一张图的不同之处在于,主干通路的两个GM之间加入了一个stride=2的Deepwise卷积,可以将特征图大小降为输入的1/2,同样跳跃连接通路也需要同样的降采样,以保证Add操作可以对齐。这个模块可以用来替换其他CNN中的降采样层(1/2)。
PS:Ghost BottleNeck的Add操作前主干通路不进行ReLU激活(参考了MobileNetV2);
实际应用中,为了进一步提高效率,GhostModule中的所有常规卷积都用pointwise卷积代替。
3. Ghost部署/移植
这部分对官方代码进行分析,并讨论一下如何对Ghost Module进行移植的方法。
(2020.07.04更新)
Ghost Module的pytorch实现:
class GhostModule(nn.Module):
def __init__(self, inp, oup, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):
super(GhostModule, self).__init__()
self.oup = oup
init_channels = math.ceil(oup / ratio)
new_channels = init_channels*(ratio-1)
self.primary_conv = nn.Sequential(
nn.Conv2d(inp, init_channels, kernel_size, stride, kernel_size//2, bias=False),
nn.BatchNorm2d(init_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
self.cheap_operation = nn.Sequential(
nn.Conv2d(init_channels, new_channels, dw_size, 1, dw_size//2, groups=init_channels, bias=False),
nn.BatchNorm2d(new_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
def forward(self, x):
x1 = self.primary_conv(x)
x2 = self.cheap_operation(x1)
out = torch.cat([x1,x2], dim=1)
return out[:,:self.oup,:,:]
Ghost BottleNeck的pytorch实现:
class GhostBottleneck(nn.Module):
def __init__(self, inp, hidden_dim, oup, kernel_size, stride, use_se):
super(GhostBottleneck, self).__init__()
assert stride in [1, 2]
self.conv = nn.Sequential(
# pw
GhostModule(inp, hidden_dim, kernel_size=1, relu=True),
# dw
depthwise_conv(hidden_dim, hidden_dim, kernel_size, stride, relu=False) if stride==2 else nn.Sequential(),
# Squeeze-and-Excite
SELayer(hidden_dim) if use_se else nn.Sequential(),
# pw-linear
GhostModule(hidden_dim, oup, kernel_size=1, relu=False),
)
if stride == 1 and inp == oup:
self.shortcut = nn.Sequential()
else:
self.shortcut = nn.Sequential(
depthwise_conv(inp, inp, 3, stride, relu=True),
nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
def forward(self, x):
return self.conv(x) + self.shortcut(x)
Ghost BottleNeck结构类似于MobileNetV2的模块,可以很方便的嵌入到模型的任何地方,我在下面这个github项目里面调用了GhostNet网络在Cifar10数据集上进行分类测试。
https://github.com/lee-zq/CNN-Backbone
ghostnet论文解析:ghost的更多相关文章
- [Network Architecture]Mask R-CNN论文解析(转)
前言 最近有一个idea需要去验证,比较忙,看完Mask R-CNN论文了,最近会去研究Mask R-CNN的代码,论文解析转载网上的两篇博客 技术挖掘者 remanented 文章1 论文题目:Ma ...
- LTMU论文解析
LTMU 第零部分:前景提要 一般来说,单目标跟踪任务可以从以下三个角度解读: A matching/correspondence problem.把其视为前后两帧物体匹配的任务(而不考虑在跟踪过程中 ...
- CVPR2020论文解析:实例分割算法
CVPR2020论文解析:实例分割算法 BlendMask: Top-Down Meets Bottom-Up for Instance Segmentation 论文链接:https://arxiv ...
- 人脸真伪验证与识别:ICCV2019论文解析
人脸真伪验证与识别:ICCV2019论文解析 Face Forensics++: Learning to Detect Manipulated Facial Images 论文链接: http://o ...
- 人体姿态和形状估计的视频推理:CVPR2020论文解析
人体姿态和形状估计的视频推理:CVPR2020论文解析 VIBE: Video Inference for Human Body Pose and Shape Estimation 论文链接:http ...
- 视频教学动作修饰语:CVPR2020论文解析
视频教学动作修饰语:CVPR2020论文解析 Action Modifiers: Learning from Adverbs in Instructional Videos 论文链接:https://a ...
- 分层条件关系网络在视频问答VideoQA中的应用:CVPR2020论文解析
分层条件关系网络在视频问答VideoQA中的应用:CVPR2020论文解析 Hierarchical Conditional Relation Networks for Video Question ...
- 慢镜头变焦:视频超分辨率:CVPR2020论文解析
慢镜头变焦:视频超分辨率:CVPR2020论文解析 Zooming Slow-Mo: Fast and Accurate One-Stage Space-Time Video Super-Resol ...
- CVPR2020论文解析:视觉算法加速
CVPR2020论文解析:视觉算法加速 GPU-Accelerated Mobile Multi-view Style Transfer 论文链接:https://arxiv.org/pdf/2003 ...
随机推荐
- java-规约-集合
/** * 1 * @hashCode&equals的处理: * 1-只要覆写了equals,必须复写hashCode. * 2-因为Set存储的是不重复的对象,依据hashCode和equa ...
- 深入理解Java虚拟机-走进Java
一.Java技术体系 从广义上讲, Clojure. JRuby. Groovy等运行于Java虚拟机上的语言及其相关的程序都属于Java技术体系中的一员. 如果仅从传统意义上来看, Sun官方所定义 ...
- 学习GlusterFS(二)
环境准备 3台机器,每个机器双网卡,每个机器还需要额外添加1个10GB的磁盘用于测试 机器系统版本是centos6.6 1 2 3 4 5 [root@gluster-1-1 ~]# uname -r ...
- 8.5_线性控制器设计_轨迹跟踪(Follow a Desired Path)
平衡点时所有的导数都为0 simulink中建立状态方程模型
- MOS管防反接电路设计
转自嵌入式单片机之家公众号 问题的提出 电源反接,会给电路造成损坏,不过,电源反接是不可避免的.所以,我们就需要给电路中加入保护电路,达到即使接反电源,也不会损坏的目的 01二极管防反接 通常情况下直 ...
- jquery+html5实现单张图片上传预览
js: if (window.File && window.FileReader && window.FileList && window.Blob){ ...
- es8(字符串,对象)
es8(字符串,对象) 字符串补白: let str = "abc"; let a = str.padEnd(5); let b = str.padStart(5); let c ...
- java string中replaceAll替换特殊符号
例如在mysql数据库中建表时表名不能使用特殊符号,'-','{}'等等,所以我们要筛选去掉 public static void main(String[] args) { String regEx ...
- PAT B1061判断题
题目描述: 判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分. 输入格式: 输入在第一行给出两个不超过 100 的正整数 N 和 M,分别是学生人数和判断题数量.第二 ...
- Android.mk文件如何打日志信息
1. 在mk文件中添加:$(warning "xxx="$(变量名)) 2. 执行lunch,选一个分支,此过程中可以打出添加的log.