tf.nn.conv2d()函数理解

4.tf.nn.conv2d

f.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None) 
input:输入图像,是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一

filter:滤波器,就是卷积的权重,是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维

strides:卷积步长,这是一个一维的向量,长度4

padding:string类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式

use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true

输出类型和输入类型一样,得到feature map,是一个tensor,shape是[batch, in_height, in_width, out_channels]

卷积前后图片大小计算公式:

输出图片的边长N为:

N = (W - F + 2P)/S + 1
其中:
输入图片大小 W
卷积核大小 F
卷积核移动步长 S
零填充的像素数 P

(1)strides是一个1维向量,长度为4。A list of ints.1-Dtensor of length 4.The stride of the sliding window for each dimension of input.

意思就是,这个stride中的 每一项代表输入tensor上的一个维度。我们输入数据[batch, in_height, in_width, in_channels],共4维,说明这里使用的stride必须是4维的。因为第一维是图像的数量,最后一维是通道数,所以这两个维度必须是1,也就是说,strides[0]=strides[3]=1,至于中间的2维-长度和宽度,则根据需要可以选择不同的值。最终格式就是:[1,stride,stride,1]

(2)padding可以选择VALID,SAME。

  • 首先考虑VALID,这个意思就是说,程序按照指定的滤波器和步长进行滑动卷积,当出现剩余的像素值不够滤波器进行一次卷积时,就舍弃剩余所有像素。如下图所示:

如图所示输入像是1*10*10*1,filter大小是3*3*1*1,步长strides=[1,3,3,1],根据公式(10-3)/3=3,所以最终图像大小是3*3*1,操作中去掉了最右边和最下边一行像素,因为它不够3*3滤波器进行一次卷积。

总结:padding为VALID模式时,很简单粗暴直接从原始图像的首段开始卷积,到最后不能匹配卷积核的部分直接舍去。

  • 当padding=SAME时,处理方式与VALID有所不同,对于一个维度不够像素时,会进行填充0处理。至于如何填充,有两种情况。

情况一:相差偶数个元素时,比如一个10*10的图像使用3*3滤波器,以步长为3进行卷积,到了最后还剩1行(列)元素,也就是说还差2行元素,系统默认在整个图像的前后(左右)填充0;如果相差4个元素,就前后各加2个元素。已达到平均的目的。

最终输出4*4大小的图像(根据公式(10-3+2*2)/3+1=4)。

情况二:相差奇数个元素,比如一个11*11的图像使用3*3滤波器,以步长为3进行卷积,到了最后还剩2行(列)元素,也就是说还差1行元素,系统会在整个图像的前面(左边)填充0;如果相差3个元素,就前面加2个0元素,后面加1个0元素。

(输入图像是11*11,还相差1个元素,加在维度的前面(第一行,第一列),最终得到的还是4*4大小的图像。根据公式(10-3+2*1)/3+1=4)

总结:当padding为SAME时,系统会对图形进行填充0处理,不会舍弃任何一个元素。当相差偶数个元素时,在图像每一维的前面和后边添加各一般的0填充;当相差奇数个元素时,总是保持前面比后面多填充一个0元素。

猜你喜欢

转载自blog.csdn.net/ifreewolf_csdn/article/details/88934681
今日推荐