深度可分离卷积结构(depthwise separable convolution)计算复杂度分析
https://zhuanlan.zhihu.com/p/28186857
这个例子说明了什么叫做空间可分离卷积,这种方法并不应用在深度学习中,只是用来帮你理解这种结构。
在神经网络中,我们通常会使用深度可分离卷积结构(depthwise separable convolution)。
这种方法在保持通道分离的前提下,接上一个深度卷积结构,即可实现空间卷积。接下来通过一个例子让大家更好地理解。
假设有一个3×3大小的卷积层,其输入通道为16、输出通道为32。具体为,32个3×3大小的卷积核会遍历16个通道中的每个数据,从而产生16×32=512个特征图谱。进而通过叠加每个输入通道对应的特征图谱后融合得到1个特征图谱。最后可得到所需的32个输出通道。
针对这个例子应用深度可分离卷积,用16个3×3大小的卷积核分别遍历16通道的数据,得到了16个特征图谱。在融合操作之前,接着用32个1×1大小的卷积核遍历这16个特征图谱,进行相加融合。这个过程使用了16×3×3+16×32×1×1=656个参数,远少于上面的16×32×3×3=4608个参数。
这个例子就是深度可分离卷积的具体操作,其中上面的深度乘数(depth multiplier)设为1,这也是目前这类网络层的通用参数。
这么做是为了对空间信息和深度信息进行去耦。从Xception模型的效果可以看出,这种方法是比较有效的。由于能够有效利用参数,因此深度可分离卷积也可以用于移动设备中。
src convolution
input output
M*N*Cin M*N*Cout
16*3*3*32
depthwise separable convolution
input output1 output2
M*N*Cin M*N*Cin M*N*Cout
16*3*3 16*32*1*1
另外一个地方看到的解释:
MobileNet-v1:
MobileNet主要用于移动端计算模型,是将传统的卷积操作改为两层的卷积操作,在保证准确率的条件下,计算时间减少为原来的1/9,计算参数减少为原来的1/7.
MobileNet模型的核心就是将原本标准的卷积操作因式分解成一个depthwise convolution和一个1*1的pointwise convolution操作。简单讲就是将原来一个卷积层分成两个卷积层,其中前面一个卷积层的每个filter都只跟input的每个channel进行卷积,然后后面一个卷积层则负责combining,即将上一层卷积的结果进行合并。
depthwise convolution:
比如输入的图片是Dk*Dk*M(Dk是图片大小,M是输入的渠道数),那么有M个Dw*Dw的卷积核,分别去跟M个渠道进行卷积,输出Df*Df*M结果
pointwise convolution:
对Df*Df*M进行卷积合并,有1*1*N的卷积,进行合并常规的卷积,输出Df*Df*N的结果
上面经过这两个卷积操作,从一个Dk*Dk*M=>Df*Df*N,相当于用Dw*Dw*N的卷积核进行常规卷积的结果,但计算量从原来的DF*DF*DK*DK*M*N减少为DF*DF*DK*DK*M+DF*DF*M*N.
第一层为常规卷积,后面接着都为depthwise convolution+pointwise convolution,最后两层为Pool层和全连接层,总共28层.
下面的代码是mobilenet的一个参数列表,计算的普通卷积与深度分离卷积的计算复杂程度比较
https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.py
# Tensorflow mandates these.
from collections import namedtuple
import functools import tensorflow as tf slim = tf.contrib.slim # Conv and DepthSepConv namedtuple define layers of the MobileNet architecture
# Conv defines 3x3 convolution layers
# DepthSepConv defines 3x3 depthwise convolution followed by 1x1 convolution.
# stride is the stride of the convolution
# depth is the number of channels or filters in a layer
Conv = namedtuple('Conv', ['kernel', 'stride', 'depth'])
DepthSepConv = namedtuple('DepthSepConv', ['kernel', 'stride', 'depth']) # _CONV_DEFS specifies the MobileNet body
_CONV_DEFS = [
Conv(kernel=[3, 3], stride=2, depth=32),
DepthSepConv(kernel=[3, 3], stride=1, depth=64),
DepthSepConv(kernel=[3, 3], stride=2, depth=128),
DepthSepConv(kernel=[3, 3], stride=1, depth=128),
DepthSepConv(kernel=[3, 3], stride=2, depth=256),
DepthSepConv(kernel=[3, 3], stride=1, depth=256),
DepthSepConv(kernel=[3, 3], stride=2, depth=512),
DepthSepConv(kernel=[3, 3], stride=1, depth=512),
DepthSepConv(kernel=[3, 3], stride=1, depth=512),
DepthSepConv(kernel=[3, 3], stride=1, depth=512),
DepthSepConv(kernel=[3, 3], stride=1, depth=512),
DepthSepConv(kernel=[3, 3], stride=1, depth=512),
DepthSepConv(kernel=[3, 3], stride=2, depth=1024),
DepthSepConv(kernel=[3, 3], stride=1, depth=1024)
] input_size = 160
inputdepth = 3
conv_defs = _CONV_DEFS
sumcost = 0
for i, conv_def in enumerate(conv_defs):
stride = conv_def.stride
kernel = conv_def.kernel
outdepth = conv_def.depth
output_size = round((input_size - int(kernel[0] / 2) * 2) / stride)
if isinstance(conv_def, Conv):
sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
if isinstance(conv_def, DepthSepConv):
sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
inputdepth = outdepth
input_size = output_size
print("src conv: ", sumcost) input_size = 160
inputdepth = 3
conv_defs = _CONV_DEFS
sumcost1 = 0
for i, conv_def in enumerate(conv_defs):
stride = conv_def.stride
kernel = conv_def.kernel
outdepth = conv_def.depth
output_size = round((input_size - int(kernel[0] / 2) * 2) / stride)
if isinstance(conv_def, Conv):
sumcost1 += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
if isinstance(conv_def, DepthSepConv):
#sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
sumcost1 += output_size * output_size *(inputdepth * kernel[0] * kernel[0] + inputdepth * outdepth * 1 * 1)
inputdepth = outdepth
input_size = output_size
print("DepthSepConv:", sumcost1)
print("compare:", sumcost1 / sumcost)
src conv: 1045417824
DepthSepConv: 126373376
compare: 0.12088312739538674
mobilenet V1介绍
https://www.cnblogs.com/darkknightzh/p/9410540.html
深度可分离卷积结构(depthwise separable convolution)计算复杂度分析的更多相关文章
- 深度可分卷积(Depthwise Separable Conv.)计算量分析
上次读到深度可分卷积还是去年暑假,各种细节都有些忘了.记录一下,特别是计算量的分析过程. 1. 标准卷积和深度可分卷积 标准卷积(MobileNet论文中称为Standard Convolution, ...
- Depthwise Separable Convolution(深度可分离卷积)的实现方式
按照普通卷积-深度卷积-深度可分离卷积的思路总结. depthwise_conv2d来源于深度可分离卷积,如下论文: Xception: Deep Learning with Depthwise Se ...
- 深度学习之depthwise separable convolution,计算量及参数量
目录: 1.什么是depthwise separable convolution? 2.分析计算量.flops 3.参数量 4.与传统卷积比较 5.reference
- 可分离卷积详解及计算量 Basic Introduction to Separable Convolutions
任何看过MobileNet架构的人都会遇到可分离卷积(separable convolutions)这个概念.但什么是“可分离卷积”,它与标准的卷积又有什么区别?可分离卷积主要有两种类型: 空间可分离 ...
- 『高性能模型』深度可分离卷积和MobileNet_v1
论文原址:MobileNets v1 TensorFlow实现:mobilenet_v1.py TensorFlow预训练模型:mobilenet_v1.md 一.深度可分离卷积 标准的卷积过程可以看 ...
- Paper | Xception: Deep Learning with Depthwise Separable Convolutions
目录 故事 Inception结构和思想 更进一步,以及现有的深度可分离卷积 Xception结构 实验 这篇论文写得很好.只要你知道卷积操作或公式,哪怕没看过Inception,也能看懂. 核心贡献 ...
- CNN中各类卷积总结:残差、shuffle、空洞卷积、变形卷积核、可分离卷积等
CNN从2012年的AlexNet发展至今,科学家们发明出各种各样的CNN模型,一个比一个深,一个比一个准确,一个比一个轻量.我下面会对近几年一些具有变革性的工作进行简单盘点,从这些充满革新性的工作中 ...
- Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1
3.Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1 http://blog.csdn.net/sunbow0 ...
- Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.2
3.Spark MLlib Deep Learning Convolution Neural Network(深度学习-卷积神经网络)3.2 http://blog.csdn.net/sunbow0 ...
随机推荐
- 具体解释java中的volatilekeyword
一.为什么要有volatilekeyword 预计非常多java刚開始学习的人都被volatile这个keyword迷惑过.尽管网上有非常多讨论volatile的文章,但它们有的过于讲述底层原理,而没 ...
- ubuntu16安装配置nginx
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev ...
- unity, 让主角头顶朝向等于地面法线(character align to surface normal)
计算过程如下: 1,通过由主角中心raycast一条竖直射线获得主角所在处地面法线,用作主角的newUp. 注:一定要从主角中心raycast,而不要从player.transform.positio ...
- HTML: < 和 > 是何方神圣
懂HTML的,都知道 < 表示 <,> 表示 >,那还有什么好写呢? 知道是知道,记不记得住是另外一回事,今天用到这两家伙,又给忘记了,还要特意查了下. 缩写不好记,如果能知道 ...
- 安装perl的版本控制器perlbrew
perlbrew可以用源码方式安装perl的各种版本,可以容纳多个perl版本共存,并随意切换. 1.把perlbrew安装到home目录: curl -L https://install.perlb ...
- IP首部
1. 引言 IP是TCP/IP协议族中最为核心的协议.所有的TCP.UDP.ICMP及IGMP数据都以IP数据报格式传输,但是IP提供不可靠.无连接的数据报传送服务.不可靠的意思是它不能保证IP数据报 ...
- Volley 解析
Volley Request处理流程 RequestQueue类中有三个基本的队列.调用RequestQueue.add(request)增加的请求会先增加mCacheQueue(优先级堵塞队列)由C ...
- C_文件包含.h文件和包含.c文件总结
很多人对C语言中的 “文件包含”都不陌生了,文件包含处理在程序开发中会给我们的模块化程序设计带来很大的好处,通过文件包含的方法把程序中的各个功能模块联系起来是模块化程序设计中的一种非常有利的手段. 文 ...
- npm 的指令介绍
npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...
- rman备份,恢复
ackup database format 'd:\tt\%U'; rman> restore database;rman> recover database; ============= ...