(一)函数简介
conv2d(input,filter,strides,padding,use_cudnn_on=True,data_format='NHWC',name=None)
1.参数:
input
:一个half或者float32类型的tensor,shape为4-D,[batches,filter_height,filter_width,in_channels]
,[训练时一组图片的数量,图片高度,图片宽度,图像通道数1],filter
: 相当于CNN中的卷积核, 必须和input
同类型,一个4-D的tensor,[filter_height,filter_width,in_channels,out_channels]
,in_channels
同input
中的in_channels
,strides
: 长度为4的1-D的tensor,卷积时在input
tensor上每一维的步长。padding
: 一个字符串,SAME
或者VALID
,卷积的类型,决定是否包含边,其值为SAME
时卷积核可以包含边,但会涉及图片的边界扩充的问题,后面解释。use_cudnn_on_gpu
: 布尔值,决定是否使用GPU加速。data_format
: 一个字符串,为“NHWC”或者“NCHW”,缺省值为“NHWC”,说明输入输出数据的格式。name
: op的名字
(二)用法:
1.计算
- 根据指定的4-D
input
和filter
tensors计算2-D的卷积,输入tensor的shape为,
[batch,in_height,in_width,in_channels]
[filter_height,filter_width,in_channels,out_channels]
计算过程如下:
- 把filter转换成shape为
[filter_height*filter_width*inchannels,output_channels]
的2-D的矩阵 - 将输入tensor中的图像组转码成virtual tensor,此tensor的shape为
[batch,out_height,out_width,filter_height*filter_width*in_channels]
. - 将上述两矩阵相乘,virtual tensor*2-D filter.
- 返回值是一个4-D的tensor.
- 把filter转换成shape为
2.图像卷积
(1)概述
卷积操作使用2-D滤波器在一组图像上进行扫描,将滤波器应用到每个适当大小的图像的窗口上3。不同的卷积操作在泛型和特殊的滤波器中进行选择:
- conv2d
:可以混合通道的任意滤波器。
- depthwise_conv2d
:分别在每个通道上独立进行卷积的滤波器。
- separable_conv2d
:深度空间滤波器,配合逐点滤波器使用。
(2)padding参数与输出feature map的大小
先不考虑通道数,假设4-D的input
tensor的shape为[batch,in_height,in_width,...]
,4-D的filter的shape为[filter_height,filter_width,...]
,卷积操作的空间特性取决图像的扩充方案,也就是padding
参数的取值是SAME
还是VALID
,图像扩充的值都是0.
— padding=SAME
关于此的详细资料见2.这里只简单总结一下这种扩充方案的机制。padding
的值为SAME
时,输出特征图的宽和高计算方式如下:
out_height = cell(float(in_height)/ float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
在输入图像的宽度和高度方向的整体扩充方式如下:
if (in_height % strides[1] == 0):
pad_along_height = max(filter_height - strides[1], 0)
else:
pad_along_height = max(filter_height - (in_height % strides[1]), 0)
if (in_width % strides[2] == 0):
pad_along_width = max(filter_width - strides[2], 0)
else:
pad_along_width = max(filter_width - (in_width % strides[2]), 0)
写成表达式为:
- pi :需要扩充的像素个数
- k :卷积核的大小
s :卷积核移动的步长- ni :输入的图像大小
最后在输入图像上下左右四个方向上要扩充的大小为:
pad_top = pad_along_height // 2
pad_bottom = pad_along_height - pad_top
pad_left = pad_along_width // 2
pad_right = pad_along_width - pad_left
可能会有pad_along_height
和pad_along_width
为奇数的情况,当出现这种情况时,习惯于把多余的那个扩充像素加到图像的下边和右边。例如,如果pad_along_height=5
,就是上面扩充2个像素,下面扩充3个像素。
— padding=VALID
图像不进行扩充,输出的feature map
的大小计算方式如下:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
Reference
1http://blog.csdn.net/farmwang/article/details/48102915
2https://www.tensorflow.org/api_guides/python/nn#Notes_on_SAME_Convolution_Padding
3https://www.tensorflow.org/api_guides/python/nn#Convolution