TensorFlow实现深度可分离卷积

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MOU_IT/article/details/82713232

1、tf.nn.depthwise_conv2d(input,filter,strides,padding,rate=None,name=None,data_format=None):深度可分离卷积

  参数:

    input: 指需要做卷积的输入图像,要求是一个4维Tensor,具有[batch, height, width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数]
    filter: 相当于CNN中的卷积核,要求是一个4维Tensor,具有[filter_height, filter_width, in_channels, channel_multiplier]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,输入通道数,输出卷积乘子],同理这里第三维in_channels,就是参数value的第四维
    strides: 卷积的滑动步长。
    padding: string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同边缘填充方式。
    rate: 这里的rate和空洞卷积中的rate作用相同

    给定4D输入张量('NHWC'或'NCHW'数据格式)和形状为[filter_height,filter_width,in_channels,channel_multiplier]的卷积核(卷积核包含in_channels个深度为1的卷积核),depthwise_conv2d对每个输入通道应用不同的卷积核(对于每个通道卷积后的结果,从1个通道扩展到channel_multiplier个通道,然后将结果连接在一起。输出具有in_channels * channel_multiplier通道。

2、tf.nn.separable_conv2d(input,depthwise_filter,pointwise_filter,strides,padding,rate=None,name=None,data_format=None)

  可以看做,深度卷积tf.nn.depthwise_conv2d的扩展,除去name参数用以指定该操作的name,data_format指定数据格式,与方法有关的一共六个参数:
    input: 指需要做卷积的输入图像,要求是一个4维Tensor,具有[batch, height, width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数]
    depthwise_filter: 用来做depthwise_conv2d的卷积核,也就是说这个函数对输入首先做了一个深度卷积。它的shape规定是[filter_height, filter_width, in_channels, channel_multiplier]
    pointwise_filter: 用来做pointwise卷积的卷积核,什么是pointwise卷积呢?我们可以把它和GoogLeNet最原始版本Inception结构中后面的1*1卷积核做channel降维来做对比,这里也是用1*1的卷积核,输入通道是depthwise_conv2d的输出通道也就是in_channels * channel_multiplier,输出通道数可以自己定义。depthwise_conv2d是对输入图像的每一个channel分别做卷积输出的,那么这个操作我们可以看做是将深度卷积得到的分离的各个channel的信息做一个融合。它的shape规定是[1, 1, channel_multiplier * in_channels, out_channels]
    strides: 卷积的滑动步长。
    padding: string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同边缘填充方式。
    rate:这里的rate和空洞卷积中的rate作用相同

  图解如下:

    举例来说,假设输入通道数64,输出通道数64,传统的Conv2D方法的参数数量为3*3*64*64;而SeparableConv2D的参数数量为3*3*64+1*1*64*64。3*3*64:对输入的64个通道分别进行卷积 ,1*1*64*64对concat后的64个通道进行1*1卷积(pointwise Convolution)。

  实验: 

img1 = tf.constant(value=[[[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]]]],dtype=tf.float32)
img2 = tf.constant(value=[[[[1],[1],[1],[1]],[[1],[1],[1],[1]],[[1],[1],[1],[1]],[[1],[1],[1],[1]]]],dtype=tf.float32)
img = tf.concat(values=[img1,img2],axis=3)
filter1 = tf.constant(value=0, shape=[3,3,1,1],dtype=tf.float32)
filter2 = tf.constant(value=1, shape=[3,3,1,1],dtype=tf.float32)
filter3 = tf.constant(value=2, shape=[3,3,1,1],dtype=tf.float32)
filter4 = tf.constant(value=3, shape=[3,3,1,1],dtype=tf.float32)
filter_out1 = tf.concat(values=[filter1,filter2],axis=2)
filter_out2 = tf.concat(values=[filter3,filter4],axis=2)
filter = tf.concat(values=[filter_out1,filter_out2],axis=3)
# 这里为普通卷积
out_img = tf.nn.conv2d(input=img, filter=filter, strides=[1,1,1,1], padding='VALID')

输出:
[[[[ 9. 63.]
   [ 9. 81.]]
  [[ 9. 63.]
   [ 9. 81.]]]]

好了,用一张图来详细展示这个过程(普通卷积) :

 

 这是普通的卷积过程,我们再来看深度卷积。

out_img = tf.nn.depthwise_conv2d(input=img, filter=filter, strides=[1,1,1,1], rate=[1,1], padding='VALID')

输出:
[[[[ 0. 36.  9. 27.]
   [ 0. 54.  9. 27.]]
  [[ 0. 36.  9. 27.]
   [ 0. 54.  9. 27.]]]]

 

    现在我们可以形象的解释一下depthwise_conv2d卷积了。看普通的卷积,我们对卷积核每一个out_channel的两个通道分别和输入的两个通道做卷积相加,得到feature map的一个channel,而depthwise_conv2d卷积,我们对每一个对应的in_channel,分别卷积生成两个out_channel,所以获得的feature map的通道数量可以用in_channel* channel_multiplier来表达,这个channel_multiplier,就可以理解为卷积核的第四维。 

  我们对这个结果做pointwise卷积:

point_filter = tf.constant(value=1, shape=[1,1,4,4],dtype=tf.float32)  
out_img = tf.nn.conv2d(input=out_img, filter=point_filter, strides=[1,1,1,1], padding='VALID')

输出:
[[[[72. 72. 72. 72.]
   [90. 90. 90. 90.]]
  [[72. 72. 72. 72.]
   [90. 90. 90. 90.]]]]

  现在我们用tf.nn.separable_conv2d来代替上面的两部操作:  

out_img = tf.nn.separable_conv2d(input=img, depthwise_filter=filter, pointwise_filter=point_filter,strides=[1,1,1,1], rate=[1,1], padding='VALID')  

输出:
[[[[72. 72. 72. 72.]
   [90. 90. 90. 90.]]
  [[72. 72. 72. 72.]
   [90. 90. 90. 90.]]]]

参考:https://blog.csdn.net/mao_xiao_feng/article/details/78003476

           https://blog.csdn.net/mao_xiao_feng/article/details/78002811

           https://www.cnblogs.com/ranjiewen/p/9278631.html

           https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d

猜你喜欢

转载自blog.csdn.net/MOU_IT/article/details/82713232