在tf.nn中“SAME”和“VALID”填充之间的区别是什么?tensorflow的Max_pool ?

在我看来,'VALID'意味着当我们做max pool时,边缘外不会有零填充。

根据深度学习卷积算法指南,它说池操作符中不会有填充,即只使用tensorflow的“VALID”。 但什么是'SAME'填充的最大池张量流量?


当前回答

当stride为1时(卷积比池化更典型),我们可以想到以下区别:

“SAME”:输出大小与输入大小相同。这就要求滤镜窗口要在输入贴图外滑动,因此需要垫片。 "VALID":过滤器窗口保持在输入映射中的有效位置,因此输出大小缩小为filter_size - 1。没有填充。

其他回答

当stride为1时(卷积比池化更典型),我们可以想到以下区别:

“SAME”:输出大小与输入大小相同。这就要求滤镜窗口要在输入贴图外滑动,因此需要垫片。 "VALID":过滤器窗口保持在输入映射中的有效位置,因此输出大小缩小为filter_size - 1。没有填充。

TensorFlow Convolution的例子概述了SAME和VALID的区别:

对于相同的填充,输出的高度和宽度计算如下: Out_height = ceil(float(in_height) / float(strides[1])) Out_width = ceil(float(in_width) / float(strides[2]))

And

对于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]))

我举个例子来说明:

X:输入形状[2,3]的图像,1通道 valid_pad: max pool with 2x2 kernel, stride 2和VALID padding。 same_pad: max pool with 2x2 kernel, stride 2和SAME padding(这是经典的方法)

输出形状为:

Valid_pad:这里没有填充,所以输出形状是[1,1] Same_pad:在这里,我们将图像填充到形状[2,4](使用-inf,然后应用Max pool),因此输出形状是[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.]

根据这里的解释和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')

总之,“有效”填充意味着没有填充。卷积层的输出大小根据输入大小和内核大小而缩小。

相反,“相同”填充意味着使用填充。当stride设置为1时,卷积层的输出大小保持为输入大小,在计算卷积时在输入数据周围附加一定数量的“0-border”。

希望这个直观的描述能有所帮助。