在tf.nn中“SAME”和“VALID”填充之间的区别是什么?tensorflow的Max_pool ?
在我看来,'VALID'意味着当我们做max pool时,边缘外不会有零填充。
根据深度学习卷积算法指南,它说池操作符中不会有填充,即只使用tensorflow的“VALID”。 但什么是'SAME'填充的最大池张量流量?
在tf.nn中“SAME”和“VALID”填充之间的区别是什么?tensorflow的Max_pool ?
在我看来,'VALID'意味着当我们做max pool时,边缘外不会有零填充。
根据深度学习卷积算法指南,它说池操作符中不会有填充,即只使用tensorflow的“VALID”。 但什么是'SAME'填充的最大池张量流量?
当前回答
快速的解释
VALID:不要应用任何填充,也就是说,假设所有的维度都是有效的,这样输入的图像就会被你指定的过滤器和stride完全覆盖。
SAME:应用填充到输入(如果需要),以便输入图像被过滤器和步幅完全覆盖。对于stride 1,这将确保输出图像大小与输入相同。
笔记
This applies to conv layers as well as max pool layers in same way The term "valid" is bit of a misnomer because things don't become "invalid" if you drop part of the image. Sometime you might even want that. This should have probably be called NO_PADDING instead. The term "same" is a misnomer too because it only makes sense for stride of 1 when output dimension is same as input dimension. For stride of 2, output dimensions will be half, for example. This should have probably be called AUTO_PADDING instead. In SAME (i.e. auto-pad mode), Tensorflow will try to spread padding evenly on both left and right. In VALID (i.e. no padding mode), Tensorflow will drop right and/or bottom cells if your filter and stride doesn't full cover input image.
其他回答
根据这里的解释和Tristan的回答,我通常使用这些快速函数进行完整性检查。
# a function to help us stay clean
def getPaddings(pad_along_height,pad_along_width):
# if even.. easy..
if pad_along_height%2 == 0:
pad_top = pad_along_height / 2
pad_bottom = pad_top
# if odd
else:
pad_top = np.floor( pad_along_height / 2 )
pad_bottom = np.floor( pad_along_height / 2 ) +1
# check if width padding is odd or even
# if even.. easy..
if pad_along_width%2 == 0:
pad_left = pad_along_width / 2
pad_right= pad_left
# if odd
else:
pad_left = np.floor( pad_along_width / 2 )
pad_right = np.floor( pad_along_width / 2 ) +1
#
return pad_top,pad_bottom,pad_left,pad_right
# strides [image index, y, x, depth]
# padding 'SAME' or 'VALID'
# bottom and right sides always get the one additional padded pixel (if padding is odd)
def getOutputDim (inputWidth,inputHeight,filterWidth,filterHeight,strides,padding):
if padding == 'SAME':
out_height = np.ceil(float(inputHeight) / float(strides[1]))
out_width = np.ceil(float(inputWidth) / float(strides[2]))
#
pad_along_height = ((out_height - 1) * strides[1] + filterHeight - inputHeight)
pad_along_width = ((out_width - 1) * strides[2] + filterWidth - inputWidth)
#
# now get padding
pad_top,pad_bottom,pad_left,pad_right = getPaddings(pad_along_height,pad_along_width)
#
print 'output height', out_height
print 'output width' , out_width
print 'total pad along height' , pad_along_height
print 'total pad along width' , pad_along_width
print 'pad at top' , pad_top
print 'pad at bottom' ,pad_bottom
print 'pad at left' , pad_left
print 'pad at right' ,pad_right
elif padding == 'VALID':
out_height = np.ceil(float(inputHeight - filterHeight + 1) / float(strides[1]))
out_width = np.ceil(float(inputWidth - filterWidth + 1) / float(strides[2]))
#
print 'output height', out_height
print 'output width' , out_width
print 'no padding'
# use like so
getOutputDim (80,80,4,4,[1,1,1,1],'SAME')
如果你喜欢ascii艺术:
"VALID" = without padding: inputs: 1 2 3 4 5 6 7 8 9 10 11 (12 13) |________________| dropped |_________________| "SAME" = with zero padding: pad| |pad inputs: 0 |1 2 3 4 5 6 7 8 9 10 11 12 13|0 0 |________________| |_________________| |________________|
在这个例子中:
输入宽度= 13 滤镜宽度= 6 步幅= 5
注:
"VALID"只删除最右边的列(或最底部的行)。 “SAME”尝试均匀地左右填充,但如果要添加的列的数量是奇数,它会将额外的列添加到右侧,就像本例中的情况一样(垂直方向上的逻辑相同:底部可能有额外的一行零)。
编辑:
关于名字:
对于“SAME”填充,如果你使用的步幅为1,该层的输出将具有与其输入相同的空间维度。 使用“VALID”填充,就没有“编造”填充输入。该层只使用有效的输入数据。
有三种填充选择:有效(无填充),相同(或一半),满。你可以在这里(Theano)找到解释: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html
有效或无填充:
有效填充不涉及零填充,因此它只覆盖有效输入,不包括人工生成的零。对于内核大小为k的步幅s=1,则输出长度为((输入长度)- (k-1))。
相同或半填充:
当s=1时,相同的填充使输出的大小与输入的大小相同。如果s=1,补零的个数为(k-1)。
完全填充:
完全填充意味着内核运行整个输入,因此在结束时,内核可能只满足一个输入,其他为零。如果s=1,填充的零的数量是2(k-1)。如果s=1,则输出长度为((输入长度)+ (k-1))。
因此,填充的数量:(有效)<=(相同)<=(满)
为了补充YvesgereY的回答,我发现这个可视化非常有用:
填充'valid'是第一个数字。滤镜窗口停留在图像内部。
填充'same'是第三个数字。输出是相同的大小。
在这篇文章里找到的
可视化致谢:vdumoulin@GitHub
填充是一种增加输入数据大小的操作。在一维数据中,你只需要在数组前加上一个常数,在2-dim中,你用这些常数包围矩阵。在n-dim中,用常数包围n-dim超立方体。在大多数情况下,这个常数是零,它被称为零填充。
下面是一个应用于2-d张量的p=1的零填充的例子:
你可以为你的内核使用任意填充,但是有些填充值比其他填充值使用得更频繁:
有效的填充。最简单的情况,意味着根本没有填充。让你的数据保持原样。 相同填充有时称为半填充。之所以称为SAME,是因为对于stride=1的卷积(或池化),它应该产生与输入相同大小的输出。之所以叫HALF是因为对于一个大小为k的核 FULL填充是最大填充,它不会导致对刚刚填充的元素进行卷积。对于一个大小为k的核,这个填充值等于k - 1。
要在TF中使用任意填充,可以使用TF .pad()