tensorflow
name__のtf.nn.max_pool
における 'SAME'と 'VALID'のパディングの違いは何ですか?
私の考えでは、「有効」とは、最大プールを行うときに、境界の外側にゼロの埋め込みがないことを意味します。
ディープラーニングのための畳み込み演算の手引き によると、プール演算子にはパディングがない、つまりtensorflow
name__の 'VALID'だけを使用するということです。しかし、tensorflow
name__の最大プールの「同じ」パディングは何ですか?
明確にするために例を挙げます。
x
:形状[2、3]の入力画像、1チャンネルvalid_pad
:2x2カーネルの最大プール、ストライド2および有効なパディング。same_pad
:2x2カーネルの最大プール、ストライド2および同じパディング(これは クラシック への道です)出力形状は以下のとおりです。
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.]
あなたがアスキーアートが好きなら:
パディングなしの"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"
は左右に均等に埋めようとしますが、追加する列の数が奇数の場合は、この例のように右側に余分な列が追加されます(同じロジックが垂直方向にも適用されます。下部にゼロの行)。stride
が1(プーリングよりも畳み込みで一般的)の場合、以下の区別が考えられます。
"SAME"
:出力サイズは入力サイズと同じ 同じ です。これは、フィルタウィンドウが入力マップの外側にずれることを必要とし、それ故、パディングする必要がある。"VALID"
:フィルタウィンドウは入力マップ内の valid の位置にあるため、出力サイズはfilter_size - 1
だけ縮小されます。パディングは発生しません。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ハイパーキューブを定数で囲みます。ほとんどの場合、この定数はゼロであり、ゼロ詰めと呼ばれます。
カーネルには任意のパディングを使用できますが、いくつかのパディング値は他のものよりも頻繁に使用されます。
k
のカーネルの場合 k
のカーネルの場合、このパディングはk - 1
と等しくなります。TFで任意のパディングを使用するには、 tf.pad()
を使用します。
簡単な説明
VALID
:パディングを適用しません。つまり、入力画像がフィルタで完全に覆われ、指定した値に移動するように、すべての次元が valid であると仮定します。
SAME
:入力画像がフィルタで完全に覆われ、指定した幅に移動するように、(必要に応じて)入力にパディングを適用します。ストライド1では、これにより、出力イメージのサイズが入力と同じ 同じ になります。
ノート
NO_PADDING
と呼ばれるべきです。AUTO_PADDING
と呼ばれるべきです。SAME
(つまり自動埋め込みモード)では、Tensorflowは左右両方に均等にパディングを広げようとします。VALID
(つまり、パディングモードなし)では、あなたのフィルタとストライドが入力画像を完全にカバーしていない場合、Tensorflowは右および/または下のセルをドロップします。パディングには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))になります。
したがって、パディングの数:(有効)<=(同じ)<=(フル)
私は公式のテンソルフロードキュメントからこの答えを引用しています 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]))
パディング値は常にゼロです。
説明 ここ そして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:
埋め込みなし。畳み込み演算などは、「有効」な場所、つまりテンソルの境界に近すぎない場所でのみ実行されます。
3 x 3のカーネルと10 x 10のイメージでは、境界の内側の8 x 8領域で畳み込みを実行します。
SAME:
パディングが提供されています。あなたの操作が近隣を参照するときはいつでも(どんなに大きくても)、その近隣が元のテンソルの外側に広がるときゼロ値が提供され、その操作が境界値に対しても働くことを可能にします。
3 x 3のカーネルと10 x 10のイメージでは、10 x 10の領域全体で畳み込みを実行します。
_ valid _ padding:これはパディングが0の場合です。混乱がないことを願っています。
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)
_ same _ padding: official docs に記載されているように、2つの条件を別々に考慮する必要があるため、これは最初から理解するのが難しいです。
として入力を取りましょう として出力 、パディングとして 、のように歩きます カーネルサイズ (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):
これがTFで _ same _ paddingが実際にどのように機能するかを理解するのに役立つことを願っています。