wake-up-neo.net

Was ist der Unterschied zwischen 'SAME' und 'VALID' in tf.nn.max_pool des Tensorflows?

Was ist der Unterschied zwischen 'SAME' und 'VALID' in tf.nn.max_pool von tensorflow?

Meiner Meinung nach bedeutet "GÜLTIG", dass beim Max-Pool kein Nullabstand außerhalb der Kanten vorhanden ist. 

Gemäß einem Leitfaden zur Faltungsarithmetik für tiefes Lernen heißt es, dass es im Pooloperator keine Auffüllung geben wird, dh es wird einfach 'VALID' von tensorflow..__ verwendet tensorflow?

204
karl_TUM

Ich werde ein Beispiel geben, um es klarer zu machen:

  • x: Eingabebild der Form [2, 3], 1 Kanal
  • valid_pad: Maximaler Pool mit 2x2 Kernel, Schritt 2 und VALID-Auffüllung.
  • same_pad: Maximaler Pool mit 2x2 Kernel, Schritt 2 und SAME-Auffüllung (dies ist der Klassiker Weg)

Die Ausgabeformen sind:

  • valid_pad: hier kein Auffüllen, daher ist die Ausgabeform [1, 1]
  • same_pad: Hier füllen wir das Bild auf die Form [2, 4] (mit -inf und wenden dann den maximalen Pool an), sodass die Ausgabeform [1, 2] ist.

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

118

Wenn Sie Ascii Art mögen:

  • "VALID" = ohne Auffüllen:

       inputs:         1  2  3  4  5  6  7  8  9  10 11 (12 13)
                      |________________|                dropped
                                     |_________________|
    
  • "SAME" = mit Nullabstand:

                   pad|                                      |pad
       inputs:      0 |1  2  3  4  5  6  7  8  9  10 11 12 13|0  0
                   |________________|
                                  |_________________|
                                                 |________________|
    

In diesem Beispiel:

  • Eingabebreite = 13
  • Filterbreite = 6
  • Schritt = 5

Anmerkungen:

  • "VALID" löscht immer nur die am weitesten rechts liegenden Spalten (oder die untersten Zeilen).
  • "SAME" versucht, die Zeilen links und rechts gleichmäßig aufzufüllen. Wenn jedoch die Anzahl der hinzuzufügenden Spalten ungerade ist, wird die zusätzliche Spalte rechts hinzugefügt, wie in diesem Beispiel (die gleiche Logik gilt vertikal) Reihe von Nullen am unteren Rand).
431
MiniQuark

Wenn stride 1 ist (typischer bei Faltung als Pooling), können wir uns folgende Unterscheidung vorstellen:

  • "SAME": Ausgabegröße ist gleich wie Eingabegröße. Dies erfordert, dass das Filterfenster aus der Eingabekarte herausrutscht und daher aufgefüllt werden muss. 
  • "VALID": Das Filterfenster bleibt innerhalb der Eingabekarte auf gültig . Die Ausgabegröße wird also um filter_size - 1 verkleinert. Es erfolgt keine Auffüllung.
102
YvesgereY

Das TensorFlow Convolution Beispiel gibt einen Überblick über den Unterschied zwischen SAME und VALID:

  • Für die SAME-Auffüllung werden Ausgabehöhe und -breite wie folgt berechnet:

    out_height = ceil(float(in_height) / float(strides[1]))
    out_width  = ceil(float(in_width) / float(strides[2]))
    

Und

  • Für die VALID-Auffüllung werden Ausgabehöhe und -breite wie folgt berechnet:

    out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
    out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))
    
73
RoyaumeIX

Padding ist ein Vorgang, um die Größe der Eingabedaten zu erhöhen. Im Falle von 1-dimensionalen Daten fügen Sie dem Array einfach eine Konstante hinzu. In 2-Dim umgeben Sie die Matrix mit diesen Konstanten. In n-dim umgeben Sie Ihren n-dim-Hyperwürfel mit der Konstante. In den meisten Fällen ist diese Konstante Null und wird als Nullauffüllung bezeichnet.

Hier ist ein Beispiel für das Auffüllen mit Nullen, wobei p=1 auf den 2-d-Tensor angewendet wird: enter image description here


Sie können eine beliebige Auffüllung für Ihren Kernel verwenden, aber einige Auffüllwerte werden häufiger verwendet als andere:

  • VALID Auffüllen. Im einfachsten Fall bedeutet das überhaupt keine Auffüllung. Belassen Sie Ihre Daten einfach so, wie sie waren.
  • SAME-Auffüllung wird gelegentlich als HALF-Auffüllung bezeichnet. Es heißt SAME, da es für eine Faltung mit einem Schritt = 1 (oder zum Pooling) eine Ausgabe mit derselben Größe wie die Eingabe erzeugen soll. Es wird HALF genannt, weil für einen Kern der Größe kenter image description here
  • FULL-Auffüllung ist die maximale Auffüllung, die nicht zu einer Faltung über aufgefüllte Elemente führt. Bei einem Kernel der Größe k ist diese Auffüllung gleich k - 1.

Um eine beliebige Auffüllung in TF zu verwenden, können Sie tf.pad() verwenden.

38
Salvador Dali

Kurze Erklärung

VALID: Wenden Sie keine Auffüllung an, d. h. nehmen Sie an, dass alle Dimensionen valid sind, sodass das Eingabebild vollständig von dem von Ihnen angegebenen Filter und Schritt abgedeckt wird.

SAME: Wenden Sie das Auffüllen auf die Eingabe an (falls erforderlich), damit das Eingabebild vollständig von dem von Ihnen angegebenen Filter und Schritt abgedeckt wird. Für Schritt 1 wird dadurch sichergestellt, dass die Ausgabebildgröße gleich wie die Eingabe ist.

Anmerkungen

  • Dies gilt in gleicher Weise für Conv-Layer sowie für Max Pool-Layer
  • Der Begriff "gültig" ist ein bisschen falsch, weil Dinge nicht "ungültig" werden, wenn Sie einen Teil des Bildes ablegen. Manchmal möchte man das sogar. Dies sollte wahrscheinlich NO_PADDING heißen.
  • Der Begriff "gleich" ist ebenfalls eine Fehlbezeichnung, da er nur für einen Schritt von 1 sinnvoll ist, wenn das Ausgabemaß gleich dem Eingabemaß ist. Bei einem Schritt von 2 sind die Ausgabeabmessungen beispielsweise die Hälfte. Dies sollte wahrscheinlich AUTO_PADDING heißen.
  • In SAME (d. H. Auto-Pad-Modus) versucht Tensorflow, die Auffüllung sowohl links als auch rechts gleichmäßig zu verteilen.
  • In VALID (d. H. Kein Auffüllmodus) wird Tensorflow die rechte und/oder untere Zelle abfallen lassen, wenn Ihr Filter und Ihre Eingabe das Eingabebild nicht vollständig abdecken.
19
Shital Shah

Es gibt drei Möglichkeiten des Auffüllens: gültig (kein Auffüllen), gleich (oder halb), voll. Erklärungen (in Theano) finden Sie hier: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

  • Gültige oder keine Auffüllung:

Die gültige Auffüllung beinhaltet keine Nullauffüllung, deckt also nur die gültige Eingabe ab, keine künstlich erzeugten Nullen. Die Länge der Ausgabe ist ((die Länge der Eingabe) - (k-1)) für die Kerngröße k, wenn der Schritt s = 1 ist.

  • Gleiche oder halbe Polsterung:

Durch die gleiche Auffüllung wird die Größe der Ausgänge mit der der Eingänge identisch, wenn s = 1. Wenn s = 1 ist die Anzahl der aufgefüllten Nullen (k-1).

  • Vollpolsterung:

Die vollständige Auffüllung bedeutet, dass der Kernel die gesamten Eingaben durchläuft, sodass an den Enden der Kernel möglicherweise nur die einzige Eingabe und Nullen trifft. Die Anzahl der aufgefüllten Nullen ist 2(k-1), wenn s = 1. Die Länge der Ausgabe ist ((die Länge der Eingabe) + (k-1)), wenn s = 1.

Daher die Anzahl der Auffüllungen: (gültig) <= (gleich) <= (voll)

10

Ich zitiere diese Antwort aus offiziellen Tensorflow-Dokumenten https://www.tensorflow.org/api_guides/python/nn#Convolution Für die Auffüllung 'SAME' werden Ausgabehöhe und -breite berechnet als

out_height = ceil(float(in_height) / float(strides[1]))
out_width  = ceil(float(in_width) / float(strides[2]))

und die Auffüllung oben und links wird wie folgt berechnet:

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

Für die Auffüllung 'VALID' werden die Ausgabehöhe und -breite wie folgt berechnet:

out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))

und die Auffüllwerte sind immer Null.

9
Vaibhav Dixit

Basierend auf der Erklärung hier und der Antwort von Tristan benutze ich diese schnellen Funktionen normalerweise für die Überprüfung der Gesundheit.

# 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')
5
ahmedhosny

Polsterung ein/aus. Bestimmt die effektive Größe Ihrer Eingabe .

VALID: Kein Auffüllen. Faltungsoperationen usw. werden nur an Stellen ausgeführt, die "gültig" sind, d. H. Nicht zu nahe an den Grenzen Ihres Tensors. 
Mit einem Kern von 3x3 und einem Bild von 10x10 würden Sie eine Faltung im 8x8-Bereich innerhalb der Grenzen durchführen.

SAME: Padding ist vorhanden. Immer wenn Ihre Operation auf eine Nachbarschaft verweist (egal wie groß), werden Nullwerte bereitgestellt, wenn diese Umgebung außerhalb des ursprünglichen Tensors liegt, damit die Operation auch für Grenzwerte funktionieren kann. 
Mit einem Kern von 3x3 und einem Bild von 10x10 würden Sie die Faltung im gesamten 10x10-Bereich durchführen.

4
Laine Mikael

G&UUML;LTIG padding: dies ist mit null padding. Ich hoffe es gibt keine Verwirrung. 

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: Das ist ziemlich kompliziert zu verstehen, da wir zwei Bedingungen separat betrachten müssen, wie in offiziellen Dokumenten erwähnt. 

Nehmen wir die Eingabe als  , Ausgabe als Polsterung als Schritt wie  und Kerngröße als . (singal dimentina wird betrachtet)

Fall 01:  :

Fall 02: 

wird so berechnet, dass der minimale Wert, der für das Auffüllen verwendet werden kann. Seit Wert von  ist bekannt, Wert von  finden Sie in diesem Formular 

Lassen Sie uns dieses Beispiel ausarbeiten:

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)

Hier ist die Dimension von x (3,4). Wenn dann die horizontale Richtung genommen wird (3):

Wenn die Vertialrichtung genommen wird (4):

Ich hoffe, dies wird helfen zu verstehen, wie das GLEICHE -Padding in TF funktioniert. 

2
GPrathap

 General Formula

Hier sind W und H Breite und Höhe der Eingabe, F sind Filterabmessungen P ist Auffüllgröße (d. H. Anzahl der Zeilen oder Spalten, die aufgefüllt werden sollen)

Für die gleiche Auffüllung: 

 SAME Padding

Für GÜLTIGE Auffüllung: 

 VALID padding

0
Shivam Kushwaha