Implementando Convoluciones con Python
Nuestra secuencia de comandos solo requiere un único argumento de línea de comando, --image, que es la ruta a nuestra imagen de entrada. Luego podemos definir dos núcleos utilizados para difuminar y suavizar una imagen:
Para ayudarnos a comprender mejor el concepto de convoluciones, veamos algunos códigos reales que revelarán cómo se implementan los núcleos y las convoluciones. Este código fuente no solo lo ayudará a comprender cómo aplicar las convoluciones a las imágenes, sino que también le permitirá comprender lo que sucede debajo del capó al capacitar a las CNN. Abra un nuevo archivo, llámalo convolutions.py y comencemos a trabajar:
Comenzamos en Lines2-5 importando nuestros paquetes Python requeridos. Usaremos NumPy y OpenCV para nuestras funciones estándar de procesamiento numérico de matrices y visión computacional, junto con la biblioteca de imágenes de scikit para ayudarnos a implementar nuestra propia función de convolución personalizada. A continuación, podemos comenzar a definir este método de convolución:
La función de convolución requiere dos parámetros: la imagen (escala de grises) que queremos que convierta con el núcleo. Dada nuestra imagen y nuestro núcleo (que presumimos que son matrices NumPy), luego determinamos las dimensiones espaciales (es decir, el ancho y el alto) de cada una (Líneas 10 y 11).
Antes de continuar, es importante comprender el proceso de "deslizar" una matriz convolucional a través de una imagen, aplicar la convolución y luego almacenar la salida, lo que en realidad disminuirá las dimensiones espaciales de nuestra imagen de entrada. ¿Por qué es esto?
Recuerde que "centramos" nuestro cálculo en torno al centro (x, y) -coordinado de la imagen de entrada que el equipo se encuentra más o menos al lado. Esta ubicación es simple, ya que no hay píxeles "centrales" para los píxeles que caen a lo largo del borde de la imagen (ya que las esquinas del kernel estarían "colgando" la imagen donde los valores no están definidos), como se muestra en la Figura 11.3.
La disminución en la dimensión espacial es simplemente un efecto secundario de aplicar circunvoluciones a las imágenes. A veces, este efecto es deseable, y otras no, simplemente depende de su aplicación. Sin embargo, en la mayoría de los casos, queremos que nuestra imagen de salida tenga las mismas dimensiones que nuestra imagen de entrada. Para garantizar que las dimensiones sean las mismas, aplicamos relleno (Líneas 15-18). Aquí simplemente estamos replicando los píxeles a lo largo del borde de la imagen, de modo que la imagen de salida coincidirá con las dimensiones de la imagen de entrada.
Existen otros métodos de relleno, incluido el relleno cero (rellenar los bordes con ceros, muy común al crear redes neuronales convolucionales) y envolver (donde los píxeles del borde se determinan al examinar el lado opuesto de la imagen). En la mayoría de los casos, verá duplicado o cero relleno. El relleno de réplica se usa más en comunicaciones solo cuando se trata de una estética, mientras que el relleno de cero es el mejor para la eficiencia. Ahora estamos listos para aplicar la convolución real a nuestra imagen:
en la matriz de salida en las mismas coordenadas (x, y) (relativas a la imagen de entrada). Ahora podemos terminar nuestro método de convolución:
Cuando se trabaja con imágenes, normalmente tratamos con valores de píxeles que se encuentran en el rango [0,255]. Sin embargo, al aplicar convoluciones, podemos obtener fácilmente valores que caen fuera de este rango. Para que nuestra imagen de salida vuelva al rango [0,255], aplicamos la función rescale_intensity de scikit-image (Linea 39). También convertimos nuestra imagen a un tipo de datos enteros de 8 bits sin firmar en la Linea 40 (anteriormente, la imagen de salida era un tipo de punto flotante para manejar valores de píxeles fuera del rango [0,255]). Finalmente, la imagen de salida se devuelve a la función de llamada en la Linea 43. Ahora que hemos definido nuestra función de convolución, pasemos a la parte del controlador del script. Esta sección de nuestro programa manejará el análisis de los argumentos de la línea de comando, definiendo una serie de núcleos que vamos a aplicar a nuestra imagen y luego mostrando los resultados de salida:
Para convencerse de que este kernel se está desenfocando, observe cómo cada entrada en el kernel es un promedio de 1/S, donde S es el número total de entradas en la matriz. Por lo tanto, este kernel multiplicará cada píxel de entrada por una pequeña fracción y tomará la suma; esta es exactamente la definición del promedio. Luego tenemos un kernel responsable de afilar una imagen:
Luego tenemos un kernel responsable de afilar (sharpening) una imagen:
Then the Laplacian kernel used to detect edge-like regions:
The Sobel kernels can be used to detect edge-like regions along both the x and y axis, respectively:
Explicar cómo se formuló cada uno de estos kernels está fuera del alcance de este libro, por lo que, por el momento, simplemente entienda que estos kernels se construyeron manualmente para realizar una operación determinada.
Para un tratamiento exhaustivo de cómo se construyen matemáticamente los núcleos y se demuestra que realizan una determinada operación de procesamiento de imágenes, consulte Szeliksi (Capítulo 3) [119]. También recomiendo usar esta excelente herramienta de visualización de kernel de Setosa.io [120]. Dados todos estos núcleos, podemos agruparlos en un conjunto de tuplas llamado "banco del núcleo":
La construcción de esta lista de núcleos permite su uso para recorrerlos y visualizar su salida de manera eficiente, como lo demuestra el siguiente bloque de código:
Las líneas 99 y 100 cargan nuestra imagen desde el disco y la convierten a escala de grises. Los operadores de convolución pueden y se aplican a RGB u otros volúmenes multicanal, pero para simplificar, solo aplicaremos nuestros filtros a las imágenes en escala de grises.
Comenzamos a recorrer nuestro conjunto de kernels en el kernelBank en la Línea 103 y luego aplicamos el kernel actual a la imagen gris en Line104 llamando a nuestro método de convolución de función, definido antes en el script.
Como control de cordura, también llamamos cv2.filter2D, que también aplica nuestro kernel a la imagen gris. La función cv2.filter2D es la versión mucho más optimizada de OpenCV de nuestra función de convolución.
La razón principal por la que incluyo ambos aquí es para que podamos revisar nuestra implementación personalizada.
Finalmente, las Líneas 111-115 muestran las imágenes de salida a nuestra pantalla para cada tipo de kernel.
Resultados de la convolución.
Para ejecutar nuestro script (y visualizar la salida de varias operaciones de convolución), solo tiene que ejecutar el siguiente comando:
$ python convolutions.py --image jemma.png
Luego verás los resultados de la aplicación del núcleo smallBlur a la imagen de entrada en la Figura 11.4. A la izquierda, tenemos nuestra imagen original. Luego, en el centro, tenemos los resultados de la función de convolución. Y a la derecha, los resultados de cv2.filter2D.
Una inspección visual rápida revelará que nuestra salida coincide con cv2.filter2D, lo que indica que nuestra función de convolución está funcionando correctamente. Además, nuestra imagen ahora aparece "borrosa" y "suavizada", gracias al núcleo suavizado. Apliquemos un desenfoque más grande, cuyos resultados se pueden ver en la Figura 11.5 (arriba a la izquierda). Esta vez estoy omitiendo los resultados de cv2.filter2D para ahorrar espacio.
Comparando los resultados de la Figura 11.5 a la Figura 11.4, observe cómo como el tamaño de los aumentos del núcleo de promediación, la cantidad de desenfoque en la imagen de salida aumenta también. También podemos enfocar nuestra imagen (Figura 11.5, medio superior) y detectar regiones similares a los bordes a través del operador laplaciano (arriba a la derecha).
El kernel de sobelX se usa para encontrar bordes verticales en la imagen (Figura 11.5, abajo a la izquierda), mientras que el kernel de sobelY revela bordes horizontales (de abajo a la mitad). Por último, podemos ver el resultado del núcleo de relieve en la parte inferior izquierda.
El papel de las convoluciones en el aprendizaje profundo
Como se ha reunido en esta sección, debemos de fi nir manualmente cada uno de nuestros núcleos para cada una de nuestras diversas operaciones de procesamiento de imágenes, como suavizado, nitidez y detección de bordes. Todo eso es bueno y bueno, pero ¿qué pasaría si no aprendiera estos filtros en su lugar? ¿Es posible de fi nir un algoritmo de aprendizaje automático que pueda mirar nuestras imágenes de entrada y eventualmente aprender este tipo de operadores? De hecho, hay - estos tipos de algoritmos son el enfoque principal de este libro: Convolutional Neural Networks (CNNs). Al aplicar filtros de convoluciones, funciones de activación no lineales, agrupación y propagación hacia atrás, las CNN pueden aprender a filtrar y detectar bordes y estructuras en forma de burbujas en capas de la red de niveles inferiores, y luego usar los bordes y las estructuras como "bloques de construcción". , eventualmente detectando objetos de alto nivel (por ejemplo, caras, gatos, perros, tazas, etc.) en las capas más profundas de la red. Este proceso de usar las capas de nivel inferior para aprender características de alto nivel es exactamente la composición de las CNN a las que nos referíamos anteriormente. ¿Pero exactamente cómo hacen esto las CNN? La respuesta es apilar un conjunto específico de capas de una manera determinada. En la siguiente sección, analizaremos estos tipos de capas, y luego examinaremos los patrones comunes de apilamiento de capas que se utilizan ampliamente entre muchas tareas de clasificación de imágenes.
Bloques de construcción de la CNN (CNN Building Blocks)
Como aprendimos en el Capítulo 10, las redes neuronales aceptan un vector de imagen/entidad de entrada (un nodo de entrada para cada entrada) y lo transforman a través de una serie de capas ocultas, comúnmente utilizando funciones de activación no lineales. Cada capa oculta también está formada por un conjunto de neuronas, donde cada neurona está completamente conectada a todas las neuronas de la capa anterior. La última capa de una red neuronal (es decir, la "capa de salida") también está completamente conectada y representa las clasificaciones finales de salida de la red.
Sin embargo, como demuestran los resultados de la Sección 10.1.4, las redes neuronales que operan directamente en intensidades de píxeles sin procesar:
1. No escalar bien a medida que aumenta el tamaño de la imagen.
2. Deja que se desee mucha precisión (es decir, una red de inscripciones anticipada estándar en CIFAR-10 obtuvo solo el 15% de precisión).
Para demostrar cómo las redes neuronales estándar no se escalan bien a medida que aumenta el tamaño de la imagen, consideremos nuevamente el conjunto de datos CIFAR-10. Cada imagen en CIFAR-10 es 32 × 32 con un canal Rojo, Verde y Azul, lo que da un total de 32 × 32 × 3 = 3,072 entradas totales a nuestra red.
Un total de 3,072 entradas no parece ser mucho, pero considere que si estuviéramos usando imágenes de 250 × 250 píxeles, el número total de entradas y pesos saltaría a 250 × 250 × 3 = 187,500, y este número es solo para el capa de entrada solo! Seguramente, nos gustaría agregar varias capas ocultas con un número variable de nodos por posición: estos parámetros pueden sumarse rápidamente y, dado el bajo rendimiento de las redes neuronales estándar en intensidades de píxeles sin procesar, esta acumulación no vale la pena.
En su lugar, podemos usar redes neuronales convolucionales (CNN) que aprovechan la estructura de la imagen de entrada y definen una arquitectura de red de una manera más sensible. A diferencia de una red neuronal estándar, las capas de una CNN se organizan en un volumen 3D en tres dimensiones: ancho, alto y profundidad (donde la profundidad se refiere a la tercera dimensión del volumen, como el número de canales en una imagen o el número de fi ltros en una capa).
Para hacer este ejemplo más concreto, considere nuevamente el conjunto de datos CIFAR-10: el volumen de entrada tendrá dimensiones 32 × 32 × 3 (ancho, altura y profundidad, respectivamente). Las neuronas en capas subsiguientes estarán conectadas a una pequeña región de la capa anterior (en lugar de la estructura tan conectada de una red neuronal estándar): llamamos a esta conectividad local que nos permite guardar una gran cantidad de parámetros en nuestra red. Finalmente, la capa de salida será un volumen de 1 × 1 × N que representa la imagen destilada en un único vector de puntuaciones de clase. En el caso de CIFAR-10, dadas diez clases, N = 10, produciendo un volumen de 1 × 1 × 10.
Tipos de capas
Existen muchos tipos de capas utilizadas para construir redes neuronales convolucionales, pero las que es más probable que encuentre incluyen:
El papel de las convoluciones en el aprendizaje profundo
Como se ha reunido en esta sección, debemos de fi nir manualmente cada uno de nuestros núcleos para cada una de nuestras diversas operaciones de procesamiento de imágenes, como suavizado, nitidez y detección de bordes. Todo eso es bueno y bueno, pero ¿qué pasaría si no aprendiera estos filtros en su lugar? ¿Es posible de fi nir un algoritmo de aprendizaje automático que pueda mirar nuestras imágenes de entrada y eventualmente aprender este tipo de operadores? De hecho, hay - estos tipos de algoritmos son el enfoque principal de este libro: Convolutional Neural Networks (CNNs). Al aplicar filtros de convoluciones, funciones de activación no lineales, agrupación y propagación hacia atrás, las CNN pueden aprender a filtrar y detectar bordes y estructuras en forma de burbujas en capas de la red de niveles inferiores, y luego usar los bordes y las estructuras como "bloques de construcción". , eventualmente detectando objetos de alto nivel (por ejemplo, caras, gatos, perros, tazas, etc.) en las capas más profundas de la red. Este proceso de usar las capas de nivel inferior para aprender características de alto nivel es exactamente la composición de las CNN a las que nos referíamos anteriormente. ¿Pero exactamente cómo hacen esto las CNN? La respuesta es apilar un conjunto específico de capas de una manera determinada. En la siguiente sección, analizaremos estos tipos de capas, y luego examinaremos los patrones comunes de apilamiento de capas que se utilizan ampliamente entre muchas tareas de clasificación de imágenes.
Bloques de construcción de la CNN (CNN Building Blocks)
Como aprendimos en el Capítulo 10, las redes neuronales aceptan un vector de imagen/entidad de entrada (un nodo de entrada para cada entrada) y lo transforman a través de una serie de capas ocultas, comúnmente utilizando funciones de activación no lineales. Cada capa oculta también está formada por un conjunto de neuronas, donde cada neurona está completamente conectada a todas las neuronas de la capa anterior. La última capa de una red neuronal (es decir, la "capa de salida") también está completamente conectada y representa las clasificaciones finales de salida de la red.
Sin embargo, como demuestran los resultados de la Sección 10.1.4, las redes neuronales que operan directamente en intensidades de píxeles sin procesar:
1. No escalar bien a medida que aumenta el tamaño de la imagen.
2. Deja que se desee mucha precisión (es decir, una red de inscripciones anticipada estándar en CIFAR-10 obtuvo solo el 15% de precisión).
Para demostrar cómo las redes neuronales estándar no se escalan bien a medida que aumenta el tamaño de la imagen, consideremos nuevamente el conjunto de datos CIFAR-10. Cada imagen en CIFAR-10 es 32 × 32 con un canal Rojo, Verde y Azul, lo que da un total de 32 × 32 × 3 = 3,072 entradas totales a nuestra red.
Un total de 3,072 entradas no parece ser mucho, pero considere que si estuviéramos usando imágenes de 250 × 250 píxeles, el número total de entradas y pesos saltaría a 250 × 250 × 3 = 187,500, y este número es solo para el capa de entrada solo! Seguramente, nos gustaría agregar varias capas ocultas con un número variable de nodos por posición: estos parámetros pueden sumarse rápidamente y, dado el bajo rendimiento de las redes neuronales estándar en intensidades de píxeles sin procesar, esta acumulación no vale la pena.
En su lugar, podemos usar redes neuronales convolucionales (CNN) que aprovechan la estructura de la imagen de entrada y definen una arquitectura de red de una manera más sensible. A diferencia de una red neuronal estándar, las capas de una CNN se organizan en un volumen 3D en tres dimensiones: ancho, alto y profundidad (donde la profundidad se refiere a la tercera dimensión del volumen, como el número de canales en una imagen o el número de fi ltros en una capa).
Para hacer este ejemplo más concreto, considere nuevamente el conjunto de datos CIFAR-10: el volumen de entrada tendrá dimensiones 32 × 32 × 3 (ancho, altura y profundidad, respectivamente). Las neuronas en capas subsiguientes estarán conectadas a una pequeña región de la capa anterior (en lugar de la estructura tan conectada de una red neuronal estándar): llamamos a esta conectividad local que nos permite guardar una gran cantidad de parámetros en nuestra red. Finalmente, la capa de salida será un volumen de 1 × 1 × N que representa la imagen destilada en un único vector de puntuaciones de clase. En el caso de CIFAR-10, dadas diez clases, N = 10, produciendo un volumen de 1 × 1 × 10.
Tipos de capas
Existen muchos tipos de capas utilizadas para construir redes neuronales convolucionales, pero las que es más probable que encuentre incluyen:
- Convolucional (CONV)
- Activación (ACT o RELU, donde usamos lo mismo de la función de activación real)
- Agrupación (POOL)
- Totalmente conectado (FC)
- Normalización de lotes (BN)
- Deserción (DO)
Al apilar una serie de estas capas de una manera específica se obtiene una CNN. A menudo usamos diagramas de texto simples para describir una CNN: ENTRADA => CONV => RELU => FC => SOFTMAX Aquí definimos una CNN simple que acepta una entrada, aplica una capa de convolución, luego una capa de activación, luego una capa completamente conectada, y, finalmente, un clasificador softmax para obtener las probabilidades de clasificación de salida.
La capa de activación SOFTMAX es a menudo activada desde el diagrama de red, ya que se supone que sigue directamente al FC final.
De estos tipos de capas, CONV y FC, (y en menor medida, BN) son las únicas capas que contienen parámetros que se aprenden durante el proceso de entrenamiento. Las capas de activación y desactivación no se consideran verdaderas "capas" en sí mismas, pero a menudo se incluyen en los diagramas de red para aclarar explícitamente la arquitectura. Las capas de agrupación (POOL), de igual importancia que CONV y FC, también se incluyen en los diagramas de red tal como están un impacto sustancial en las dimensiones espaciales de una imagen a medida que se mueve a través de una CNN.
CONV, POOL, RELU y FC son los más importantes al definir su arquitectura de red real. Eso no quiere decir que las otras capas no sean críticas, sino que ocupen un segundo plano en este conjunto crítico de cuatro, ya que definen la arquitectura real en sí.
Las funciones de activación en sí mismas prácticamente se asumen como parte de la arquitectura. Al definir arquitecturas CNN, a menudo omitimos las capas de activación de una tabla / diagrama para ahorrar espacio; sin embargo, se asume implícitamente que las capas de activación forman parte de la arquitectura.
En el resto de esta sección, revisaremos cada uno de estos tipos de capas en detalle y discutiremos los parámetros asociados con cada capa (y cómo establecerlos). Más adelante en este capítulo analizaré con más detalle cómo apilar estas capas correctamente para construir sus propias arquitecturas de CNN.
Comentarios
Publicar un comentario