#!/usr/bin/env python
# coding: utf-8
# # Redes Neuronales Convolucionadas (RNC)
# # Autor
#
# 1. Alvaro Mauricio Montenegro Díaz, ammontenegrod@unal.edu.co
# 2. Daniel Mauricio Montenegro Reyes, dextronomo@gmail.com
# In[ ]:
# # References
#
# 1. Ian Goodfellow, Yosua Bengio and Aaron Courville, *Deep Learning*, MIT press, 2016.
# 2. Vincent Doumolin and Francesco Visin, *A guide to convolution arithmetic for deep learning*, ArXiv:1603.07285v2, 2018
# 3. https://towardsdatascience.com/applied-deep-learning-part-4-convolutional-neural-networks-584bc134c1e2
#
#
#
# # Introducción
#
#
#
# Las redes RNC son un tipo especializado de red neuronal para procesar datos que tiene una topología conocida similar a una cuadrícula. Los ejemplos incluyen datos de series temporales, que pueden puede considerarse como una cuadrícula 1D que toma muestras a intervalos de tiempo regulares y datos de imagen, que puede considerarse como una cuadrícula de píxeles en 2D.
#
#
# El nombre "red neuronal convolucional" indica que la red emplea una operación matemática llamada convolución. La convolución es un tipo especializado de operación lineal. Las redes convolucionales son simplemente redes neuronales que utilizan convolución en lugar de una matriz general en al menos una de sus capas.
#
# # La operación de convolución
#
# En su forma más general, la convolución es una operación en dos funciones de un valor real argumento.
#
#
# Para motivar la definición de convolución, comenzamos con ejemplos de dos funciones que podríamos usar.
#
#
# Supongamos que estamos rastreando la ubicación de una nave espacial con un sensor láser. Nuestro
# sensor láser proporciona una salida única $ x (t) $, la posición de la nave espacial en el momento
# $ t $. Tanto $ x $ como $ t $ tienen un valor real, es decir, podemos obtener una lectura diferente del láser
# sensor en cualquier instante en el tiempo.
#
#
# Ahora suponga que nuestro sensor láser es algo ruidoso. Para obtener una estimación menos ruidosa de la posición de la nave espacial, una buena idea es promediar varias mediciones.
#
# Por supuesto, las mediciones más recientes son más relevantes, por lo que lo haremos un promedio ponderado que otorgue más peso a las mediciones recientes.
#
# Podemos hacer esto con una función de ponderación $ w (a) $, donde $ a $ es la edad de una medición.
#
# Si aplicamos una operación promedio ponderada en cada momento, obtenemos una nueva
# función que proporciona una estimación suavizada de la posición $s$ de la nave espacial:
#
# $$
# s(t) = \int x(a) w(t-a)da
# $$
#
# Observe que si $a_1.\ldots, a_n$ es una muestra de la distibución cuya función de densidad es $w$, entonces se tiene que
#
# $$
# s(t)\approx \tfrac{1}{n}\sum_{i=1}^n x(a_i) w(t-a_i)
# $$
#
# Esta operación se llama **convolución**. La operación de convolución es típicamente denotado con un asterisco:
#
# $$
# s(t) = (x ∗ w)(t)
# $$
#
# En el ejemplo, $ w $ debe ser una función de densidad de probabilidad válida, o el
# el resultado no es un promedio ponderado.
#
#
#
# Además, $ w $ debe ser 0 para todos los argumentos negativos, o mirar hacia el futuro, lo que presumiblemente está más allá de nuestras capacidades. Sin embargo, estas limitaciones son particulares de nuestro ejemplo. En general, la convolución se define para cualquier función para la cual se define la integral anterior, y puede modificarse para otras multas además de tomar promedios ponderados.
#
# $\leadsto$ **Terminología**
# 1. $x$ es la entrada **input**.
# 2. $w$ es el **kernel** o filtro
# 3. La salida es el **feature map**.
#
# **Discretización**
#
# En el ejemplo, la idea de un sensor láser que pueda proporcionar mediciones en cada instante en el tiempo no es realista.
#
# Por lo general, cuando trabajamos con **datos** en una computadora, el tiempo será discretizado y nuestro sensor proporcionará datos a intervalos regulares. En el ejemplo, podría ser más realista suponer que nuestro láser proporciona una medición una vez por segundo. El índice de tiempo $ t $ solo puede tomar valores enteros Si ahora suponemos que $x$ y $w $ se definen solo en el entero $t$, puede definir la convolución discreta:
#
# $$
# s(t) = (x ∗ w)(t) = \sum_{a=-\infty}^{\infty} x(a)w(t-a)
# $$
# # Cuestiones prácticas
#
# $ \leadsto $ **Sumas finitas**
#
# En las aplicaciones de aprendizaje automático, la entrada suele ser un tensor) de datos y el núcleo suele ser una matriz multidimensional de parámetros que son aprendidos por el algoritmo de aprendizaje.
#
#
# Porque cada elemento de la entrada y el núcleo deben almacenarse explícitamente
# por separado, generalmente asumimos que estas funciones son cero en todas partes excepto
# conjunto finito de puntos para los que almacenamos los valores. Esto significa que en la práctica se
# puede implementar la suma infinita como una suma sobre un número finito de
# elementos de la matriz.
#
# A menudo usamos convoluciones en más de un eje a la vez. Por
# ejemplo, si usamos una imagen bidimensional $ I $ como entrada, probablemente también queremos para usar un kernel bidimensional $ K $:
#
# $$
# S (i, j) = (I ∗ K) (i, j) = \sum_ {m} \sum_ {n} I (m, n) K (i-m, j-n).
# $$
#
# $ \leadsto $ **Conmutativo**
#
# La convolución es conmutativa. Podemos escribir
#
# $$
# S (i, j) = (K ∗ I) (i, j) = \sum_ {m} \sum_ {n} I (i-m, j-n) K (m, n).
# $$
#
# Esta propiedad es conveniente para el estudio matemático de convoluciones.
#
#
# $ \leadsto $ **Correlación cruzada**
#
# Por otro lado, muchas bibliotecas de redes neuronales implementan un
# función relacionada llamada correlación cruzada, que es lo mismo que convolución
# pero sin voltear el kernel:
#
# $$
# S (i, j) = (I ∗ K) (i, j) = \sum_m \sum_n I (i + m, j + n) K (m, n).
# $$
#
# Muchas bibliotecas de aprendizaje automático implementan correlación cruzada pero la llaman convolución. Haremos lo mismo.
#
# #
# # Estructuras intrínsecas de datos donde la convolución es útil
#
# Las imágenes, los clips de sonido y muchos otros tipos de datos similares tienen estructura característica común.
#
# Más formalmente, comparten estas propiedades importantes:
#
# 1. Se almacenan como matrices multidimensionales (tensores).
# 2. Cuentan con uno o más ejes para los que importa el orden (por ejemplo, ejes de ancho y alto para una imagen, eje de tiempo para un clip de sonido).
# 3. Un eje, llamado eje del canal (channel), se usa para acceder a diferentes vistas de los datos (por ejemplo, los canales rojo, verde y azul de una imagen en color, o los canales izquierdo y derecho de una pista de audio estéreo).
# # Convoluciones discretas
#
# Supongamos que tenemos un kernel como el mostrado en la imagen. El kernel es mostrado como una distribución no normalizada. Los cálculos son como se muestran en la imagen.
#
#
#
#
#
#
Cálculo de una convolución
#
#
# La siguiente figura proporciona un ejemplo de una convolución discreta. El azul claro
# La cuadrícula se denomina mapa de entidades de entrada. Para mantener el dibujo simple, una sola entrada
# el mapa de características está representado, pero no es raro tener múltiples características
# mapas apilados uno sobre otro, como en caso de la imágenes de color.
#
#
#
#
#
#
#
Cálculo completo de una convolución
#
#
#
# En cada ubicación, se calcula el producto entre cada elemento del núcleo y el elemento de entrada que se superpone y los resultados se resumen para obtener la salida en la ubicación actual.
#
# El procedimiento puede repetirse usando diferentes núcleos para formar tantas características de salida
# mapas según lo deseado. Los resultados finales de este procedimiento se denominan mapas de características de salida.
#
# Si hay múltiples mapas de de entrada (digamos tres por cada imagen), el núcleo puede que ser tridimensional, o, de manera equivalente, cada uno de los mapas s estará filtrado con un núcleo distinto, y los mapas resultantes serán resumido por elementos para producir el mapa de características de salida.
# ## Relleno (padding)
#
# ¿Qué sucede cuando aplica tres filtros de 5 x 5 x 3 a un volumen de entrada de 32 x 32 x 3? El volumen de salida sería 28 x 28 x 3. Observe que las dimensiones espaciales disminuyen. A medida que seguimos aplicando capas *conv*, el tamaño del volumen disminuirá más rápido de lo que quisiéramos.
#
# En las primeras capas de nuestra red, queremos preservar la mayor cantidad de información sobre el volumen de entrada original para poder extraer esas características de bajo nivel. Supongamos que queremos aplicar la misma capa *conv* pero queremos que el volumen de salida permanezca 32 x 32 x 3. Para hacer esto, podemos aplicar un relleno cero de tamaño 2 a esa capa.
#
# El relleno cero rellena el volumen de entrada con ceros alrededor del borde. Si pensamos en un relleno cero de dos, esto daría como resultado un volumen de entrada de 36 x 36 x 3.
#
#
#
#
#
#
#
Ilustración de relleno (padding)
#
#
#
# ## Saltos (stripes)
#
# En este caso, deslizamos nuestra ventana por 1 píxel a la vez. En algunos casos, las personas deslizan las ventanas más de 1 píxel. Este número se llama zancada (stripe).
#
#
# ## Agregación (pooling)
#
#
# La capa de agrupación se usa principalmente inmediatamente después de la capa convolucional para reducir el tamaño espacial (solo ancho y alto, no profundidad). Esto reduce el número de parámetros, por lo tanto, se reduce el cálculo. Además, un número menor de parámetros evita el sobreajuste. La forma más común de agrupación es la agrupación máxima, donde tomamos un filtro de tamaño F * F y aplicamos la operación máxima sobre la parte de tamaño de F * F de la imagen.
#
#
#
#
#
#
#
#
Cálculo del pooling
#
#
#
# # Arquitecture de redes RNC
#
#
# Todos los modelos RCN siguen una arquitectura similar, como se muestra en la figura a continuación.
#
# Hay una imagen de entrada con la que estamos trabajando. Realizamos una serie de operaciones de convolución + agrupación, seguidas de varias capas completamente conectadas. Si estamos realizando una clasificación multiclase, la salida es softmax. Ahora nos sumergiremos en cada componente.
#
#