Die Pooling- und Faltungsoperationen schieben ein "Fenster" über den Eingangstensor. Die Verwendung tf.nn.conv2d
als Beispiel: Wenn der Eingang Tensor 4 Dimensionen hat: [batch, height, width, channels]
, dann arbeitet die Faltung auf einem 2D - Fenstern auf den height, width
Dimensionen.
strides
bestimmt, um wie viel sich das Fenster in jeder der Dimensionen verschiebt. Die typische Verwendung setzt den ersten (die Charge) und den letzten (die Tiefe) Schritt auf 1.
Verwenden wir ein sehr konkretes Beispiel: Ausführen einer 2D-Faltung über ein 32 x 32-Graustufen-Eingabebild. Ich sage Graustufen, weil das Eingabebild dann Tiefe = 1 hat, was hilft, es einfach zu halten. Lassen Sie das Bild so aussehen:
00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
Lassen Sie uns ein 2x2-Faltungsfenster über ein einzelnes Beispiel ausführen (Stapelgröße = 1). Wir geben der Faltung eine Ausgangskanaltiefe von 8.
Die Eingabe zur Faltung hat shape=[1, 32, 32, 1]
.
Wenn Sie angeben , strides=[1,1,1,1]
mit padding=SAME
, dann wird der Ausgang des Filters [1, 32, 32, 8].
Der Filter erstellt zunächst eine Ausgabe für:
F(00 01
10 11)
Und dann für:
F(01 02
11 12)
und so weiter. Dann geht es in die zweite Zeile und berechnet:
F(10, 11
20, 21)
dann
F(11, 12
21, 22)
Wenn Sie einen Schritt von [1, 2, 2, 1] angeben, werden keine überlappenden Fenster ausgeführt. Es wird berechnet:
F(00, 01
10, 11)
und dann
F(02, 03
12, 13)
Der Schritt funktioniert für die Pooling-Betreiber ähnlich.
Frage 2: Warum Schritte [1, x, y, 1] für Convnets
Die erste 1 ist der Stapel: Normalerweise möchten Sie keine Beispiele in Ihrem Stapel überspringen, oder Sie hätten sie gar nicht erst aufnehmen sollen. :) :)
Die letzte 1 ist die Tiefe der Faltung: Aus dem gleichen Grund möchten Sie normalerweise keine Eingaben überspringen.
Der conv2d Operator ist allgemeiner, so dass Sie könnte Faltungen, die das Fenster entlang anderen Dimensionen schieben zu schaffen, aber das ist kein typischer Einsatz in convnets. Die typische Verwendung besteht darin, sie räumlich zu verwenden.
Warum die Umformung auf -1 -1 erfolgt, ist ein Platzhalter mit der Aufschrift "Nach Bedarf anpassen, um die für den vollen Tensor erforderliche Größe anzupassen". Auf diese Weise wird der Code unabhängig von der eingegebenen Stapelgröße, sodass Sie Ihre Pipeline ändern können und die Stapelgröße nicht überall im Code anpassen müssen.