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


309

Was ist der Unterschied zwischen ‚SAMT‘ und ‚VALID‘ padding in tf.nn.max_poolder tensorflow?

Meiner Meinung nach bedeutet "GÜLTIG", dass es außerhalb der Kanten keine Null-Polsterung gibt, wenn wir den Max-Pool ausführen.

Laut einem Leitfaden zur Faltungsarithmetik für tiefes Lernen heißt es, dass der Poolbetreiber keine Polsterung aufweist, dh verwenden Sie einfach 'VALID' von tensorflow. Aber was ist die gleiche Polsterung des maximalen Pools tensorflow?


3
Überprüfen Sie tensorflow.org/api_guides/python/… auf Details. So haben Sie es gemacht.
GabrielChu


4
Schauen Sie sich diese erstaunlichen Gifs an, um zu verstehen, wie Polsterung und Schritt funktionieren. Link
Deepak

1
@GabrielChu Ihr Link scheint gestorben zu sein und ist jetzt eine Weiterleitung zu einer allgemeinen Übersicht.
Matt

Beim Upgrade von Tensorflow auf 2.0 werden die Dinge durch Keras ersetzt, und ich glaube, Sie finden die Pooling-Informationen in Keras-Dokumentationen. @ Matt
GabrielChu

Antworten:


163

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

  • x: Eingabebild der Form [2, 3], 1 Kanal
  • valid_pad: Max Pool mit 2x2 Kernel, Schritt 2 und gültiger Polsterung.
  • same_pad: Max Pool mit 2x2 Kernel, Stride 2 und SAME Padding (dies ist der klassische Weg)

Die Ausgabeformen sind:

  • valid_pad: hier keine Polsterung, daher ist die Ausgabeform [1, 1]
  • same_pad: Hier füllen wir das Bild auf die Form [2, 4] (mit -infund 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.]


603

Wenn Sie ASCII Kunst mögen:

  • "VALID" = ohne Polsterung:

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

                   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 Spalten ganz rechts (oder Zeilen ganz unten).
  • "SAME" versucht, gleichmäßig nach links und rechts aufzufüllen, aber wenn die Anzahl der hinzuzufügenden Spalten ungerade ist, wird die zusätzliche Spalte nach rechts hinzugefügt, wie dies in diesem Beispiel der Fall ist (dieselbe Logik gilt vertikal: Möglicherweise gibt es eine zusätzliche Zeile von Nullen unten).

Bearbeiten :

Über den Namen:

  • Mit "SAME"Polsterung, wenn Sie einen Schritt von 1 verwenden, haben die Schicht der Ausgänge die gleichen räumlichen Dimensionen als seine Eingänge.
  • Beim "VALID"Auffüllen gibt es keine "erfundenen" Auffüllungseingaben. Die Ebene verwendet nur gültige Eingabedaten.

Ist es fair zu sagen, dass "SAME" bedeutet, dass "Null-Padding" verwendet wird, um sicherzustellen, dass sich die Filtergröße nicht ändern muss, wenn die Bildbreite nicht ein Vielfaches der Filterbreite oder die Bildhöhe kein Vielfaches der Filterhöhe ist "? Wie in "Pad mit Nullen bis zu einem Vielfachen der Filterbreite", wenn Breite das Problem ist?
StatsSorceress

2
Beantwortung meiner eigenen Nebenfrage: NEIN, das ist nicht der Punkt der Nullpolsterung. Sie wählen die Filtergröße für die Eingabe (einschließlich Null-Auffüllung), wählen jedoch nicht die Null-Auffüllung nach der Filtergröße.
StatsSorceress

Ich verstehe deine eigene Antwort @StatsSorceress nicht. Es scheint mir, dass Sie genügend Nullen hinzufügen (so symmetrisch wie möglich), damit alle Eingaben von einem Filter abgedeckt werden. Stimmt das?
Guillefix

2
Gute Antwort, nur um hinzuzufügen: Für den Fall, dass die Tensorwerte negativ sein können, ist das Auffüllen für max_pooling mit -inf .
Tones29

Was ist, wenn die Eingabebreite eine gerade Zahl ist, wenn ksize = 2, stride = 2 und mit der gleichen Auffüllung? ... dann sollte sie nicht richtig mit Null aufgefüllt werden? .... Ich sage dies, wenn ich Darkflow-Code-Repo sehe verwenden sie das gleiche Pad, Schritt = 2, ksize = 2 für maxpool .... nach maxpooling Bildbreite von 416 Pixelbreite auf 208 Pixel reduziert. Kann jemand das klarstellen?
K. vindi

161

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

  • "SAME": Ausgabegröße ist gleich als Eingangsgröße. Dies erfordert, dass das Filterfenster außerhalb der Eingabekarte verschoben wird, daher muss aufgefüllt werden.
  • "VALID": Das Filterfenster bleibt an der gültigen Position innerhalb der Eingabekarte, sodass die Ausgabegröße um kleiner wird filter_size - 1. Es erfolgt keine Polsterung.

65
Das ist endlich hilfreich. Bis zu diesem Punkt schien es, dass SAMEund VALIDkann genauso gut fooundbar
omatai

7
Ich denke, "Ausgabegröße ist die gleiche wie Eingabegröße" ist nur wahr, wenn die
Schrittlänge

92

Das Beispiel der TensorFlow-Faltung gibt einen Überblick über den Unterschied zwischen SAMEund VALID:

  • Für die SAMEPolsterung werden die 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 VALIDPolsterung 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]))

46

Das Auffüllen ist eine Operation zum Erhöhen der Größe der Eingabedaten. Bei eindimensionalen 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 Null-Auffüllung bezeichnet.

Hier ist ein Beispiel für eine Nullpolsterung mit p=1Anwendung auf einen 2D-Tensor: Geben Sie hier die Bildbeschreibung ein


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

  • GÜLTIGE Polsterung . Der einfachste Fall bedeutet, dass überhaupt keine Polsterung vorhanden ist. Lassen Sie Ihre Daten einfach so, wie sie waren.
  • GLEICHE Polsterung wird manchmal als HALB-Polsterung bezeichnet . Es wird als GLEICH bezeichnet, da es für eine Faltung mit einem Schritt = 1 (oder für das Pooling) eine Ausgabe mit der gleichen Größe wie die Eingabe erzeugen sollte. Es heißt HALB, weil für einen Kernel von Größek Geben Sie hier die Bildbeschreibung ein
  • VOLLSTÄNDIGES Auffüllen ist das maximale Auffüllen, das nicht zu einer Faltung über nur aufgefüllte Elemente führt. Für einen Kernel der Größe kist diese Polsterung gleich k - 1.

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


32

Kurze Erklärung

VALID: Wenden Sie keine Auffüllung an, dh nehmen Sie an, dass alle Dimensionen gültig sind , damit das Eingabebild vollständig von dem von Ihnen angegebenen Filter und Schritt abgedeckt wird.

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

Anmerkungen

  • Dies gilt in gleicher Weise sowohl für Conv-Layer als auch für Max-Pool-Layer
  • Der Begriff "gültig" ist eine Fehlbezeichnung, da die Dinge nicht "ungültig" werden, wenn Sie einen Teil des Bildes löschen. Manchmal möchten Sie das vielleicht sogar. Dies sollte wahrscheinlich stattdessen aufgerufen NO_PADDINGwerden.
  • Der Begriff "gleich" ist ebenfalls eine Fehlbezeichnung, da er für den Schritt 1 nur dann sinnvoll ist, wenn die Ausgabedimension mit der Eingabedimension identisch ist. Bei einem Schritt von 2 betragen die Ausgangsabmessungen beispielsweise die Hälfte. Dies sollte wahrscheinlich stattdessen aufgerufen AUTO_PADDINGwerden.
  • Im SAME(dh Auto-Pad-Modus) versucht Tensorflow, die Polsterung sowohl links als auch rechts gleichmäßig zu verteilen.
  • In VALID(dh ohne Auffüllmodus) fällt der Tensorflow nach rechts und / oder in die unteren Zellen, wenn Ihr Filter und Schritt das Eingabebild nicht vollständig abdeckt.

19

Ich zitiere diese Antwort aus den offiziellen Tensorflow-Dokumenten https://www.tensorflow.org/api_guides/python/nn#Convolution. Für die 'SAME'-Auffüllung werden die 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 die Polsterung oben und links werden 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 'VALID'-Auffüllung 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 Füllwerte sind immer Null.


1
Ehrlich gesagt ist dies die einzig gültige und vollständige Antwort, nicht nur auf Schritte von 1. Und alles, was es braucht, ist ein Zitat aus den Dokumenten. +1
P-Gn

1
Es ist sehr nützlich, diese Antwort zu haben, insbesondere weil der Link, auf den Sie verweisen, nicht mehr funktioniert und Google diese Informationen anscheinend von der tf-Website gelöscht hat!
Daniel

12

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

  • Gültig oder keine Polsterung:

Die gültige Auffüllung beinhaltet keine Nullauffüllung, sodass nur die gültige Eingabe abgedeckt wird, ohne künstlich erzeugte 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 ist die Größe der Ausgänge mit der der Eingänge identisch, wenn s = 1 ist. Wenn s = 1 ist, ist die Anzahl der aufgefüllten Nullen (k-1).

  • Volle Polsterung:

Das vollständige Auffüllen bedeutet, dass der Kernel über die gesamten Eingaben läuft, sodass der Kernel an den Enden möglicherweise nur die eine Eingabe und sonst die Nullen erfüllt. Die Anzahl der aufgefüllten Nullen beträgt 2 (k-1), wenn s = 1 ist. Die Länge der Ausgabe ist ((die Länge der Eingabe) + (k-1)), wenn s = 1 ist.

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


8

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

VALID:Keine Polsterung. Faltungsoperationen usw. werden nur an Orten durchgeführt, die "gültig" sind, dh nicht zu nahe an den Grenzen Ihres Tensors.
Mit einem Kernel von 3x3 und einem Bild von 10x10 würden Sie eine Faltung im 8x8-Bereich innerhalb der Grenzen durchführen.

SAME:Polsterung ist vorhanden. Immer wenn Ihre Operation auf eine Nachbarschaft verweist (egal wie groß), werden Nullwerte bereitgestellt, wenn sich diese Nachbarschaft außerhalb des ursprünglichen Tensors erstreckt, damit diese Operation auch für Grenzwerte funktioniert.
Mit einem Kernel von 3x3 und einem Image von 10x10 würden Sie eine Faltung im gesamten 10x10-Bereich durchführen.


8

GÜLTIGE Auffüllung: Dies erfolgt mit Null-Auffüllung. 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)

GLEICHE Polsterung: Dies ist in erster Linie schwierig zu verstehen, da wir zwei Bedingungen getrennt betrachten müssen, wie in den offiziellen Dokumenten erwähnt .

Nehmen wir Eingabe als , Ausgabe als , Auffüllen als , Schritt als und Kernelgröße als (nur eine einzige Dimension wird berücksichtigt).

Fall 01: :

Fall 02: :

wird so berechnet, dass der Mindestwert, der zum Auffüllen verwendet werden kann. Da der Wert von bekannt ist, kann der Wert von unter Verwendung dieser Formel gefunden werden .

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 vertikale Richtung genommen wird (4):

Ich hoffe, dies hilft zu verstehen, wie die gleiche Auffüllung in TF tatsächlich funktioniert.


7

Basierend auf der Erklärung hier und der Weiterverfolgung von Tristans Antwort verwende ich diese Schnellfunktionen normalerweise für die Überprüfung der geistigen 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')

6

Zusammenfassend bedeutet "gültige" Polsterung keine Polsterung. Die Ausgabegröße der Faltungsschicht verringert sich abhängig von der Eingabegröße und der Kernelgröße.

Im Gegenteil, "gleiche" Polsterung bedeutet die Verwendung von Polsterung. Wenn der Schritt auf 1 gesetzt ist, bleibt die Ausgabegröße der Faltungsschicht als Eingabegröße erhalten, indem bei der Berechnung der Faltung eine bestimmte Anzahl von '0-Rändern' um die Eingabedaten angehängt wird.

Hoffe diese intuitive Beschreibung hilft.


5

Allgemeine Formel

Hier sind W und H Breite und Höhe der Eingabe, F sind Filterabmessungen, P ist die Auffüllgröße (dh die Anzahl der aufzufüllenden Zeilen oder Spalten).

Für die gleiche Polsterung:

GLEICHE Polsterung

Für gültige Polsterung:

GÜLTIGE Polsterung


2

Als Ergänzung zu YvesgereYs großartiger Antwort fand ich diese Visualisierung äußerst hilfreich:

Padding-Visualisierung

Das Auffüllen ' gültig ' ist die erste Zahl. Das Filterfenster bleibt im Bild.

Das Auffüllen von " same " ist die dritte Zahl. Die Ausgabe ist gleich groß.


Fand es auf diesem Artikel .


0

Tensorflow 2.0-kompatible Antwort : ausführliche Erläuterungen zu "Valid" und "Same" Padding gegeben.

Ich werde jedoch verschiedene Pooling-Funktionen und ihre jeweiligen Befehle Tensorflow 2.x (>= 2.0)zum Nutzen der Community angeben .

Funktionen in 1.x :

tf.nn.max_pool

tf.keras.layers.MaxPool2D

Average Pooling => None in tf.nn, tf.keras.layers.AveragePooling2D

Funktionen in 2.x :

tf.nn.max_poolbei Verwendung in 2.x und tf.compat.v1.nn.max_pool_v2oder tf.compat.v2.nn.max_poolbei Migration von 1.x auf 2.x.

tf.keras.layers.MaxPool2D wenn in 2.x und verwendet

tf.compat.v1.keras.layers.MaxPool2Doder tf.compat.v1.keras.layers.MaxPooling2Doder tf.compat.v2.keras.layers.MaxPool2Doder tf.compat.v2.keras.layers.MaxPooling2D, wenn von 1.x auf 2.x migriert.

Average Pooling => tf.nn.avg_pool2doder tf.keras.layers.AveragePooling2Dwenn in TF 2.x und verwendet

tf.compat.v1.nn.avg_pool_v2oder tf.compat.v2.nn.avg_pooloder tf.compat.v1.keras.layers.AveragePooling2Doder tf.compat.v1.keras.layers.AvgPool2Doder tf.compat.v2.keras.layers.AveragePooling2Doder tf.compat.v2.keras.layers.AvgPool2D, wenn von 1.x auf 2.x migriert.

Weitere Informationen zur Migration von Tensorflow 1.x nach 2.x finden Sie in diesem Migrationshandbuch .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.