wake-up-neo.com

Intuitives Verständnis von 1D-, 2D- und 3D-Konvolutionen in neuronalen Faltungsnetzen

Kann jemand bitte den Unterschied zwischen 1D-, 2D- und 3D-Faltungen in CNN (Deep Learning) anhand von Beispielen erklären?

93
xlax

Ich möchte mit Bild von C3D erklären.

Kurz gesagt, Faltungsrichtung & Ausgabeform ist wichtig!

enter image description here

↑↑↑↑↑ 1D Convolutions - Basic ↑↑↑↑↑

  • nur 1 - Richtung (Zeitachse) zur Berechnung der Konv
  • eingabe W], Filter = [k], Ausgabe = [W]
  • ex) Eingabe = [1,1,1,1,1], Filter = [0,25,0,5,0,25], Ausgabe = [1,1,1,1,1]
  • die Ausgabeform ist 1D-Array
  • beispiel) Graphenglättung

tf.nn.conv1d code Toy Example

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)

enter image description here

↑↑↑↑↑ == [- 2D Convolutions - Basic ↑↑↑↑↑

  • 2 - Richtung (x, y) zur Berechnung der Konv
  • die Ausgabeform ist eine 2D Matrix
  • eingabe W, H], Filter = [k, k] Ausgabe = [W, H]
  • beispiel) Sobel Egde Filter

tf.nn.conv2d - Spielzeugbeispiel

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)

enter image description here

↑↑↑↑↑ == [- 3D Convolutions - Basic ↑↑↑↑↑

  • 3 - Richtung (x, y, z) zur Berechnung der Konv
  • die Ausgabeform ist 3D Volumen
  • eingabe W, H, [~ # ~] 1 [~ # ~] ], Filter = [k, k, d ] output = [W, H, M]
  • d <L ist wichtig! zur Ausgabe von Volumen
  • beispiel) C3D

tf.nn.conv3d - Spielzeugbeispiel

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_depth, 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)

enter image description here

↑↑↑↑↑ == [- 2D Convolutions mit 3D-Eingabe - LeNet, VGG, ..., ↑↑↑↑ ↑

  • Obwohl die Eingabe 3D ex) 224x224x3, 112x112x32 ist
  • die Ausgabeform ist nicht 3D Volumen, sondern 2D Matrix
  • weil die Filtertiefe = [~ # ~] l [~ # ~] mit den Eingangskanälen abgeglichen werden muss = [ ~ # ~] l [~ # ~]
  • 2 - Richtung (x, y) zur Berechnung der Konvektion! nicht 3D
  • eingabe W, H, [~ # ~] 1 [~ # ~] ], Filter = [k, k, [~ # ~] l [~ # ~] ] output = [W, H]
  • ausgabeform ist 2D Matrix
  • was ist, wenn wir N Filter trainieren wollen (N ist die Anzahl der Filter)
  • dann ist die Ausgabeform eine (gestapelte 2D) 3D = 2D x N Matrix.

conv2d - LeNet, VGG, ... für 1 Filter

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)

conv2d - LeNet, VGG, ... für N-Filter

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)

enter image description here ↑↑↑↑↑ == [- Bonus 1x1 Conv in CNN - GoogLeNet, ..., ↑↑↑ ↑↑

  • 1x1 Conv ist verwirrend, wenn Sie dies als 2D-Bildfilter wie Sobel betrachten
  • für 1x1 Conv in CNN ist die Eingabe die 3D-Form wie oben abgebildet.
  • es berechnet die Tiefenfilterung
  • eingabe W, H, L], Filter = [1,1, L] Ausgabe = [W, H]
  • die gestapelte Ausgabeform ist 3D = 2D x N Matrix.

tf.nn.conv2d - Sonderfall 1x1 konv

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)

Animation (2D Conv mit 3D-Eingaben)

enter image description here - Original Link: LINK
- Der Autor: Martin Görner
- Twitter: @martin_gorner
- Google +: plus.google.com/+MartinGorne

Bonus 1D Convolutions mit 2D Eingabe

enter image description here ↑↑↑↑↑ == [- 1D Convolutions mit 1D Input ↑↑↑↑↑

enter image description here ↑↑↑↑↑ 1D Convolutions mit 2D-Eingabe ↑↑↑↑↑

  • Obwohl die Eingabe 2D ex) 20x14 ist
  • die Ausgabeform ist nicht 2D , sondern 1D Matrix
  • weil die Filterhöhe = [~ # ~] l [~ # ~] mit der Eingabehöhe = [übereinstimmen muss ~ # ~] l [~ # ~]
  • 1 - Richtung (x) zur Berechnung der Konvektion! nicht 2D
  • eingabe = [W, [~ # ~] l [~ # ~] ], Filter = [k, [~ # ~] l [~ # ~] ] output = [W]
  • die Ausgabeform ist 1D Matrix
  • was ist, wenn wir N Filter trainieren wollen (N ist die Anzahl der Filter)
  • dann ist die Ausgabeform eine (gestapelte 1D) 2D = 1D x N Matrix.

Bonus C3D

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_depth, 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()

Input & Output im Tensorflow

enter image description here

enter image description here

Zusammenfassung

enter image description here

314
runhani
  1. CNN 1D, 2D oder 3D bezieht sich eher auf die Faltungsrichtung als auf die Eingabe- oder Filterdimension.

  2. Bei 1-Kanal-Eingang entspricht CNN2D CNN1D ist Kernellänge = Eingangslänge. (1 Conv Richtung)

0
Jerry Liu