在tensorflow
的tf.nn.max_pool
中’SAME’和’VALID’填充有什么区别?
在我看来,’VALID’意味着做最大池时,边外没有零填充。
根据A guide to convolution arithmetic for deep learning,它表示池化操作符中没有填充,即只使用tensorflow
的’VALID’。但是什么是tensorflow
中最大池的’SAME’填充?
最佳解决方案
我举一个例子来说明一点:
-
x
:shape[2,3],1通道的输入图像 -
valid_pad
:具有2×2内核,步幅2和VALID填充的最大池化。 -
same_pad
:最大池化,2×2内核,步幅2和SAME填充(这是经典的方法)
输出形状为:
-
valid_pad
:这里没有填充,所以输出形状为[1,1] -
same_pad
:在这里,我们将图像填充到形状[2,4](使用-inf
,然后应用最大池化),因此输出形状为[1,2]
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')
valid_pad.get_shape() == [1, 1, 1, 1] # valid_pad is [5.]
same_pad.get_shape() == [1, 1, 2, 1] # same_pad is [5., 6.]
次佳解决方案
如果你喜欢ascii art:
-
"VALID"
=没有填充:inputs: 1 2 3 4 5 6 7 8 9 10 11 (12 13) |________________| dropped |_________________|
-
"SAME"
=零填充:pad| |pad inputs: 0 |1 2 3 4 5 6 7 8 9 10 11 12 13|0 0 |________________| |_________________| |________________|
在这个例子中:
-
输入宽度= 13
-
过滤宽度= 6
-
步幅= 5
注意:
-
"VALID"
只丢弃最右边的列(或最底部的行)。 -
"SAME"
尝试向左和向右均匀填充,但如果要添加的列数是奇数,它将向右添加额外的列,如本示例中的情况(相同的逻辑垂直应用:可能有一个额外的底部的一排零)。
第三种解决方案
TensorFlow Convolution示例概述了SAME
和VALID
之间的差异:
-
对于
SAME
填充,输出高度和宽度计算如下:
out_height = ceil(float(in_height)/float(strides [1]))
out_width = ceil(float(in_width)/float(strides [2]))
和
-
对于
VALID
填充,输出高度和宽度计算如下:
out_height = ceil(float(in_height – filter_height + 1)/float(strides [1]))
out_width = ceil(float(in_width – filter_width + 1)/float(strides [2]))
第四种方案
当stride
为1时(更常见的是卷积而不是合并),我们可以想到以下区别:
-
"SAME"
:输出大小与输入大小相同。这需要过滤器窗口在输入映射外滑动,因此需要填充。 -
"VALID"
:过滤器窗口保持在输入映射内的有效位置,因此输出大小会缩小filter_size - 1
。没有填充。
第五种方案
填充是一种增加输入数据大小的操作。在一维数据的情况下,您只需在数组中附加/前置一个常数,使用这些常数在2维度环绕矩阵中。在n-dim中,您可以使用常量包围n-dim超立方体。在大多数情况下,此常数为零,称为zero-padding。
以下是zero-padding与p=1
应用于2-d张量的示例:
您可以为内核使用任意填充,但某些填充值的使用频率高于其他填充值:
-
有效填充。最简单的情况,意味着根本没有填充。只需保留您的数据即可。
-
SAME填充有时称为HALF填充。它被称为SAME,因为对于stride = 1的卷积(或用于汇集),它应该产生与输入相同大小的输出。它被称为HALF,因为对于大小为
k
的内核 -
FULL填充是最大填充,不会导致仅填充元素的卷积。对于大小为
k
的内核,此填充等于k - 1
。
要在TF中使用任意填充,可以使用tf.pad()
第六种方案
填充有三种选择:有效(无填充),相同(或一半),填充。你可以在这里找到解释(在Theano):http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html
-
有效或无填充:
有效填充不涉及零填充,因此它仅覆盖有效输入,不包括人工生成的零。如果步幅s = 1,则输出的长度是((输入的长度) – (k-1))对于内核大小k。
-
相同或半填充:
当s = 1时,相同的填充使输出的大小与输入的大小相同。如果s = 1,则填充的零的数量是(k-1)。
-
全填充:
完整填充意味着内核在整个输入上运行,因此在最后,内核可能只满足一个输入和零。如果s = 1,填充的零的数量是2(k-1)。如果s = 1,则输出长度为((输入长度)+(k-1))。
因此,填充数量:(有效)< =(相同)< =(完整)
第七种方案
快速解释
VALID
:不要应用任何填充,即假设所有尺寸都有效,以便输入图像完全被过滤器覆盖并按指定步幅覆盖。
SAME
:将填充应用于输入(如果需要),以便输入图像被过滤器完全覆盖并按指定步幅。对于步幅1,这将确保输出图像大小与输入相同。
注意
-
这同样适用于coov图层和最大池化图层
-
术语”valid”有点用词不当,因为如果丢弃部分图像,事情就不会变成”invalid”。有时你甚至可能想要那样。这可能应该被称为”NO_PADDING”。
-
术语”same”也是用词不当,因为当输出维数与输入维度相同时,它只对1的步幅有意义。例如,对于2的步幅,输出尺寸将是一半。这可能应该被称为”AUTO_PADDING”。
-
在
SAME
(即auto-pad模式)中,Tensorflow将尝试在左右两侧均匀分布填充。 -
在
VALID
中(即无填充模式),如果过滤器和步幅未完全覆盖输入图像,则Tensorflow将向右和/或底部单元格下降。
第八种方案
我从官方tensorflow docs https://www.tensorflow.org/api_guides/python/nn#Convolution引用这个答案对于’SAME’填充,输出高度和宽度计算如下:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
并且顶部和左侧的填充计算如下:
pad_along_height = max((out_height - 1) * strides[1] +
filter_height - in_height, 0)
pad_along_width = max((out_width - 1) * strides[2] +
filter_width - in_width, 0)
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
对于’VALID’填充,输出高度和宽度计算如下:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
并且填充值始终为零。