tf.nn.depthwise_conv2d()使用

1、函数定义 

def depthwise_conv2d(
input,
filter,
strides,
padding,
rate=None,  # 意思同conv的dilation,但是只有两个元素的list,[x,y]
name=None,
data_format=None
)

2、参数说明

2.1 depthwise_conv2d的参数与conv2d基本一致,只是操作略有不同,最好先了解conv2d:tf.nn.conv2d()

参数特别说明:

1) strides:当前实现仅支持strides_x = strides_y, 否则会报错:InvalidArgumentError (see above for traceback): Current implementation only supports equal length strides in the row and column dimensions.

2)rate:空洞率,即膨胀系数,但是size不同,dilation[1,h,w,1],rate是[h,w]。

PS:我这里解释膨胀系数为把filter缩放,放大部分用0填充。关于rate还有另一种理解(即间隔采用):https://blog.csdn.net/qq_38675570/article/details/81239774 by开心95

2.2 depthwise_conv2d深度卷积,与conv2d的不同,主要表现在conv操作中 Tensor各channel的filter滑窗 与filter卷积结果是相加的,得到的是一个点(标量),而depthwise_conv2d中,Tensor中各channel的filter浮窗 与filter卷积结果相互独立,不想加。如例:

in_size = [1, 24, 24, 3]
filter = [4, 4, 3, 4]
a = tf.nn.conv2d(
    input=np.random.random(in_size),
    filter=np.random.random(filter),
    strides=[1, 1, 1, 1],
    padding='VALID',
    use_cudnn_on_gpu=True,
    data_format="NHWC",
    dilations=[1, 1, 1, 1],
    name=None
)
b = tf.nn.depthwise_conv2d(input=np.random.random(in_size),
                     filter=np.random.random(filter),
                     strides=[1, 1, 1, 1],
                     padding='VALID',
                     rate=None,
                     name=None,
                     data_format=None
)

print(a)
print(b)
================================================================== output
Tensor("Conv2D:0", shape=(1, 21, 21, 4), dtype=float64)
Tensor("depthwise:0", shape=(1, 21, 21, 12), dtype=float64)

3、图解conv2d和depthwise-conv2d的不同

忽略batch,只针对height,width,channel

假设Tensor【batch, height, width, in_channel】,filter【f_h, f_w, in_channel, out_channel】

3.1 conv2d:结果Tensor的 channel = out_channel

3.2 depthwise_conv2d: 结果Tensor的channel = in_channel * out_channel

4、问题请教

前提是在函数定义里有一个这样的说明:

If any value in `rate` is greater than 1, we perform atrous depthwise
convolution, in which case all values in the `strides` tensor must be equal
to 1.

网络查询时看到:现有的框架都要求dilation_rate>1时,strides不能>1,也就是strides =1时,才能进行膨胀卷积操作。但是我就是很好奇,就是了一下rate>1,strides>1, tensorflow支持计算,但是结果shape的宽和高跟conv不一样!! 这真的,我太好奇了!!谁知道为什么这样?或者为什么有这样的规定,原因出自什么理论? 希望有大神看到帮忙解答一下疑惑,多谢~~~~~

in_size = [1, 24, 24, 3]
filter = [4, 4, 3, 4]
a = tf.nn.conv2d(
    input=np.random.random(in_size),
    filter=np.random.random(filter),
    strides=[1, 4, 4, 1],
    padding='VALID',
    use_cudnn_on_gpu=True,
    data_format="NHWC",
    dilations=[1, 3, 3, 1],
    name=None
)
b = tf.nn.depthwise_conv2d(input=np.random.random(in_size),
                     filter=np.random.random(filter),
                     strides=[1, 4, 4, 1],
                     padding='VALID',
                     rate=[3, 3],
                     name=None,
                     data_format="NHWC",
)
print(a)
print(b)

【anwser1】rate要求是一个int型的正数,正常的卷积操作应该会有stride(即卷积核的滑动步长),但是空洞卷积是没有stride参数的,这一点尤其要注意。取而代之,它使用了新的rate参数,那么rate参数有什么用呢?它定义为我们在输入图像上卷积时的采样间隔,你可以理解为卷积核当中穿插了(rate-1)数量的“0”,把原来的卷积核插出了很多“洞洞”,这样做卷积时就相当于对原图像的采样间隔变大了。by just_sort

【疑惑】虽然知道是这样,但是还是好奇,如果空洞卷积是这样定义的,那么我在设置rate>1,且strides>1时,不就有问题吗,为什么不报个错或者提示??如果这样可以推理,那结果又为什么跟conv2d的不一样??这个问题我会持续关注/(ㄒoㄒ)/~~


版权声明:本文为zmj1582188592原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。