zoukankan      html  css  js  c++  java
  • Depthwise Separable Convolution(深度可分离卷积)的实现方式

    按照普通卷积-深度卷积-深度可分离卷积的思路总结。

    depthwise_conv2d来源于深度可分离卷积,如下论文:

    Xception: Deep Learning with Depthwise Separable Convolutions

    函数定义如下:

    tf.nn.depthwise_conv2d(input,filter,strides,padding,rate=None,name=None,data_format=None)

    除去name参数用以指定该操作的name,data_format指定数据格式,与方法有关的一共五个参数:

    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:
    这个参数的详细解释见【Tensorflow】tf.nn.atrous_conv2d如何实现空洞卷积?

    结果返回一个Tensor,shape为[batch, out_height, out_width, in_channels * channel_multiplier],注意这里输出通道变成了in_channels * channel_multiplier
    自定义卷积信息做实例:

    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')

    普通卷积的实现过程如下系列图:

    做深度卷积:

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

     

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

     如下,增加定义了point_filter 核。

    import tensorflow as tf
    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)

    point_filter = tf.constant(value=1, shape=[1,1,4,4],dtype=tf.float32)
    out_img = tf.nn.depthwise_conv2d(input=img, filter=filter, strides=[1,1,1,1],rate=[1,1], padding='VALID')
    做深度分层卷积=做深度卷积,然后做pointwise卷积,因此在上代码添加做pointwise卷积代码即可完成,如下:

    out_img = tf.nn.conv2d(input=out_img, filter=point_filter, strides=[1,1,1,1], padding='VALID')

    输出:

    使用官方函数编码查看结果,即:

    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')
    输出:

    ok,愉快地结束。

  • 相关阅读:
    leetcode 287 寻找重复数
    739 每日温度 && 单调栈算法的思路
    leetcode 34 在排序数组中查找元素的第一个和最后一个位置
    leetcode 239 滑动窗口最大值
    leetcode 114 二叉树展开为链表
    leetcode 79 单词搜索
    leetcode 88 合并两个有序数组
    函数指针 & 指针函数
    leetcode 240 搜索二维矩阵
    谱聚类
  • 原文地址:https://www.cnblogs.com/HYWZ36/p/11403230.html
Copyright © 2011-2022 走看看