def depthwise_conv2d(
input,
filter,
strides,
padding,
rate=None, # 意思同conv的dilation,但是只有两个元素的list,[x,y]
name=None,
data_format=None
)
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)
忽略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
前提是在函数定义里有一个这样的说明:
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ㄒ)/~~