转载请标明出处:http://blog.csdn.net/wuzqchom/article/details/74785643
在用tensorflow调用卷积核api的时候,会有填padding方式的参数,找到源码中的函数定义如下(max pooling
也是一样):
def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None,
data_format=None, name=None)
源码中对于padding
参数的说明如下:
padding: A `string` from: `"SAME", "VALID"`.
The type of padding algorithm to use.
源码中说明padding
可以用SAME
和VALID
两种方式,但是对于这两种方式具体是什么并没有多加说明。
这里用Stack Overflow中的一份代码来简单解释一下,代码如下:
import tensorflow as tf
x = tf.constant([[1., 2., 3.],
[4., 5., 6.]])
x = tf.reshape(x, [1, 2, 3, 1]) # give a shape accepted by tf.nn.max_pool
valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
print(valid_pad.get_shape())
print(same_pad.get_shape())
最后输出的结果为:
(1, 1, 1, 1)
(1, 1, 2, 1)
可以看出SAME
的填充方式是比VALID
的填充方式多了一列。
让我们来看看变量
x
x
x是一个
2
×
3
2\times3
2×3的矩阵,max pooling
窗口为
2
×
2
2\times2
2×2,两个维度的步长
s
t
r
i
d
e
s
=
2
strides=2
strides=2。
第一次由于窗口可以覆盖,橙色区域做max pooling
,没什么问题,如下:

接下来就是SAME
和VALID
的区别所在:由于步长为2,当向右滑动两步之后,VALID
方式发现余下的窗口不到
2
×
2
2\times2
2×2所以直接将第三列舍弃,而SAME
方式并不会把多出的一列丢弃,但是只有一列了不够
2
×
2
2\times2
2×2怎么办?填充!

如上图所示,SAME
会增加第四列以保证可以达到
2
×
2
2\times2
2×2,但为了不影响原始信息,一般以0来填充。这就不难理解不同的padding方式输出的形状会有所不同了。
我们设计网络结构时需要设置输入输出的shape,源码nn_ops.py中的convolution函数和pool函数给出的计算公式如下:当CNN用于文本中时,一般卷积层设置卷积核的大小为n×k,其中k为输入向量的维度(即[n,k,input_channel_num,output_channel_num]),这时候我们就需要选择“VALID”填充方式,这时候窗口仅仅是沿着一个维度扫描而不是两个维度。可以理解为统计语言模型当中的N-gram。
If padding == "SAME":
output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides[i])
If padding == "VALID":
output_spatial_shape[i] =
ceil((input_spatial_shape[i] -
(spatial_filter_shape[i]-1) * dilation_rate[i])
/ strides[i]).
d
i
l
a
t
i
o
n
_
r
a
t
e
dilation\_rate
dilation_rate为一个可选的参数,默认为1,这里我们不管。
整理一下,对于VALID
,输出的形状计算如下:
n
e
w
_
h
e
i
g
h
t
=
n
e
w
_
w
i
d
t
h
=
⌈
(
W
–
F
+
1
)
S
⌉
new\_height = new\_width =\lceil \frac{ (W – F + 1)} { S} \rceil
new_height=new_width=⌈S(W–F+1)⌉
对于SAME
,输出的形状计算如下:
n
e
w
_
h
e
i
g
h
t
=
n
e
w
_
w
i
d
t
h
=
⌈
W
S
⌉
new\_height = new\_width =\lceil \frac{ W } { S}\rceil
new_height=new_width=⌈SW⌉
其中,
W
W
W为输入的size,
F
F
F为filter的size,
S
S
S为步长,
⌈
⌉
\lceil \rceil
⌈⌉为向上取整符号。