「SAME」とで「有効」パディングの違いは何であるtf.nn.max_pool
のはtensorflow
?
私の意見では、「有効」とは、max poolを実行したときに、エッジの外側にゼロパディングがないことを意味します。
ディープラーニングのたたみ込み演算のガイドによると、プール演算子にはパディングがない、つまりの 'VALID'を使用するだけですtensorflow
。しかし、最大プールの「SAME」パディングとはtensorflow
何ですか?
「SAME」とで「有効」パディングの違いは何であるtf.nn.max_pool
のはtensorflow
?
私の意見では、「有効」とは、max poolを実行したときに、エッジの外側にゼロパディングがないことを意味します。
ディープラーニングのたたみ込み演算のガイドによると、プール演算子にはパディングがない、つまりの 'VALID'を使用するだけですtensorflow
。しかし、最大プールの「SAME」パディングとはtensorflow
何ですか?
回答:
わかりやすくするために例を示します。
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.]
あなたがアスキーアートが好きなら:
"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]))
パディングは、入力データのサイズを増やす操作です。1次元データの場合は、配列に定数を追加または追加するだけで、2次元では、これらの定数で行列を囲みます。n-dimでは、n-dimハイパーキューブを定数で囲みます。ほとんどの場合、この定数はゼロであり、ゼロパディングと呼ばれます。
以下は、p=1
2次元テンソルに適用されたゼロパディングの例です。
カーネルには任意のパディングを使用できますが、一部のパディング値は他のパディング値よりも頻繁に使用されます。
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
'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]))
パディング値は常にゼロです。
パディングには、有効(パディングなし)、同じ(または半分)、フルの3つの選択肢があります。ここで(Theanoで)説明を見つけることができます:http : //deeplearning.net/software/theano/tutorial/conv_arithmetic.html
有効なパディングはゼロパディングを含まないため、人工的に生成されたゼロを含まず、有効な入力のみをカバーします。ストライドs = 1の場合、カーネルサイズkの出力の長さは((入力の長さ)-(k-1))です。
同じパディングにより、s = 1の場合、出力のサイズは入力のサイズと同じになります。s = 1の場合、埋め込まれるゼロの数は(k-1)です。
完全なパディングは、カーネルが入力全体にわたって実行されることを意味します。そのため、最後に、カーネルは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)
同じ パディング:これは、公式ドキュメントで言及されているように2つの条件を個別に考慮する必要があるため、最初は理解するのが難しいです。
入力を、出力を、パディングを、ストライドをとして、カーネルサイズをとしてみましょう(単一の次元のみが考慮されます)
ケース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):
これが実際にTFでSAMEパディングがどのように機能するかを理解するのに役立つことを願っています。
ここでの説明と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)
コミュニティのために、では、さまざまなプーリング機能とそれぞれのコマンドを指定します。
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
or tf.compat.v2.nn.avg_pool
またはtf.compat.v1.keras.layers.AveragePooling2D
or tf.compat.v1.keras.layers.AvgPool2D
またはtf.compat.v2.keras.layers.AveragePooling2D
or tf.compat.v2.keras.layers.AvgPool2D
、1.xから2.xに移行した場合。