Ich habe mir tf.nn.conv2d
hier die Dokumente von Tensorflow angesehen . Aber ich kann nicht verstehen, was es tut oder was es zu erreichen versucht. Es steht auf den Dokumenten,
# 1: Glättet den Filter zu einer 2-D-Matrix mit Form
[filter_height * filter_width * in_channels, output_channels]
.
Was macht das nun? Ist das eine elementweise Multiplikation oder nur eine einfache Matrixmultiplikation? Ich konnte auch die beiden anderen in den Dokumenten erwähnten Punkte nicht verstehen. Ich habe sie unten geschrieben:
# 2: Extrahiert Bildfelder aus dem Eingangstensor, um einen virtuellen Formtensor zu bilden
[batch, out_height, out_width, filter_height * filter_width * in_channels]
.# 3: Für jedes Patch multipliziert rechts die Filtermatrix und den Bild-Patch-Vektor.
Es wäre wirklich hilfreich, wenn jemand ein Beispiel geben könnte, vielleicht einen Code (äußerst hilfreich) und erklären könnte, was dort vor sich geht und warum die Operation so ist.
Ich habe versucht, einen kleinen Teil zu codieren und die Form der Operation auszudrucken. Trotzdem kann ich nicht verstehen.
Ich habe so etwas versucht:
op = tf.shape(tf.nn.conv2d(tf.random_normal([1,10,10,10]),
tf.random_normal([2,10,10,10]),
strides=[1, 2, 2, 1], padding='SAME'))
with tf.Session() as sess:
result = sess.run(op)
print(result)
Ich verstehe Teile von Faltungs-Neuronalen Netzen. Ich habe sie hier studiert . Aber die Implementierung von Tensorflow entspricht nicht meinen Erwartungen. Also warf es die Frage auf.
EDIT : Also habe ich einen viel einfacheren Code implementiert. Aber ich kann nicht herausfinden, was los ist. Ich meine, wie die Ergebnisse so sind. Es wäre äußerst hilfreich, wenn mir jemand sagen könnte, welcher Prozess diese Ausgabe liefert.
input = tf.Variable(tf.random_normal([1,2,2,1]))
filter = tf.Variable(tf.random_normal([1,1,1,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
print("input")
print(input.eval())
print("filter")
print(filter.eval())
print("result")
result = sess.run(op)
print(result)
Ausgabe
input
[[[[ 1.60314465]
[-0.55022103]]
[[ 0.00595062]
[-0.69889867]]]]
filter
[[[[-0.59594476]]]]
result
[[[[-0.95538563]
[ 0.32790133]]
[[-0.00354624]
[ 0.41650501]]]]
quelle
tf.nn.conv2d()
, daher wird die betreffende Methode überhaupt nicht verwendet, wenn TF mit GPU-Unterstützung verwendet wird, esuse_cudnn_on_gpu=False
sei denn, dies ist explizit angegeben.Antworten:
Die 2D-Faltung wird auf ähnliche Weise berechnet wie die 1D-Faltung : Sie schieben Ihren Kernel über die Eingabe, berechnen die elementweisen Multiplikationen und fassen sie zusammen. Aber anstatt dass Ihr Kernel / Ihre Eingabe ein Array ist, sind sie hier Matrizen.
Im einfachsten Beispiel gibt es keine Polsterung und Schritt = 1. Nehmen wir an, Sie sind
input
undkernel
sind:Wenn Sie Ihren Kernel verwenden, erhalten Sie die folgende Ausgabe : , die wie folgt berechnet wird:
Die conv2d- Funktion von TF berechnet Faltungen in Stapeln und verwendet ein etwas anderes Format. Für eine Eingabe ist es
[batch, in_height, in_width, in_channels]
für den Kernel[filter_height, filter_width, in_channels, out_channels]
. Wir müssen also die Daten im richtigen Format bereitstellen:Danach wird die Faltung berechnet mit:
Und entspricht dem, den wir von Hand berechnet haben.
Für Beispiele mit Polsterung / Fortschritte, finden hier sehen .
quelle
Ok, ich denke, das ist der einfachste Weg, alles zu erklären.
Ihr Beispiel ist 1 Bild, Größe 2x2, mit 1 Kanal. Sie haben 1 Filter mit der Größe 1x1 und 1 Kanal (Größe ist Höhe x Breite x Kanäle x Anzahl der Filter).
Für diesen einfachen Fall ist das resultierende 2x2, 1-Kanal-Bild (Größe 1x2x2x1, Anzahl der Bilder x Höhe x Breite xx Kanäle) das Ergebnis der Multiplikation des Filterwerts mit jedem Pixel des Bildes.
Probieren wir jetzt weitere Kanäle aus:
Hier haben das 3x3-Bild und der 1x1-Filter jeweils 5 Kanäle. Das resultierende Bild ist 3x3 mit 1 Kanal (Größe 1x3x3x1), wobei der Wert jedes Pixels das Punktprodukt über die Kanäle des Filters mit dem entsprechenden Pixel im Eingabebild ist.
Jetzt mit einem 3x3 Filter
Hier erhalten wir ein 1x1 Bild mit 1 Kanal (Größe 1x1x1x1). Der Wert ist die Summe der 9, 5-Element-Punktprodukte. Man könnte dies aber auch als ein Produkt mit 45 Elementen bezeichnen.
Jetzt mit einem größeren Bild
Die Ausgabe ist ein 3x3 1-Kanal-Bild (Größe 1x3x3x1). Jeder dieser Werte ist eine Summe von 9 5-Element-Punktprodukten.
Jede Ausgabe erfolgt durch Zentrieren des Filters auf einem der 9 mittleren Pixel des Eingabebildes, so dass keiner der Filter hervorsteht. Die folgenden
x
s repräsentieren die Filterzentren für jedes Ausgangspixel.Jetzt mit "SAME" -Polsterung:
Dies ergibt ein 5x5-Ausgabebild (Größe 1x5x5x1). Dies erfolgt durch Zentrieren des Filters an jeder Position im Bild.
Jedes der 5-Element-Punktprodukte, bei denen der Filter über den Bildrand hinausragt, erhält den Wert Null.
Die Ecken sind also nur Summen von 4, 5-Element-Punktprodukten.
Jetzt mit mehreren Filtern.
Dies ergibt immer noch ein 5x5-Ausgabebild, jedoch mit 7 Kanälen (Größe 1x5x5x7). Wobei jeder Kanal von einem der Filter im Set erzeugt wird.
Jetzt mit Schritten 2,2:
Jetzt hat das Ergebnis noch 7 Kanäle, ist aber nur 3x3 (Größe 1x3x3x7).
Dies liegt daran, dass die Filter nicht an jedem Punkt des Bildes zentriert werden, sondern an jedem anderen Punkt des Bildes zentriert werden, wobei Schritte (Schritte) der Breite 2 ausgeführt werden. Die
x
folgenden Werte geben die Filtermitte für jedes Ausgabepixel an das Eingabebild.Und natürlich ist die erste Dimension der Eingabe die Anzahl der Bilder, sodass Sie sie auf einen Stapel von 10 Bildern anwenden können, zum Beispiel:
Dies führt die gleiche Operation für jedes Bild unabhängig aus und ergibt einen Stapel von 10 Bildern als Ergebnis (Größe 10x3x3x7).
quelle
Must have strides[0] = strides[3] = 1. For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1].
the 3x3 image and the 1x1 filter each have 5 channels
das Ergebnis vom manuell berechneten Punktprodukt abweicht.Um die anderen Antworten zu ergänzen, sollten Sie an die Parameter in denken
als '5' entsprechend der Anzahl der Kanäle in jedem Filter. Jeder Filter ist ein 3D-Würfel mit einer Tiefe von 5. Ihre Filtertiefe muss der Tiefe Ihres Eingabebildes entsprechen. Der letzte Parameter, 7, sollte als Anzahl der Filter im Stapel betrachtet werden. Vergessen Sie einfach, dass dies 4D ist, und stellen Sie sich stattdessen vor, Sie haben einen Satz oder einen Stapel von 7 Filtern. Sie erstellen 7 Filterwürfel mit den Abmessungen (3,3,5).
Es ist viel einfacher, im Fourier-Bereich zu visualisieren, da die Faltung zur punktweisen Multiplikation wird. Für ein Eingabebild mit Abmessungen (100, 100, 3) können Sie die Filterabmessungen wie folgt umschreiben
Um eine der 7 Ausgabe-Feature-Maps zu erhalten, führen wir einfach die punktweise Multiplikation des Filterwürfels mit dem Bildwürfel durch. Dann summieren wir die Ergebnisse über die Kanal- / Tiefen-Dimension (hier 3) und reduzieren sie auf 2d (100.100) Feature-Map. Wenn Sie dies mit jedem Filterwürfel tun, erhalten Sie 7 2D-Feature-Maps.
quelle
Ich habe versucht, conv2d (für mein Studium) zu implementieren. Nun, das habe ich geschrieben:
Hoffe ich habe es richtig gemacht. Auf MNIST überprüft, hatte sehr enge Ergebnisse (aber diese Implementierung ist langsamer). Ich hoffe das hilft dir.
quelle
Zusätzlich zu anderen Antworten wird die conv2d-Operation in c ++ (cpu) oder cuda für GPU-Maschinen ausgeführt, bei denen Daten auf bestimmte Weise reduziert und umgeformt werden müssen und die Matrixmultiplikation gemmBLAS oder cuBLAS (cuda) verwendet werden muss.
quelle