zoukankan      html  css  js  c++  java
  • 【Tensorflow】tf.nn.atrous_conv2d如何实现空洞卷积?膨胀卷积

    介绍
    关于空洞卷积的理论可以查看以下链接,这里我们不详细讲理论:

    1.Long J, Shelhamer E, Darrell T, et al. Fully convolutional networks for semantic segmentation[C]. Computer Vision and Pattern Recognition, 2015.

    2.Yu, Fisher, and Vladlen Koltun. “Multi-scale context aggregation by dilated convolutions.” arXiv preprint arXiv:1511.07122 (2015).

    3.如何理解空洞卷积(dilated convolution)?

    其实用一句话概括就是,在不用pooling的情况下扩大感受野(pooling层会导致信息损失)

    为了阅读方便再贴一些相关链接:

    【TensorFlow】tf.nn.conv2d是怎样实现卷积的?

    【TensorFlow】tf.nn.conv2d_transpose是怎样实现反卷积的?

    惯例先展示函数:

    tf.nn.atrous_conv2d(value,filters,rate,padding,name=None)
    1
    除去name参数用以指定该操作的name,与方法有关的一共四个参数:

    value:
    指需要做卷积的输入图像,要求是一个4维Tensor,具有[batch, height, width, channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数]

    filters:
    相当于CNN中的卷积核,要求是一个4维Tensor,具有[filter_height, filter_width, channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],同理这里第三维channels,就是参数value的第四维

    rate:
    要求是一个int型的正数,正常的卷积操作应该会有stride(即卷积核的滑动步长),但是空洞卷积是没有stride参数的,这一点尤其要注意。取而代之,它使用了新的rate参数,那么rate参数有什么用呢?它定义为我们在输入图像上卷积时的采样间隔,你可以理解为卷积核当中穿插了(rate-1)数量的“0”,把原来的卷积核插出了很多“洞洞”,这样做卷积时就相当于对原图像的采样间隔变大了。具体怎么插得,可以看后面更加详细的描述。此时我们很容易得出rate=1时,就没有0插入,此时这个函数就变成了普通卷积。

    padding:
    string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同边缘填充方式。

    ok,完了,到这就没有参数了,或许有的小伙伴会问那“stride”参数呢。其实这个函数已经默认了stride=1,也就是滑动步长无法改变,固定为1。

    结果返回一个Tensor,填充方式为“VALID”时,返回[batch,height-2*(filter_width-1),width-2*(filter_height-1),out_channels]的Tensor,填充方式为“SAME”时,返回[batch, height, width, out_channels]的Tensor,这个结果怎么得出来的?先不急,我们通过一段程序形象的演示一下空洞卷积。

    实验
    首先创建一张2通道图

    img = tf.constant(value=[[[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]]]],dtype=tf.float32)
    img = tf.concat(values=[img,img],axis=3)
    1
    2
    然后用一个3*3卷积核去做卷积

    filter = tf.constant(value=1, shape=[3,3,2,5], dtype=tf.float32)
    out_img = tf.nn.atrous_conv2d(value=img, filters=filter, rate=1)
    1
    2
    建立好了img和filter,就可以做卷积了

    out_img = tf.nn.conv2d(input=img, filter=filter, strides=[1,1,1,1], padding='VALID')
    1
    输出5个channel,我们设置rate=1,此时空洞卷积可以看做普通的卷积,分别在SAME和VALID模式下输出如下:

    ok,调整rate=2,继续运行程序

    out_img = tf.nn.atrous_conv2d(value=img, filters=filter, rate=2, padding='SAME')
    1
    查看输出结果

    [[[[ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]
    [ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]]

    [[ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]
    [ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]]

    [[ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]
    [ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]]

    [[ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]
    [ 16. 16. 16. 16. 16.]
    [ 24. 24. 24. 24. 24.]]]]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    这个结果怎么出来的呢?再用一张图


    这里我们看到rate=2时,通过穿插“0”,卷积核由3*3膨胀到了5*5。再看看“VALID”模式下,会发生什么?

    直接报错了。因为卷积核的大小已经超过了原图大小

    好了,看到这里相信大家对于空洞卷积有了基本的了解了。那么,填充方式为“VALID”时,返回[batch,height-2*(filter_width-1),width-2*(filter_height-1),out_channels]的Tensor,这个结果,相信大家就可以证明了。

    代码清单
    import tensorflow as tf


    img = tf.constant(value=[[[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]],[[1],[2],[3],[4]]]],dtype=tf.float32)
    img = tf.concat(values=[img,img],axis=3)
    filter = tf.constant(value=1, shape=[3,3,2,5], dtype=tf.float32)
    out_img1 = tf.nn.atrous_conv2d(value=img, filters=filter, rate=1, padding='SAME')
    out_img2 = tf.nn.atrous_conv2d(value=img, filters=filter, rate=1, padding='VALID')
    out_img3 = tf.nn.atrous_conv2d(value=img, filters=filter, rate=2, padding='SAME')

    #error
    #out_img4 = tf.nn.atrous_conv2d(value=img, filters=filter, rate=2, padding='VALID')

    with tf.Session() as sess:
    print 'rate=1, SAME mode result:'
    print(sess.run(out_img1))

    print 'rate=1, VALID mode result:'
    print(sess.run(out_img2))

    print 'rate=2, SAME mode result:'
    print(sess.run(out_img3))

    # error
    #print 'rate=2, VALID mode result:'
    #print(sess.run(out_img4))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    TensorFlow实现卷积、反卷积和空洞卷积
    阅读数 1532

    TensorFlow实现卷积、反卷积和空洞卷积TensorFlow已经实现了卷积(tf.nn.conv2d卷积函数),反卷积(tf.nn.conv2d_transpose反卷积函数)以及空洞卷积(tf...
    博文
    来自: pan_jinquan的博客


    wsdgh: Nice, but `height - [filter_width + (filter_width - 1) * (rate - 1)] + 1` make more sense, when `padding=VALID`.
    import tensorflow as tf
    import numpy as np

    kernel_height = 3
    kernel_width = kernel_height

    img_height = 9
    img_width = img_height
    rate = 2
    padding = 'VALID'
    sz_same = img_height
    sz_valid = img_height - ((kernel_height - 1)*(rate - 1) + kernel_height) + 1

    img = np.random.randn(1, img_height, img_width, 3)
    kernel = np.random.randn(kernel_height, kernel_width, 3, 1)

    imgT = tf.constant(img)
    kernelT = tf.constant(kernel)

    imgO1 = tf.nn.atrous_conv2d(imgT, kernel, rate=rate, padding=padding)
    print(imgO1.shape)
    print(sz_same if padding.upper() == 'SAME' else sz_valid)
    # (1, 5, 5, 1)
    # 5

    ---------------------
    作者:xf__mao
    来源:CSDN
    原文:https://blog.csdn.net/mao_xiao_feng/article/details/78003730
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    设计模式学习总结系列应用实例
    【研究课题】高校特殊学生的发现及培养机制研究
    Linux下Oracle11G RAC报错:在安装oracle软件时报file not found一例
    python pro practice
    openstack python sdk list tenants get token get servers
    openstack api
    python
    git for windows
    openstack api users list get token get servers
    linux 流量监控
  • 原文地址:https://www.cnblogs.com/jfdwd/p/11184384.html
Copyright © 2011-2022 走看看