Antworten:
Ich möchte mit Bild von C3D erklären .
Kurz gesagt, Faltungsrichtung und Ausgabeform sind wichtig!
↑↑↑↑↑ 1D Convolutions - Basic ↑↑↑↑↑
import tensorflow as tf
import numpy as np
sess = tf.Session()
ones_1d = np.ones(5)
weight_1d = np.ones(3)
strides_1d = 1
in_1d = tf.constant(ones_1d, dtype=tf.float32)
filter_1d = tf.constant(weight_1d, dtype=tf.float32)
in_width = int(in_1d.shape[0])
filter_width = int(filter_1d.shape[0])
input_1d = tf.reshape(in_1d, [1, in_width, 1])
kernel_1d = tf.reshape(filter_1d, [filter_width, 1, 1])
output_1d = tf.squeeze(tf.nn.conv1d(input_1d, kernel_1d, strides_1d, padding='SAME'))
print sess.run(output_1d)
↑↑↑↑↑ 2D- Konvolutionen - Grundlegend ↑↑↑↑↑
ones_2d = np.ones((5,5))
weight_2d = np.ones((3,3))
strides_2d = [1, 1, 1, 1]
in_2d = tf.constant(ones_2d, dtype=tf.float32)
filter_2d = tf.constant(weight_2d, dtype=tf.float32)
in_width = int(in_2d.shape[0])
in_height = int(in_2d.shape[1])
filter_width = int(filter_2d.shape[0])
filter_height = int(filter_2d.shape[1])
input_2d = tf.reshape(in_2d, [1, in_height, in_width, 1])
kernel_2d = tf.reshape(filter_2d, [filter_height, filter_width, 1, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_2d, kernel_2d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
↑↑↑↑↑ 3D- Konvolutionen - Grundlegend ↑↑↑↑↑
ones_3d = np.ones((5,5,5))
weight_3d = np.ones((3,3,3))
strides_3d = [1, 1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
in_depth = int(in_3d.shape[2])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
filter_depth = int(filter_3d.shape[2])
input_3d = tf.reshape(in_3d, [1, in_depth, in_height, in_width, 1])
kernel_3d = tf.reshape(filter_3d, [filter_depth, filter_height, filter_width, 1, 1])
output_3d = tf.squeeze(tf.nn.conv3d(input_3d, kernel_3d, strides=strides_3d, padding='SAME'))
print sess.run(output_3d)
↑↑↑↑↑ 2D-Faltungen mit 3D-Eingabe - LeNet, VGG, ..., ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae with in_channels
weight_3d = np.ones((3,3,in_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_3d = tf.reshape(filter_3d, [filter_height, filter_width, in_channels, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_3d, kernel_3d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
↑↑↑↑↑ Bonus 1x1 Conv in CNN - GoogLeNet, ..., ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((1,1,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
- Original Link: LINK
- Der Autor: Martin Görner
- Twitter: @martin_gorner
- Google +: plus.google.com/+MartinGorne
↑↑↑↑↑ 1D-Faltungen mit 1D-Eingang ↑↑↑↑↑
↑↑↑↑↑ 1D Faltungen mit 2D-Eingabe ↑↑↑↑↑
in_channels = 32 # 3, 32, 64, 128, ...
out_channels = 64 # 3, 32, 64, 128, ...
ones_4d = np.ones((5,5,5,in_channels))
weight_5d = np.ones((3,3,3,in_channels,out_channels))
strides_3d = [1, 1, 1, 1, 1]
in_4d = tf.constant(ones_4d, dtype=tf.float32)
filter_5d = tf.constant(weight_5d, dtype=tf.float32)
in_width = int(in_4d.shape[0])
in_height = int(in_4d.shape[1])
in_depth = int(in_4d.shape[2])
filter_width = int(filter_5d.shape[0])
filter_height = int(filter_5d.shape[1])
filter_depth = int(filter_5d.shape[2])
input_4d = tf.reshape(in_4d, [1, in_depth, in_height, in_width, in_channels])
kernel_5d = tf.reshape(filter_5d, [filter_depth, filter_height, filter_width, in_channels, out_channels])
output_4d = tf.nn.conv3d(input_4d, kernel_5d, strides=strides_3d, padding='SAME')
print sess.run(output_4d)
sess.close()
1
, dann → für Zeile ist 1+stride
. Die Faltung selbst ist verschiebungsinvariant. Warum ist die Richtung der Faltung wichtig?
Nach der Antwort von @runhani füge ich ein paar weitere Details hinzu, um die Erklärung etwas klarer zu machen, und werde versuchen, dies etwas genauer zu erklären (und natürlich mit Beispielen aus TF1 und TF2).
Eines der wichtigsten zusätzlichen Elemente, die ich einbeziehe, sind:
tf.Variable
Hier erfahren Sie, wie Sie eine 1D-Faltung mit TF 1 und TF 2 durchführen können.
Und um genau zu sein, meine Daten haben folgende Formen:
[batch size, width, in channels]
(z 1, 5, 1
)[width, in channels, out channels]
(zB 5, 1, 4
)[batch size, width, out_channels]
(zB 1, 5, 4
)import tensorflow as tf
import numpy as np
inp = tf.placeholder(shape=[None, 5, 1], dtype=tf.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5, 1, 4]), dtype=tf.float32)
out = tf.nn.conv1d(inp, kernel, stride=1, padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(sess.run(out, feed_dict={inp: np.array([[[0],[1],[2],[3],[4]],[[5],[4],[3],[2],[1]]])}))
import tensorflow as tf
import numpy as np
inp = np.array([[[0],[1],[2],[3],[4]],[[5],[4],[3],[2],[1]]]).astype(np.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5, 1, 4]), dtype=tf.float32)
out = tf.nn.conv1d(inp, kernel, stride=1, padding='SAME')
print(out)
Es ist viel weniger Arbeit mit TF2 als TF2 nicht braucht Session
und variable_initializer
zum Beispiel.
Lassen Sie uns anhand eines Beispiels zur Signalglättung verstehen, was dies bewirkt. Links haben Sie das Original und rechts haben Sie den Ausgang einer Convolution 1D mit 3 Ausgangskanälen.
Mehrere Kanäle sind im Grunde mehrere Feature-Darstellungen eines Eingangs. In diesem Beispiel haben Sie drei Darstellungen, die von drei verschiedenen Filtern erhalten wurden. Der erste Kanal ist der gleichgewichtete Glättungsfilter. Der zweite ist ein Filter, der die Mitte des Filters mehr als die Grenzen gewichtet. Der letzte Filter macht das Gegenteil des zweiten. So können Sie sehen, wie diese verschiedenen Filter unterschiedliche Effekte bewirken.
1D Faltung wurde für die verwendete erfolgreiche Satz Klassifikationsaufgabe.
Aus zur 2D-Faltung. Wenn Sie eine tief lernende Person sind, ist die Wahrscheinlichkeit, dass Sie nicht auf 2D-Faltung gestoßen sind,… ungefähr Null. Es wird in CNNs zur Bildklassifizierung, Objekterkennung usw. sowie bei NLP-Problemen verwendet, die Bilder betreffen (z. B. Erzeugung von Bildunterschriften).
Versuchen wir ein Beispiel: Ich habe hier einen Faltungskern mit den folgenden Filtern:
Und um genau zu sein, meine Daten haben folgende Formen:
[batch_size, height, width, 1]
(zB 1, 340, 371, 1
)[height, width, in channels, out channels]
(zB 3, 3, 1, 3
)[batch_size, height, width, out_channels]
(z 1, 340, 371, 3
)import tensorflow as tf
import numpy as np
from PIL import Image
im = np.array(Image.open(<some image>).convert('L'))#/255.0
kernel_init = np.array(
[
[[[-1, 1.0/9, 0]],[[-1, 1.0/9, -1]],[[-1, 1.0/9, 0]]],
[[[-1, 1.0/9, -1]],[[8, 1.0/9,5]],[[-1, 1.0/9,-1]]],
[[[-1, 1.0/9,0]],[[-1, 1.0/9,-1]],[[-1, 1.0/9, 0]]]
])
inp = tf.placeholder(shape=[None, image_height, image_width, 1], dtype=tf.float32)
kernel = tf.Variable(kernel_init, dtype=tf.float32)
out = tf.nn.conv2d(inp, kernel, strides=[1,1,1,1], padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
res = sess.run(out, feed_dict={inp: np.expand_dims(np.expand_dims(im,0),-1)})
import tensorflow as tf
import numpy as np
from PIL import Image
im = np.array(Image.open(<some image>).convert('L'))#/255.0
x = np.expand_dims(np.expand_dims(im,0),-1)
kernel_init = np.array(
[
[[[-1, 1.0/9, 0]],[[-1, 1.0/9, -1]],[[-1, 1.0/9, 0]]],
[[[-1, 1.0/9, -1]],[[8, 1.0/9,5]],[[-1, 1.0/9,-1]]],
[[[-1, 1.0/9,0]],[[-1, 1.0/9,-1]],[[-1, 1.0/9, 0]]]
])
kernel = tf.Variable(kernel_init, dtype=tf.float32)
out = tf.nn.conv2d(x, kernel, strides=[1,1,1,1], padding='SAME')
Hier sehen Sie die Ausgabe, die durch den obigen Code erzeugt wird. Das erste Bild ist das Original und im Uhrzeigersinn haben Sie Ausgänge des 1. Filters, 2. Filters und 3 Filters.
Im Zusammenhang mit 2D-Faltung ist es viel einfacher zu verstehen, was diese mehreren Kanäle bedeuten. Angenommen, Sie machen Gesichtserkennung. Sie können sich vorstellen (dies ist eine sehr unrealistische Vereinfachung, bringt aber den Punkt auf den Punkt), dass jeder Filter ein Auge, einen Mund, eine Nase usw. darstellt, sodass jede Feature-Map eine binäre Darstellung dessen ist, ob dieses Feature in dem von Ihnen bereitgestellten Bild vorhanden ist . Ich glaube nicht, dass ich betonen muss, dass dies für ein Gesichtserkennungsmodell sehr wertvolle Merkmale sind. Weitere Informationen in diesem Artikel .
Dies ist eine Illustration dessen, was ich zu artikulieren versuche.
2D-Faltung ist im Bereich des tiefen Lernens sehr verbreitet.
CNNs (Convolution Neural Networks) verwenden 2D-Faltungsoperationen für fast alle Computer-Vision-Aufgaben (z. B. Bildklassifizierung, Objekterkennung, Videoklassifizierung).
Jetzt wird es immer schwieriger zu veranschaulichen, was mit zunehmender Anzahl von Dimensionen vor sich geht. Mit einem guten Verständnis der Funktionsweise von 1D- und 2D-Faltung ist es jedoch sehr einfach, dieses Verständnis auf 3D-Faltung zu verallgemeinern. Also los geht's.
Und um genau zu sein, meine Daten haben folgende Formen:
[batch size, height, width, depth, in channels]
(z 1, 200, 200, 200, 1
)[height, width, depth, in channels, out channels]
(zB 5, 5, 5, 1, 3
)[batch size, width, height, width, depth, out_channels]
(zB 1, 200, 200, 2000, 3
)import tensorflow as tf
import numpy as np
tf.reset_default_graph()
inp = tf.placeholder(shape=[None, 200, 200, 200, 1], dtype=tf.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5,5,5,1,3]), dtype=tf.float32)
out = tf.nn.conv3d(inp, kernel, strides=[1,1,1,1,1], padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
res = sess.run(out, feed_dict={inp: np.random.normal(size=(1,200,200,200,1))})
import tensorflow as tf
import numpy as np
x = np.random.normal(size=(1,200,200,200,1))
kernel = tf.Variable(tf.initializers.glorot_uniform()([5,5,5,1,3]), dtype=tf.float32)
out = tf.nn.conv3d(x, kernel, strides=[1,1,1,1,1], padding='SAME')
Die 3D-Faltung wurde bei der Entwicklung von Anwendungen für maschinelles Lernen verwendet, die dreidimensionale LIDAR-Daten (Light Detection and Ranging) enthalten.
Okay, du bist fast da. Also halte durch. Mal sehen, was Schritt und Polsterung ist. Sie sind sehr intuitiv, wenn Sie an sie denken.
Wenn Sie über einen Korridor gehen, gelangen Sie in weniger Schritten schneller dorthin. Es bedeutet aber auch, dass Sie eine geringere Umgebung beobachtet haben, als wenn Sie durch den Raum gegangen wären. Lassen Sie uns jetzt unser Verständnis mit einem schönen Bild verstärken! Lassen Sie uns diese über 2D-Faltung verstehen.
Wenn Sie tf.nn.conv2d
zum Beispiel verwenden, müssen Sie es als Vektor von 4 Elementen festlegen. Es gibt keinen Grund, sich davon einschüchtern zu lassen. Es enthält nur die Schritte in der folgenden Reihenfolge.
2D-Faltung - [batch stride, height stride, width stride, channel stride]
. Hier haben Sie Batch-Schritt und Kanal-Schritt nur auf eins gesetzt (ich implementiere seit 5 Jahren Deep-Learning-Modelle und musste sie nie auf etwas anderes als eins setzen). Sie haben also nur noch 2 Schritte zum Setzen.
3D Faltung - [batch stride, height stride, width stride, depth stride, channel stride]
. Hier kümmern Sie sich nur um Höhen-, Breiten- und Tiefenschritte.
Jetzt bemerken Sie, dass unabhängig davon, wie klein Ihr Schritt ist (dh 1), während der Faltung eine unvermeidbare Dimensionsreduzierung auftritt (z. B. beträgt die Breite 3 nach dem Falten eines 4 Einheiten breiten Bildes). Dies ist insbesondere beim Aufbau neuronaler Netze mit tiefer Faltung unerwünscht. Hier hilft die Polsterung. Es gibt zwei am häufigsten verwendete Polstertypen.
SAME
und VALID
Unten sehen Sie den Unterschied.
Letztes Wort : Wenn Sie sehr neugierig sind, fragen Sie sich vielleicht. Wir haben gerade eine Bombe auf die vollständige automatische Dimensionsreduzierung abgeworfen und sprechen jetzt davon, unterschiedliche Schritte zu machen. Das Beste am Schritt ist jedoch, dass Sie steuern, wann und wie die Abmessungen reduziert werden.
Zusammenfassend bewegt sich der Kernel in 1D CNN in eine Richtung. Die Eingabe- und Ausgabedaten von 1D CNN sind zweidimensional. Wird hauptsächlich für Zeitreihendaten verwendet.
In 2D CNN bewegt sich der Kernel in zwei Richtungen. Die Eingabe- und Ausgabedaten von 2D-CNN sind dreidimensional. Wird hauptsächlich für Bilddaten verwendet.
In 3D CNN bewegt sich der Kernel in drei Richtungen. Die Eingabe- und Ausgabedaten von 3D CNN sind 4-dimensional. Wird hauptsächlich für 3D-Bilddaten (MRT, CT) verwendet.
Weitere Informationen finden Sie hier: https://medium.com/@xzz201920/conv1d-conv2d-and-conv3d-8a59182c4d6