张量流的tf.nn.max_pool中的'SAME'和'VALID'填充有什么区别?
deep-learning
python
tensorflow
5
0

张量tf.nn.max_pooltensorflow 'SAME'和'VALID'填充有tf.nn.max_pool tensorflow

在我看来,“有效”表示在进行最大池化时,边缘外部不会出现零填充。

根据深度学习卷积算法指南 ,它说池运算符中将不会有填充,即仅使用张量流的“ VALID” tensorflow 。但是,什么是最大池的“相同”填充tensorflow

参考资料:
Stack Overflow
收藏
评论
共 10 个回答
高赞 时间 活跃

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

这是将p=1应用于二维张量的零填充示例: 在此处输入图片说明


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

  • 有效填充 。最简单的情况是完全没有填充。只需保持数据不变即可。
  • 相同的填充有时也称为半填充 。之所以称为SAME ,是因为对于步幅= 1的卷积(或对于池化),它应产生与输入大小相同的输出。之所以称为HALF ,是因为对于大小为k的内核在此处输入图片说明
  • 全填充是最大填充,不会导致仅填充元素的卷积。对于大小为k的内核,此填充等于k - 1

要在TF中使用任意填充,可以使用tf.pad()

收藏
评论

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

  • "SAME" :输出大小输入大小相同 。这要求过滤器窗口滑到输入图的外部,因此需要填充。
  • "VALID" :过滤器窗口停留在输入映射内的有效位置,因此输出大小按filter_size - 1缩小。没有填充发生。
收藏
评论

填充有三种选择:有效(无填充),相同(或一半),完整。您可以在以下位置找到说明(在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))。

因此,填充数:(有效)<=(相同)<=(满)

收藏
评论

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

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)

相同的填充:首先要理解这有点棘手,因为我们必须分别考虑两个条件,如官方文档中所述

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

案例01:

案例02:

计算出使得填充可用的最小值。由于价值众所周知,价值可以用这个公式找到

让我们算出这个例子:

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

x的维数为(3,4)。然后,如果采取水平方向(3):

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

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

收藏
评论

我将举一个例子使之更清楚:

  • x :形状为[2,3],1通道的输入图像
  • valid_pad :具有2x2内核,跨度2和有效填充的最大池。
  • same_pad :具有2x2内核,跨度2和相同填充的最大池(这是经典的处理方式)

输出形状为:

  • 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.]

收藏
评论

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

  • 对于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])) 
收藏
评论

我引用了官方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]))

并且填充值始终为零。

收藏
评论

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

快速说明

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

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

笔记

  • 这同样适用于转换层和最大池层
  • 术语“有效”有点用词不当,因为如果您删除部分图像,事情不会变得“无效”。有时候你甚至可能想要那个。应将其称为NO_PADDING
  • 术语“相同”也用词不当,因为只有当输出尺寸与输入尺寸相同时,步幅为1才有意义。例如,对于跨度2,输出尺寸将是一半。可能应该将其称为AUTO_PADDING
  • SAME (即自动填充模式)下,Tensorflow将尝试在左右两侧均匀地填充填充。
  • VALID (即无填充模式)下,如果您的过滤器和步幅未完全覆盖输入图像,Tensorflow将掉落右侧和/或底部单元格。
收藏
评论

如果您喜欢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"尝试左右均匀填充,但如果要添加的列数是奇数,则它将在右边添加多余的列,如本示例中的情况(垂直应用相同的逻辑:可能存在在底部增加一排零)。

编辑

关于名字:

  • 使用"SAME"填充时,如果跨度为1,则图层的输出将具有与其输入相同的空间尺寸。
  • 使用"VALID"填充,没有"VALID" ”填充输入。该图层仅使用有效的输入数据。
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号