什么是“相同”和“有效”填充之间的区别tf.nn.max_pool
的tensorflow
?
我认为,“有效”表示在进行最大池化时,边缘外部不会出现零填充。
根据深度学习卷积算法指南,它说池运算符中将没有填充,即仅使用的“ VALID” tensorflow
。但是最大池的“相同”填充是tensorflow
什么?
什么是“相同”和“有效”填充之间的区别tf.nn.max_pool
的tensorflow
?
我认为,“有效”表示在进行最大池化时,边缘外部不会出现零填充。
根据深度学习卷积算法指南,它说池运算符中将没有填充,即仅使用的“ VALID” tensorflow
。但是最大池的“相同”填充是tensorflow
什么?
Answers:
我将举一个例子使其更加清晰:
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.]
如果您喜欢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
|________________|
|_________________|
|________________|
在此示例中:
笔记:
"VALID"
只删除最右边的列(或最下面的行)。"SAME"
尝试左右均匀填充,但是如果要添加的列数是奇数,它将在右边添加额外的列,如本示例中的情况(相同的逻辑在垂直方向上适用:可能会有额外的行底部的零)。编辑:
关于名字:
"SAME"
填充时,如果跨度为1,则图层的输出将具有与其输入相同的空间尺寸。"VALID"
填充时,没有“虚构的”填充输入。该图层仅使用有效的输入数据。-inf
。
当stride
为1时(卷积比池化更典型),我们可以想到以下区别:
"SAME"
:输出大小与输入大小相同。这要求过滤器窗口滑到输入图的外部,因此需要填充。"VALID"
:过滤器窗口停留在输入地图内的有效位置,因此输出大小缩小filter_size - 1
。没有填充发生。SAME
并VALID
可能也被称为foo
和bar
所述TensorFlow卷积示例给出关于之间的差的概述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]))
填充是增加输入数据大小的操作。如果是一维数据,则只需在数组上附加/添加常量,在二维中,将这些常量包围在矩阵中。在n-dim中,将常数包围在n-dim超立方体中。在大多数情况下,此常数为零,称为零填充。
您可以对内核使用任意填充,但是某些填充值的使用频率要比其他填充值高:
k
k
,此填充等于k - 1
。要在TF中使用任意填充,您可以使用 tf.pad()
快速说明
VALID
:不要应用任何填充,即假设所有尺寸均有效,以便输入图像完全被您指定的过滤器和步幅覆盖。
SAME
:对输入使用填充(如果需要),以使输入图像完全被滤镜覆盖,并跨步指定。对于第1步,这将确保输出图像大小相同输入。
笔记
NO_PADDING
改为。AUTO_PADDING
改为调用它。SAME
(即自动填充模式)下,Tensorflow将尝试在左右两侧均匀地填充填充。VALID
(即无填充模式)下,如果您的过滤器和步幅未完全覆盖输入图像,Tensorflow将在右边和/或底部单元格下降。我引用官方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]))
填充值始终为零。
填充有三种选择:有效(无填充),相同(或一半),完整。您可以在以下位置找到说明(在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))。
因此,填充数:(有效)<=(相同)<=(满)
启用/禁用填充。确定输入的有效大小。
VALID:
没有填充。卷积运算等操作仅在“有效”的位置执行,即不太靠近张量的边界。
使用3x3的内核和10x10的图像,您将在边界内的8x8区域执行卷积。
SAME:
提供填充。每当您的操作引用邻域(无论大小)时,当该邻域超出原始张量时,都会提供零值,以使该操作也可以处理边界值。
使用3x3的内核和10x10的图像,您将在整个10x10区域上进行卷积。
有效填充:这是零填充。希望没有混乱。
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中的实际作用。
根据此处的说明以及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')
Tensorflow 2.0兼容答案:上面已经提供了有关“有效”和“相同”填充的详细说明。
但是,Tensorflow 2.x (>= 2.0)
为了社区的利益,我将在中指定不同的Pooling Function及其各自的Command 。
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_v2
或中使用tf.compat.v2.nn.max_pool
,则从1.x迁移到2.x。
tf.keras.layers.MaxPool2D
如果在2.x和
tf.compat.v1.keras.layers.MaxPool2D
或tf.compat.v1.keras.layers.MaxPooling2D
或 tf.compat.v2.keras.layers.MaxPool2D
或tf.compat.v2.keras.layers.MaxPooling2D
(如果从1.x迁移到2.x)。
Average Pooling => tf.nn.avg_pool2d
或者tf.keras.layers.AveragePooling2D
在TF 2.x中使用
tf.compat.v1.nn.avg_pool_v2
或tf.compat.v2.nn.avg_pool
或tf.compat.v1.keras.layers.AveragePooling2D
或tf.compat.v1.keras.layers.AvgPool2D
或tf.compat.v2.keras.layers.AveragePooling2D
或tf.compat.v2.keras.layers.AvgPool2D
,如果从1.x中迁移到2.x版本
有关从Tensorflow 1.x迁移到2.x的更多信息,请参阅此迁移指南。