La visión por computador es una disciplina con una gran trayectoria en las Ciencias de la Computación.
Utilizar redes densas en visión por computador es impracticable. El tamaño de una imagen, en píxeles, determina el número de neuronas en la capa de entrada y posteriores.
El número de parámetros que es necesario entrenar es muy elevado.
Las redes neuronales convolucionales están inspiradas en el funcionamiento de la percepción de la visión:
Las redes convolucionales proponen una solución basada en dos elementos:
Además, en muchos casos las últimas capas de una red convolucional están formadas por capas densas.
Esto permite utilizar redes neuronales en las tareas típicas de la visión por computador.
Las tareas típicas dentro de la visión por computador son:
Un modelo de clasificación está entrenado de tal modo que es capaz de asignar una clase, o etiqueta, a una nueva muestra.
Perro
Gato
Encontrar la caja delimitadora de un objeto dentro de una imagen:
Encontrar todos los objetos dentro de una imagen:
Asigna cada pixel a uno de los objetos detectados.
Una convolución es una operación entre los píxeles de una imagen. En estos dos casos, el paso es de 1 pixel. La figura de la derecha muestra la opción con márgenes añadidos.
En este otro caso, el paso es de 2 píxeles.
Las imágenes en color tienen tres canales: rojo, verde y azul. Las convoluciones pueden ser distintas para cada uno de los canales.
Ejemplo de convolución que emborrona una imagen:
\[ \begin{equation} \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \\ \end{bmatrix} \end{equation} \]
Ejemplo de convolución que resalta los bordes:
\[ \begin{equation} \frac{1}{9} \begin{bmatrix} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \\ \end{bmatrix} \end{equation} \]
Lo que va a aprender la red convolucional es a ajustar los valores de las matrices de convolución:
\[ \begin{equation} \begin{bmatrix} m_{1,1} & m_{1,2} & m_{1,3} \\ m_{2,1} & m_{2,2} & m_{2,3}\\ m_{3,1} & m_{3,2} & m_{3,3} \\ \end{bmatrix} \end{equation} \]
Para instanciar una capa convolucional en Keras:
tf.keras.layers.Conv2D(6,
kernel_size=(5, 5),
strides=(1, 1),
activation='tanh',
input_shape=[28, 28, 1],
padding="same")
tf.keras.layers.Conv2D(6,
kernel_size=(5, 5),
strides=(1, 1),
activation='tanh',
input_shape=[28, 28, 1],
padding="same")
El número de parámetros que hay que entrenar crece al aplicar capas de convoluciones. Una manera de reducir el número de parámetros es aplicar capas de pooling:
Keras nos proporciona capas para poder hacer pooling.
Para instanciar capas de pooling máximo en Keras:
Para instanciar capas de pooling promedio en Keras:
En ambos casos pool_size es el tamaño del lado del cuadrado de recorte.
Con estos dos nuevos tipos de capas podemos crear redes convolucionales.
Esta es la arquitectura básica de una CNN. Observa cómo se van alternando las capas convolucionales con las capas de pooling.
Al final hay una estructura de capas totalmente conectadas.
Esta es la arquitectura original presentada por Yann Le-Cunn et al.
Las Gaussian connections del final son la activación softmax.
La implementación:
lenet5 = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(6, kernel_size=(5, 5),
strides=(1, 1), activation='tanh',
input_shape=[28, 28, 1], padding="same"),
tf.keras.layers.AveragePooling2D(pool_size=(2, 2),
strides=(2, 2), padding='valid'),
tf.keras.layers.Conv2D(16, kernel_size=(5, 5),
strides=(1, 1), activation='tanh',
padding='valid'),
tf.keras.layers.AveragePooling2D(pool_size=(2, 2),
strides=(2, 2), padding='valid'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(120, activation='tanh'),
tf.keras.layers.Dense(84, activation='tanh'),
tf.keras.layers.Dense(units=10, activation='softmax')
])
En este libro de Colab tienes una implementación de LeNet5.
MINIST es el conjunto con el que se entrenó LeNet5:
Si entrenamos LeNet5 con el conjunto MNIST, utilizando como función de activación la función tanh y como optimizador Stocastic Gradient Descent (SGD), durante 20 épocas, obtenemos una precisión sobre el conjunto de pruebas del 98%!!!.
Historia
Matriz de confusión
Si utilizamos como función de activación la función relu y como optimizador Adam, durante 20 épocas, obtenemos una precisión sobre el conjunto de pruebas de casi el 99%.
Historia
Matriz de confusión
Aquí puedes comparar el desempeño de ambas implementaciones:
Tanh + sgd (precisión: 98%)
ReLu + Adam (precision: 99%)
Algunos ejemplos:
[1.0795905e-19 5.6615489e-12 1.5740088e-13 8.3432508e-14 8.5658287e-16 9.8535682e-16 3.1860348e-19 1.0000000e+00 1.1258355e-17 3.4307670e-12]
Algunos ejemplos:
[3.57783143e-16 4.28349088e-13 1.00000000e+00 1.95093300e-16 8.98499199e-17 1.41323059e-23 1.89028567e-12 1.19629157e-14 2.68268784e-17 1.12507135e-17]
En este vídeo, de 1989, tienes una demo.
Podemos probar con un conjunto de datos más difícil Fashion MNIST, que tiene el mismo número de imágenes que MNIST, pero esta vez de objetos más complejos, ropa y complementos (10 clases).
La historia del entrenamiento y la matriz de confusión:
Tanh + sgd (precisión: 88%)
Matriz de confusión
ResNet introdujo una novedad en su diseño para reducir el problema del desvanecimiento del gradiente. La novedad es en saltar capas:
\[ H(x) = F(x) + x \rightarrow F(x) = H(x) - x \]
Lo que aprenden las dos capas intermedias de la figura (representadas por la función \(F(x)\)) es a ajustar la diferencia entre la entrada real a la capa y el resultado de la aplicación de la capa.
Keras proporciona una implementación de ResNet perfectamente funcional:
resetnet50 = tf.keras.applications.ResNet50(weights="imagenet")
path = "bicicleta2.jpg"
img = tf.keras.preprocessing.image.load_img(path, target_size=[224, 224])
x = tf.keras.utils.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = tf.keras.applications.resnet50.preprocess_input(x)
y = resetnet50.predict(x)
print("Predicción: ", tf.keras.applications.resnet50.decode_predictions(y, top=3)[0])
ImageNet es un conjunto de datos con 1.000 clases , 1.281.167 imágenes de entrenamiento, 50.000 imágenes de validación y 100.000 imágenes de prueba.
En Keras hay implementadas y entrenadas un buen número de redes.
Aquí tienes la lista de todas las redes convolucionales disponibles en Keras.
You Only Look Once (YOLO) es una red convolucional con un gran desempeño en muchas de la tareas típicas en visión por computador.
YOLO es mantenida por la empresa Ultralytics.
Este es el artículo donde se presentó esta arquitectura de red neuronal.
Y esta es la arquitectura tal y como se presenta en el artículo:
Una de la novedades de YOLO es que a la salida propociona la caja envolvente de los objetos detectados, así como la probabilidad de su clasificación, y también es capaz de realizar segmentación semántica.
YOLO se presenta en varias versiones, basándose en el número de parámetros presente en la red (tamaño). Las versiones más pequeñas tienen en desempeño más bajo que las versiones grandes, pero, como contrapartida, se pueden ejecutar en dispositivos con hardware más modesto.
Todas las versiones están entrenadas con el cojunto de datos COCO.
Para comparar las prestaciones de cada modelo, vamos a empezar con el de menor tamaño, 2.6 millones de parámetros y tarea de detección:
Veamos ahora con el mayor modelo, 56.9 millones de parámetros
Pasemos ahora a la segmentación semántica, lo único que tenemos que hacer es cambiar el modelo, el resto de código es el mismo:
Con el modelo más grande para segmentación:
YOLO también es capaz de encontrar el esqueleto:
Entrenar una red convolucional desde cero es una tarea muy costosa:
Sin embargo, existe un atajo para poder (re)entrenar redes convolucionales ya existentes sobre conjuntos de datos, de nuestro interés, para tareas específicas.
El atajo consiste en lo siguiente:
3.1. Congelar los pesos de las capas preexistentes.
3.2. Entrenar hasta que la precisión sobre el conjunto de validación se estabilice.
3.3. Descongelar todas las capas y entrenar hasta conseguir una buena precisión.
Con YOLO tenemos dos opciones para reentrenas modelos:
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/coco8 # dataset root dir
train: images/train # train images (relative to 'path') 4 images
val: images/val # val images (relative to 'path') 4 images
test: # test images (optional)
# Classes (80 COCO classes)
names:
0: person
1: bicycle
2: car
# ...
77: teddy bear
78: hair drier
79: toothbrush
Ultralytics espera la siguiente estructura en los datos de entrenamiento:
Este es un ejemplo del trabajo de Arturo, estudiante de máster:
Aprendizaje Automático (IR2130) - Óscar Belmonte Fernández