在tensorflow
的tf.nn.max_pool
中’SAME’和’VALID’填充有什麽區別?
在我看來,’VALID’意味著做最大池時,邊外沒有零填充。
根據A guide to convolution arithmetic for deep learning,它表示池化操作符中沒有填充,即隻使用tensorflow
的’VALID’。但是什麽是tensorflow
中最大池的’SAME’填充?
最佳解決方案
我舉一個例子來說明一點:
-
x
:shape[2,3],1通道的輸入圖像 -
valid_pad
:具有2×2內核,步幅2和VALID填充的最大池化。 -
same_pad
:最大池化,2×2內核,步幅2和SAME填充(這是經典的方法)
輸出形狀為:
-
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 art:
-
"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"
嘗試向左和向右均勻填充,但如果要添加的列數是奇數,它將向右添加額外的列,如本示例中的情況(相同的邏輯垂直應用:可能有一個額外的底部的一排零)。
第三種解決方案
TensorFlow Convolution示例概述了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]))
第四種方案
當stride
為1時(更常見的是卷積而不是合並),我們可以想到以下區別:
-
"SAME"
:輸出大小與輸入大小相同。這需要過濾器窗口在輸入映射外滑動,因此需要填充。 -
"VALID"
:過濾器窗口保持在輸入映射內的有效位置,因此輸出大小會縮小filter_size - 1
。沒有填充。
第五種方案
填充是一種增加輸入數據大小的操作。在一維數據的情況下,您隻需在數組中附加/前置一個常數,使用這些常數在2維度環繞矩陣中。在n-dim中,您可以使用常量包圍n-dim超立方體。在大多數情況下,此常數為零,稱為zero-padding。
以下是zero-padding與p=1
應用於2-d張量的示例:
您可以為內核使用任意填充,但某些填充值的使用頻率高於其他填充值:
-
有效填充。最簡單的情況,意味著根本沒有填充。隻需保留您的數據即可。
-
SAME填充有時稱為HALF填充。它被稱為SAME,因為對於stride = 1的卷積(或用於匯集),它應該產生與輸入相同大小的輸出。它被稱為HALF,因為對於大小為
k
的內核 -
FULL填充是最大填充,不會導致僅填充元素的卷積。對於大小為
k
的內核,此填充等於k - 1
。
要在TF中使用任意填充,可以使用tf.pad()
第六種方案
填充有三種選擇:有效(無填充),相同(或一半),填充。你可以在這裏找到解釋(在Theano):http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html
-
有效或無填充:
有效填充不涉及零填充,因此它僅覆蓋有效輸入,不包括人工生成的零。如果步幅s = 1,則輸出的長度是((輸入的長度) – (k-1))對於內核大小k。
-
相同或半填充:
當s = 1時,相同的填充使輸出的大小與輸入的大小相同。如果s = 1,則填充的零的數量是(k-1)。
-
全填充:
完整填充意味著內核在整個輸入上運行,因此在最後,內核可能隻滿足一個輸入和零。如果s = 1,填充的零的數量是2(k-1)。如果s = 1,則輸出長度為((輸入長度)+(k-1))。
因此,填充數量:(有效)< =(相同)< =(完整)
第七種方案
快速解釋
VALID
:不要應用任何填充,即假設所有尺寸都有效,以便輸入圖像完全被過濾器覆蓋並按指定步幅覆蓋。
SAME
:將填充應用於輸入(如果需要),以便輸入圖像被過濾器完全覆蓋並按指定步幅。對於步幅1,這將確保輸出圖像大小與輸入相同。
注意
-
這同樣適用於coov圖層和最大池化圖層
-
術語”valid”有點用詞不當,因為如果丟棄部分圖像,事情就不會變成”invalid”。有時你甚至可能想要那樣。這可能應該被稱為”NO_PADDING”。
-
術語”same”也是用詞不當,因為當輸出維數與輸入維度相同時,它隻對1的步幅有意義。例如,對於2的步幅,輸出尺寸將是一半。這可能應該被稱為”AUTO_PADDING”。
-
在
SAME
(即auto-pad模式)中,Tensorflow將嘗試在左右兩側均勻分布填充。 -
在
VALID
中(即無填充模式),如果過濾器和步幅未完全覆蓋輸入圖像,則Tensorflow將向右和/或底部單元格下降。
第八種方案
我從官方tensorflow docs 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
對於’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]))
並且填充值始終為零。