¿Alguien puede explicar claramente la diferencia entre convoluciones 1D, 2D y 3D en redes neuronales convolucionales (en aprendizaje profundo) con el uso de ejemplos?
126
¿Alguien puede explicar claramente la diferencia entre convoluciones 1D, 2D y 3D en redes neuronales convolucionales (en aprendizaje profundo) con el uso de ejemplos?
Quiero explicar con foto de C3D .
En pocas palabras, ¡la dirección convolucional y la forma de salida son importantes!
↑↑↑↑↑ Convoluciones 1D - Básico ↑↑↑↑↑
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)
↑↑↑↑↑ Convoluciones 2D - Básico ↑↑↑↑↑
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)
↑↑↑↑↑ Convoluciones 3D - Básico ↑↑↑↑↑
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)
↑↑↑↑↑ Convoluciones 2D con entrada 3D - 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)
↑↑↑↑↑ Bonificación 1x1 conv en 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)
- Enlace original: LINK
- Autor: Martin Görner
- Twitter: @martin_gorner
- Google +: plus.google.com/+MartinGorne
↑↑↑↑↑ Convoluciones 1D con entrada 1D ↑↑↑↑↑
↑↑↑↑↑ Convoluciones 1D con entrada 2D ↑↑↑↑↑
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
, luego → para fila1+stride
. La convolución en sí es invariante al desplazamiento, entonces, ¿por qué es importante la dirección de la convolución?Siguiendo la respuesta de @runhani, estoy agregando algunos detalles más para que la explicación sea un poco más clara e intentaré explicar esto un poco más (y, por supuesto, con ejemplos de TF1 y TF2).
Uno de los principales bits adicionales que incluyo son:
tf.Variable
Convolución 1D
Así es como puede hacer una convolución 1D usando TF 1 y TF 2.
Y para ser específico, mis datos tienen las siguientes formas,
[batch size, width, in channels]
(p1, 5, 1
. Ej. )[width, in channels, out channels]
(p5, 1, 4
. Ej. )[batch size, width, out_channels]
(p1, 5, 4
. Ej. )Ejemplo de TF1
Ejemplo TF2
Es mucho menos trabajo con TF2 ya que TF2 no lo necesita
Session
y,variable_initializer
por ejemplo.¿Cómo se vería esto en la vida real?
Entonces, entendamos qué está haciendo esto usando un ejemplo de suavizado de señal. A la izquierda tienes el original y a la derecha tienes la salida de un Convolution 1D que tiene 3 canales de salida.
¿Qué significan varios canales?
Los canales múltiples son básicamente representaciones de características múltiples de una entrada. En este ejemplo, tiene tres representaciones obtenidas por tres filtros diferentes. El primer canal es el filtro de suavizado de igual ponderación. El segundo es un filtro que pondera el medio del filtro más que los límites. El filtro final hace lo opuesto al segundo. Para que pueda ver cómo estos diferentes filtros producen diferentes efectos.
Aplicaciones de aprendizaje profundo de convolución 1D
La convolución 1D se ha utilizado con éxito para la tarea de clasificación de frases .
Convolución 2D
Desactivado a convolución 2D. Si eres una persona de aprendizaje profundo, las posibilidades de que no te hayas encontrado con la convolución 2D son ... bueno, aproximadamente cero. Se utiliza en CNN para clasificación de imágenes, detección de objetos, etc., así como en problemas de PNL que involucran imágenes (por ejemplo, generación de subtítulos de imágenes).
Probemos un ejemplo, obtuve un kernel de convolución con los siguientes filtros aquí,
Y para ser específico, mis datos tienen las siguientes formas,
[batch_size, height, width, 1]
(p1, 340, 371, 1
. Ej. )[height, width, in channels, out channels]
(p3, 3, 1, 3
. Ej. )[batch_size, height, width, out_channels]
(p1, 340, 371, 3
. Ej. )Ejemplo TF1,
Ejemplo TF2
¿Cómo se vería esto en la vida real?
Aquí puede ver el resultado producido por el código anterior. La primera imagen es la original y, en el sentido de las agujas del reloj, tiene salidas del primer filtro, segundo filtro y tercer filtro.
¿Qué significan varios canales?
En el contexto de la convolución 2D, es mucho más fácil comprender lo que significan estos canales múltiples. Digamos que está haciendo reconocimiento facial. Puede pensar en (esta es una simplificación muy poco realista pero transmite el punto) cada filtro representa un ojo, boca, nariz, etc. De modo que cada mapa de características sería una representación binaria de si esa característica está en la imagen que proporcionó . No creo que deba enfatizar que para un modelo de reconocimiento facial esas son características muy valiosas. Más información en este artículo .
Esta es una ilustración de lo que estoy tratando de articular.
Aplicaciones de aprendizaje profundo de convolución 2D
La convolución 2D es muy frecuente en el ámbito del aprendizaje profundo.
Las CNN (redes neuronales de convolución) utilizan la operación de convolución 2D para casi todas las tareas de visión por computadora (por ejemplo, clasificación de imágenes, detección de objetos, clasificación de video).
Convolución 3D
Ahora se vuelve cada vez más difícil ilustrar lo que sucede a medida que aumenta el número de dimensiones. Pero con una buena comprensión de cómo funciona la convolución 1D y 2D, es muy sencillo generalizar esa comprensión a la convolución 3D. Así que aquí va.
Y para ser específico, mis datos tienen las siguientes formas,
[batch size, height, width, depth, in channels]
(p1, 200, 200, 200, 1
. Ej. )[height, width, depth, in channels, out channels]
(p5, 5, 5, 1, 3
. Ej. )[batch size, width, height, width, depth, out_channels]
(p1, 200, 200, 2000, 3
. Ej. )Ejemplo TF1
Ejemplo TF2
Aplicaciones de aprendizaje profundo de convolución 3D
La convolución 3D se ha utilizado al desarrollar aplicaciones de aprendizaje automático que involucran datos LIDAR (Detección y rango de luz) que son de naturaleza tridimensional.
¿Qué ... más jerga ?: Stride and padding
Muy bien, estás casi allí. Así que aguanta. Veamos qué es la zancada y el acolchado. Son bastante intuitivos si se piensa en ellos.
Si cruzas un pasillo, llegarás más rápido en menos pasos. Pero también significa que observó un entorno menor que si caminara por la habitación. ¡Refuercemos ahora nuestra comprensión con una bonita imagen también! Entendamos esto a través de la convolución 2D.
Comprender la zancada
Cuando usa,
tf.nn.conv2d
por ejemplo, debe configurarlo como un vector de 4 elementos. No hay razón para sentirse intimidado por esto. Solo contiene los pasos en el siguiente orden.Convolución 2D -
[batch stride, height stride, width stride, channel stride]
. Aquí, paso por lotes y paso de canal que acaba de establecer en uno (he estado implementando modelos de aprendizaje profundo durante 5 años y nunca tuve que configurarlos en nada excepto uno). Así que eso te deja solo con 2 zancadas para establecer.Convolución 3D -
[batch stride, height stride, width stride, depth stride, channel stride]
. Aquí solo te preocupas por los pasos de altura / ancho / profundidad.Entendiendo el relleno
Ahora, observa que no importa cuán pequeño sea su paso (es decir, 1), hay una reducción de dimensión inevitable que ocurre durante la convolución (por ejemplo, el ancho es 3 después de convolucionar una imagen de 4 unidades de ancho). Esto no es deseable, especialmente cuando se construyen redes neuronales de convolución profunda. Aquí es donde el acolchado viene al rescate. Hay dos tipos de relleno más utilizados.
SAME
yVALID
A continuación puede ver la diferencia.
Palabra final : si tiene mucha curiosidad, es posible que se esté preguntando. Acabamos de lanzar una bomba sobre la reducción de dimensión completamente automática y ahora hablamos de tener diferentes pasos. Pero lo mejor de la zancada es que controlas cuándo y cómo se reducen las dimensiones.
fuente
CNN 1D, 2D o 3D se refiere a la dirección de convolución, en lugar de la dimensión de entrada o filtro.
Para la entrada de 1 canal, CNN2D es igual a CNN1D es la longitud del núcleo = la longitud de la entrada. (1 dirección conv.)
fuente
En resumen, en 1D CNN, el kernel se mueve en una dirección. Los datos de entrada y salida de 1D CNN son bidimensionales. Se utiliza principalmente en datos de series temporales.
En CNN 2D, el kernel se mueve en 2 direcciones. Los datos de entrada y salida de CNN 2D son tridimensionales. Se utiliza principalmente en datos de imagen.
En 3D CNN, el kernel se mueve en 3 direcciones. Los datos de entrada y salida de 3D CNN son de 4 dimensiones. Se utiliza principalmente en datos de imágenes 3D (resonancia magnética, tomografías computarizadas).
Puede encontrar más detalles aquí: https://medium.com/@xzz201920/conv1d-conv2d-and-conv3d-8a59182c4d6
fuente