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

  1. # Tensorflow mandates these.
  2. from collections import namedtuple
  3. import functools
  4.  
  5. import tensorflow as tf
  6.  
  7. slim = tf.contrib.slim
  8.  
  9. # Conv and DepthSepConv namedtuple define layers of the MobileNet architecture
  10. # Conv defines 3x3 convolution layers
  11. # DepthSepConv defines 3x3 depthwise convolution followed by 1x1 convolution.
  12. # stride is the stride of the convolution
  13. # depth is the number of channels or filters in a layer
  14. Conv = namedtuple('Conv', ['kernel', 'stride', 'depth'])
  15. DepthSepConv = namedtuple('DepthSepConv', ['kernel', 'stride', 'depth'])
  16.  
  17. # _CONV_DEFS specifies the MobileNet body
  18. _CONV_DEFS = [
  19. Conv(kernel=[3, 3], stride=2, depth=32),
  20. DepthSepConv(kernel=[3, 3], stride=1, depth=64),
  21. DepthSepConv(kernel=[3, 3], stride=2, depth=128),
  22. DepthSepConv(kernel=[3, 3], stride=1, depth=128),
  23. DepthSepConv(kernel=[3, 3], stride=2, depth=256),
  24. DepthSepConv(kernel=[3, 3], stride=1, depth=256),
  25. DepthSepConv(kernel=[3, 3], stride=2, depth=512),
  26. DepthSepConv(kernel=[3, 3], stride=1, depth=512),
  27. DepthSepConv(kernel=[3, 3], stride=1, depth=512),
  28. DepthSepConv(kernel=[3, 3], stride=1, depth=512),
  29. DepthSepConv(kernel=[3, 3], stride=1, depth=512),
  30. DepthSepConv(kernel=[3, 3], stride=1, depth=512),
  31. DepthSepConv(kernel=[3, 3], stride=2, depth=1024),
  32. DepthSepConv(kernel=[3, 3], stride=1, depth=1024)
  33. ]
  34.  
  35. input_size = 160
  36. inputdepth = 3
  37. conv_defs = _CONV_DEFS
  38. sumcost = 0
  39. for i, conv_def in enumerate(conv_defs):
  40. stride = conv_def.stride
  41. kernel = conv_def.kernel
  42. outdepth = conv_def.depth
  43. output_size = round((input_size - int(kernel[0] / 2) * 2) / stride)
  44. if isinstance(conv_def, Conv):
  45. sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
  46. if isinstance(conv_def, DepthSepConv):
  47. sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
  48. inputdepth = outdepth
  49. input_size = output_size
  50. print("src conv: ", sumcost)
  51.  
  52. input_size = 160
  53. inputdepth = 3
  54. conv_defs = _CONV_DEFS
  55. sumcost1 = 0
  56. for i, conv_def in enumerate(conv_defs):
  57. stride = conv_def.stride
  58. kernel = conv_def.kernel
  59. outdepth = conv_def.depth
  60. output_size = round((input_size - int(kernel[0] / 2) * 2) / stride)
  61. if isinstance(conv_def, Conv):
  62. sumcost1 += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
  63. if isinstance(conv_def, DepthSepConv):
  64. #sumcost += output_size * output_size * kernel[0] * kernel[0] * inputdepth * outdepth
  65. sumcost1 += output_size * output_size *(inputdepth * kernel[0] * kernel[0] + inputdepth * outdepth * 1 * 1)
  66. inputdepth = outdepth
  67. input_size = output_size
  68. print("DepthSepConv:", sumcost1)
  69. 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)计算复杂度分析的更多相关文章

  1. 深度可分卷积(Depthwise Separable Conv.)计算量分析

    上次读到深度可分卷积还是去年暑假,各种细节都有些忘了.记录一下,特别是计算量的分析过程. 1. 标准卷积和深度可分卷积 标准卷积(MobileNet论文中称为Standard Convolution, ...

  2. Depthwise Separable Convolution(深度可分离卷积)的实现方式

    按照普通卷积-深度卷积-深度可分离卷积的思路总结. depthwise_conv2d来源于深度可分离卷积,如下论文: Xception: Deep Learning with Depthwise Se ...

  3. 深度学习之depthwise separable convolution,计算量及参数量

    目录: 1.什么是depthwise separable convolution? 2.分析计算量.flops 3.参数量 4.与传统卷积比较 5.reference

  4. 可分离卷积详解及计算量 Basic Introduction to Separable Convolutions

    任何看过MobileNet架构的人都会遇到可分离卷积(separable convolutions)这个概念.但什么是“可分离卷积”,它与标准的卷积又有什么区别?可分离卷积主要有两种类型: 空间可分离 ...

  5. 『高性能模型』深度可分离卷积和MobileNet_v1

    论文原址:MobileNets v1 TensorFlow实现:mobilenet_v1.py TensorFlow预训练模型:mobilenet_v1.md 一.深度可分离卷积 标准的卷积过程可以看 ...

  6. Paper | Xception: Deep Learning with Depthwise Separable Convolutions

    目录 故事 Inception结构和思想 更进一步,以及现有的深度可分离卷积 Xception结构 实验 这篇论文写得很好.只要你知道卷积操作或公式,哪怕没看过Inception,也能看懂. 核心贡献 ...

  7. CNN中各类卷积总结:残差、shuffle、空洞卷积、变形卷积核、可分离卷积等

    CNN从2012年的AlexNet发展至今,科学家们发明出各种各样的CNN模型,一个比一个深,一个比一个准确,一个比一个轻量.我下面会对近几年一些具有变革性的工作进行简单盘点,从这些充满革新性的工作中 ...

  8. Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1

    3.Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1 http://blog.csdn.net/sunbow0 ...

  9. Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.2

    3.Spark MLlib Deep Learning Convolution Neural Network(深度学习-卷积神经网络)3.2 http://blog.csdn.net/sunbow0 ...

随机推荐

  1. CodeForces 445B. DZY Loves Chemistry(并查集)

    转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://codeforces.com/problemset/prob ...

  2. Android-SQLiteOpenHelper

    Android-SQLiteOpenHelper 一 概念 是对SOLiteDatabase的封装.主要用于建立和版本号控制,方便我们去建立库表结构 二 用法 又一次封装一个MySqliteOpenH ...

  3. puppeteer (Nodejs版selenium )快速入门

    官网 https://pptr.dev/ api 与 教程: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.mdhttp ...

  4. unity 在Game视图中显示Gizmos

    自己画的Gizmos要想在Game视图中能看到,需要把Game视图窗口右上角的"Gizmos"按钮点下去.如图: 比如,下面代码以角色的capsuleCollider中心为中心画一 ...

  5. HTML5游戏实战之精灵翻转

    要实现精灵的翻转.很easy.先看实际效果点这里. 代码仅仅有区区几行: var sp = this.getWindow().find("ui-status2-general"); ...

  6. 认识k_BackingField,微软自己的序列化和反序列化

    事情从Json的序列化和反序列化说起. 在C#2.0的项目中,以前经常使用Json.Net实现序列化和反序列化.后来从c#3.0中开始使用新增的DataContractJsonSerializer进行 ...

  7. Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(3)

    Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(3) 一.配置共享存储 [oracle@aix203 ~]$lsdev -c disk hdisk0 Available ...

  8. Linux系统cp: omitting directory `XXX'问题解决

    在linux系统中复制文件夹时提示如下: cp: omitting directory `foldera/' 其中foldera是我要复制的文件夹名,出现该警告的原因是因为foldera目录下还存在目 ...

  9. C++虚函数表与虚析构函数

    1.静态联编和动态联编联编:将源代码中的函数调用解释为要执行函数代码. 静态联编:编译时能确定唯一函数.在C中,每个函数名都能确定唯一的函数代码.在C++中,因为有函数重载,编译器须根据函数名,参数才 ...

  10. MySQL通过视图(或临时表)实现动态SQL(游标)

    >参考de优秀文章 写MySQL存储过程实现动态执行SQL Dynamic cursor in stored procedure MySQL通过视图(或临时表)实现动态SQL(游标). 因在实现 ...