tf.nn.max_pooltensorflow中,“ SAME”和“ VALID”填充之间有什么区别?

根据深度学习卷积算法指南,它说池运算符中将没有填充,即仅使用tensorflow的“ VALID”。 tensorflow中最大池的填充?

评论

检查tensorflow.org/api_guides/python/…以获得详细信息,这是tf做到的方式。

这是关于可视化的一个非常详细的答案。

查看这些惊人的GIF,以了解填充和跨距的工作原理。链接

@GabrielChu您的链接似乎已消失,现在已重定向到一般概述。

随着Tensorflow升级到2.0,事情将被Keras取代,我相信您可以在Keras文档中找到池化信息。 @matt

#1 楼

我将举一个例子使之更清楚: :具有2x2内核,步幅2和有效填充的最大缓冲池。

x:具有2x2内核,步幅2和相同填充的最大缓冲池(这是经典的处理方法)

输出形状为:



valid_pad:此处,没有填充,因此输出形状为[1,1]

same_pad:此处,我们将图像填充为[2,4]形状(使用valid_pad,然后应用最大池),因此输出形状为[1,2]


 same_pad 




#2 楼

如果您喜欢ascii艺术:



"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"填充时,如果跨度为1,则图层的输出将具有与其输入相同的空间尺寸。该图层仅使用有效的输入数据。


评论


公平地说“ SAME”的意思是“如果图像宽度不是滤波器宽度的倍数或图像高度不是滤波器高度的倍数,请使用零填充以确保不必更改滤波器大小“?例如,如果宽度是问题,那么“用零填充直至滤波器宽度的倍数”?

–StatsSorceress
17年11月30日在17:46



回答我自己的问题:不,这不是零填充的意义。您可以选择要与输入配合使用的过滤器大小(包括零填充),但不要在过滤器大小之后选择零填充。

–StatsSorceress
17年2月2日于1:20

我不明白你自己的答案@StatsSorceress。在我看来,您添加了足够的零(以尽可能对称的方式),以便所有输入都被某个过滤器覆盖,对吗?

– guillefix
19年1月11日在17:25

很好的答案是,只需添加一下:如果张量值可以为负,则使用-inf填充max_pooling。

– Tones29
19年4月10日在12:46

如果在ksize = 2,stride = 2且使用相同填充的情况下输入宽度是偶数怎么办?...那么它不应被零填充吗?....我是在看darkflow代码仓库时说的,他们使用的是SAME pad,maxpool的步幅= 2,ksize = 2 .... maxpooling图像宽度从416像素宽度减少到208像素之后。谁能澄清一下?

– K.vindi
20-4-4在21:01



#3 楼

stride为1时(卷积比池化更典型),我们可以想到以下区别:"SAME":输出大小与输入大小相同。这要求过滤器窗口滑到输入图的外部,因此需要填充。

"VALID":过滤器窗口停留在输入映射内的有效位置,因此输出大小缩小了filter_size - 1。没有填充发生。


评论


这最终是有帮助的。到目前为止,似乎SAME和VALID也可能被称为foo和bar

– omatai
18年1月25日在3:33



我认为“输出大小与输入大小相同”仅在步幅为1时才是正确的。

–omsrisagar
18年7月16日在18:19

#4 楼

TensorFlow卷积示例概述了SAMEVALID之间的区别:



对于SAME填充,输出高度和宽度的计算方式如下: br />
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]))




#5 楼

填充是增加输入数据大小的操作。如果是一维数据,则只需在数组前添加/添加常量,在二维中,将这些常量包围在矩阵中。在n-dim中,您用常数包围n-dim超立方体。在大多数情况下,此常数为零,这称为零填充。

以下是零填充的示例,其中p=1应用于二维张量:



您可以对内核使用任意填充,但是某些填充值的使用频率要比其他填充值高:



有效填充。最简单的情况是完全没有填充。只需保持数据不变即可。

相同的填充有时也称为HALF填充。之所以称为SAME,是因为对于步幅= 1的卷积(或对于池化),它应产生与输入大小相同的输出。之所以称为HALF,是因为对于大小为k 的内核,完全填充是最大填充,它不会导致仅填充元素的卷积。对于大小为k的内核,此填充等于k - 1。要在TF中使用任意填充,可以使用tf.pad()

#6 楼

快速说明

VALID:不应用任何填充,即,假设所有尺寸均有效,以便输入图像完全被过滤器覆盖并跨步指定。

SAME :对输入使用填充(如果需要),以使输入图像完全被滤镜覆盖,并跨步指定。对于第1步,这将确保输出图像的大小与输入的大小相同。

注意事项方式
“有效”一词有点用词不当,因为如果您删除部分图像,事情不会变得“无效”。有时您甚至可能想要那样。
术语“相同”也是一个错误的称呼,因为只有当输出尺寸与输入尺寸相同时,步幅为1才有意义。例如,跨度为2时,输出尺寸将为一半。
NO_PADDING(即自动填充模式)下,Tensorflow会尝试在左右两侧均匀地扩展填充。
AUTO_PADDING(即无填充模式)下,Tensorflow如果您的过滤条件和步幅未完全覆盖输入图像,则会在右侧和/或底部放置单元格。


#7 楼

补充YvesgereY的一个很好的答案,我发现这种可视化效果非常有用:



填充“有效”是第一个数字。过滤器窗口停留在图像内部。

填充“相同”是第三个数字。输出的大小相同。


在本文中找到了它。

评论


非常立即的答案!

–尼古拉·佩萨文托(Nicola Pesavento)
20/09/14 '16:03

这对我来说是最好的解决方案。可视化讲述了故事。谢谢

– wbadry
20-10-19在17:08

#8 楼

我引用了官方tensorflow文档的这个答案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


对于“有效”填充,输出高度和宽度的计算公式如下:

out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))


填充值始终为零。

评论


坦白说,这是唯一有效且完整的答案,不仅仅限于1的跨度。而且所需要的只是文档中的引用。 +1

– P-Gn
18年5月26日在18:53



得到这个答案非常有用,特别是因为您指向的链接不再起作用,而且看来Google删除了tf网站上的信息!

–丹尼尔(Daniel)
20 Mar 4 '20 at 2:28

#9 楼

有三种填充选项:有效(无填充),相同(或一半),完整。您可以在以下位置找到说明(在Theano中):
http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html


有效或无填充:

有效填充不涉及零填充,因此它仅覆盖有效输入,不包括人工生成的零。如果步幅s = 1,则对于内核大小k,输出的长度为((输入的长度)-(k-1))。


相同或一半的填充:

当s = 1时,相同的填充使输出的大小与输入的大小相同。如果s = 1,则填充的零数为(k-1)。


完全填充:

完全填充意味着内核在整个输入,因此到最后,内核可能只满足一个输入,而另一个则为零。如果s = 1,则填充的零数为2(k-1)。如果s = 1,则输出的长度为((输入的长度)+(k-1))。

因此,填充数为:(有效)<=(相同)<=(完整)

#10 楼

有效填充:这是零填充。希望没有混乱。

x = tf.constant([[1., 2., 3.], [4., 5., 6.],[ 7., 8., 9.], [ 7., 8., 9.]])
x = tf.reshape(x, [1, 4, 3, 1])
valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
print (valid_pad.get_shape()) # output-->(1, 2, 1, 1)


SAME填充:首先要理解这有点棘手,因为我们必须分别考虑官方文档中提到的两个条件。

让我们将输入作为,将输出作为,将填充作为,将步幅作为并将内核大小作为(仅考虑一个维度)

案例01:

案例02:

的计算应使填充可用的最小值。由于已知的值,因此可以使用此公式找到的值。

让我们来研究这个例子:那么如果采用水平方向(3):



如果采用垂直方向(4):



希望这将有助于了解SAME填充在TF中的实际工作方式。

#11 楼

综上所述,“有效”填充表示没有填充。卷积层的输出大小根据输入大小和内核大小而缩小。

相反,“相同”填充表示使用填充。当跨距设置为1时,在计算卷积时,通过在输入数据周围附加一定数量的“ 0边界”,将卷积层的输出大小保持为输入大小。说明有帮助。

#12 楼

根据此处的说明以及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')


#13 楼

启用/禁用填充。确定输入的有效大小。

VALID:无填充。卷积运算等操作仅在“有效”的位置执行,即不太靠近张量的边界。使用3x3的内核和10x10的图像,您将在边界内的8x8区域执行卷积。

SAME:提供了填充。每当您的操作引用邻域(无论大小)时,当该邻域扩展到原始张量之外时,都会提供零值,以使该操作也可以处理边界值。使用3x3的内核和10x10的图像,您将在整个10x10区域执行卷积。

#14 楼



这里,W和H是输入的宽度和高度,
F是过滤器尺寸,
P是填充大小(即,要填充的行数或列数)

用于相同填充:



用于有效填充:



#15 楼

Tensorflow 2.0兼容答案:上面已经提供了有关“有效”和“相同”填充的详细说明。

但是,为了社区的利益,我将在Tensorflow 2.x (>= 2.0)中指定不同的Pooling Function及其相应的命令。

1.x中的功能:

tf.nn.max_pool

tf.keras.layers.MaxPool2D

Average Pooling => None in tf.nn, tf.keras.layers.AveragePooling2D

2.x中的功能:

tf.nn.max_pool(如果在2.x中使用)和tf.compat.v1.nn.max_pool_v2tf.compat.v2.nn.max_pool(如果从1.x迁移到2.x)。

tf.keras.layers.MaxPool2D(如果用于2.x和

tf.compat.v1.keras.layers.MaxPool2Dtf.compat.v1.keras.layers.MaxPooling2Dtf.compat.v2.keras.layers.MaxPool2Dtf.compat.v2.keras.layers.MaxPooling2D(如果迁移)从1.x到2.x.

Average Pooling => tf.nn.avg_pool2dtf.keras.layers.AveragePooling2D(如果在TF 2.x和

tf.compat.v1.nn.avg_pool_v2tf.compat.v2.nn.avg_pooltf.compat.v1.keras.layers.AveragePooling2Dtf.compat.v1.keras.layers.AvgPool2Dtf.compat.v2.keras.layers.AveragePooling2Dtf.compat.v2.keras.layers.AvgPool2D(如果已迁移)从1.x到2.x.

有关从Tensorflow 1.x到2.x迁移的更多信息,请参阅此迁移指南。