# Retropropagación

En aprendizaje de máquina, la retropropagación o propagación hacia atrás de errores (del inglés backpropagation) es un algoritmo de aprendizaje supervisado utilizado para entrenar redes neuronales prealimentadas. Dado que es un método de cálculo del gradiente el algoritmo generalmente se puede usar en otros tipos de redes neuronales artificiales y en general para funciones.
El método emplea un ciclo de propagación–adaptación de dos fases, en resumen permite que la información del costo fluya hacia atrás a través de la red para calcular el gradiente. Una vez que se ha aplicado un patrón a la entrada de la red como estímulo, este se propaga desde la primera capa a través de las capas siguientes de la red, hasta generar una salida. La señal de salida se compara con la salida deseada y se calcula una señal de error para cada una de las salidas. Las salidas de error entonces se propagan hacia atrás, partiendo de la capa de salida, hacia todas las neuronas de la capa oculta que contribuyen directamente a la salida. Sin embargo las neuronas de la capa oculta solo reciben una fracción de la señal total del error, basándose aproximadamente en la contribución relativa que haya aportado cada neurona a la salida original. Este proceso se repite, capa por capa, hasta que todas las neuronas de la red hayan recibido una señal de error que describa su contribución relativa al error total.
La importancia de este proceso consiste en que, a medida que se entrena la red, las neuronas de las capas intermedias se organizan a sí mismas de tal modo que las distintas neuronas aprenden a reconocer distintas características del espacio total de entrada. Después del entrenamiento, cuando se les presente un patrón arbitrario de entrada que contenga ruido o que esté incompleto, las neuronas de la capa oculta de la red responderán con una salida activa si la nueva entrada contiene un patrón que se asemeje a aquella característica que las neuronas individuales hayan aprendido a reconocer durante su entrenamiento.

## Estructura del perceptrón

El perceptrón es un modelo matemático de la neurona, busca imitar el proceso de una neurona biológica.
Sean los $p_{i}$ las entradas (por las dendritas) a la neurona. Estas sufren un efecto multiplicador $w_{i}$ por la comunicación de las mismas al núcleo de la neurona, donde se sumaran mediante:
$n=\sum _{i=1}^{i=q}(w_{i}*p_{i})+b$
Y luego pasa por la función de activación:
$a=f(n)=f(\sum _{i=0}^{i=q}(p_{i}*w_{i})+b)$

## Perceptrón Multicapa

Un Perceptrón multicapa es una red neuronal artificial con alimentación (propagación) hacia delante, compuesta de varias capas de neuronas entre la entrada y la salida de la misma. Esta red permite establecer regiones de decisión mucho más complejas que las de dos semiplanos, como lo hace el Perceptrón de un solo nivel. Las capacidades del Perceptrón multicapa con dos y tres capas y con una única neurona en la capa de salida se muestran en la siguiente figura:
Perceptrón simple, activándose su salida para los patrones de un lado del hiperplano, si el valor de los pesos de las conexiones entre las neuronas de la segunda capa y una neurona del nivel de salida son todos igual a 1, y la función de salida es de tipo hardlim, la salida de la red se activará sólo si las salidas de todos los nodos de la segunda capa están activos, esto equivale a ejecutar la función lógica AND en el nodo de salida, resultando una región de decisión intersección de todos los semiplanos formados en el nivel anterior. La región de decisión resultante de la intersección será una región convexa con un número de lados a lo sumo igual al número de neuronas de la segunda capa. A partir de este análisis surge el interrogante respecto a los criterios de selección para las neuronas de las capas ocultas de una red multicapa, este número en general debe ser lo suficientemente grande como para que se forme una región compleja que pueda resolver el problema, sin embargo no debe ser muy grande pues la estimación de los pesos puede ser no confiable para el conjunto de los patrones de entrada disponibles. Hasta el momento no hay un criterio establecido para determinar la configuración de la red y esto depende más bien de la experiencia del diseñador.

## Estructura de la Red

Puede notarse que esta red de tres capas equivale a tener tres redes tipo Perceptrón en cascada; la salida de la primera red, es la entrada a la segunda y la salida de la segunda red es la entrada a la tercera. Cada capa puede tener diferente número de neuronas, e incluso distinta función de transferencia.

## Regla de aprendizaje

La red retropropagada trabaja bajo aprendizaje supervisado y por tanto necesita un conjunto de entrenamiento que le describa cada salida y su valor de salida esperado de la siguiente forma:
${(p_{1},t_{1})},{(p_{2},t_{2})},...,{(p_{q},t_{q})}(1)$
Donde $p_{q}$ es una entrada a la red y $t_{q}$ es la correspondiente salida deseada para el patrón q-ésimo. El algoritmo debe ajustar los parámetros de la red para minimizar el error cuadrático medio. Es importante recalcar que no existe una técnica para determinar el número de capas ocultas, ni el número de neuronas que debe contener cada una de ellas para un problema específico, esta elección es determinada por la experiencia del diseñador, el cual debe cumplir con las limitaciones de tipo computacional. Cada patrón de entrenamiento se propaga a través de la red y sus parámetros para producir una respuesta en la capa de salida, la cual se compara con los patrones objetivo o salidas deseadas para calcular el error en el aprendizaje, este error marca el camino más adecuado para la actualización de los pesos y ganancias que al final del entrenamiento producirán una respuesta satisfactoria a todos los patrones de entrenamiento, esto se logra minimizando el error cuadrático medio en cada iteración del proceso de aprendizaje.
Para iniciar el entrenamiento se le presenta a la red un patrón de entrenamiento, el cual tiene q componentes como se describe en la ecuación (2):
$p={\begin{bmatrix}p_{1}\\p_{2}\\.\\.\\p_{i}\\.\\.\\p_{q}\end{bmatrix}}(2)$
Cuando se le presenta a la red un patrón de entrenamiento, este se propaga a través de las conexiones existentes produciendo una entrada neta n en cada una las neuronas de la siguiente capa, la entrada neta a la neurona j de la siguiente capa debido a la presencia de un patrón de entrenamiento en la entrada está dada por la ecuación (3), nótese que la entrada neta es el valor justo antes de pasar por la función de transferencia:
$n_{j}^{0}=\sum _{i=1}^{q}(w_{ji}^{0}*p_{i})+b_{j}^{0}(3)$
Donde el 0 representa la capa oculta a la que pertenece cada parámetro. Cada una de las neuronas de la capa oculta tiene como salida $a_{j}^{0}$, dada por:
$a_{j}^{0}=f^{0}(\sum _{i=1}^{q}(w_{ji}^{0}*p_{i})+b_{j}^{0})(4)$
$f^{0}$: Función de transferencia de las neuronas de la capa oculta. Las salidas $a_{j}^{0}$ de las neuronas de la capa oculta (de m componentes) son las entradas a los pesos de conexión de la capa de salida, este comportamiento está descrito por: $$ $n_{k}^{s}=\sum _{j=1}^{m}(w_{kj}^{s}*a_{j}^{0})+b_{k}^{s}(5)$
La red produce una salida final: $a_{k}^{s}=f^{s}(n_{k}^{s})(6)$
$f^{s}$: Función de transferencia de las neuronas de la capa de salida.
La salida de la red de cada neurona $a_{k}^{s}$ se compara con la salida deseada $t_{k}$ para calcular el error en cada unidad: $\delta _{k}=(t_{k}-a_{k}^{s})$
El error debido a cada patrón p propagado está dado por:
$ep^{2}=1/2\sum _{k=1}^{l}(\delta _{k}^{2})$
$ep^{2}$: Error cuadrático medio para cada patrón de entrada p.
$\delta _{k}$: Error en la neurona k de la capa de salida con l neuronas.
Este proceso se repite para el número total de patrones de entrenamiento (r), para un proceso de aprendizaje exitoso el objetivo del algoritmo es actualizar todos los pesos y ganancias de la red minimizando el error cuadrático medio total descrito en:
$e^{2}=\sum _{p=1}^{r}(ep^{2})$
$e^{2}$: Error total en el proceso de aprendizaje en una iteración después de haber presentado a la red los r patrones de entrenamiento. El error que genera una red neuronal en función de sus pesos, genera un espacio de n dimensiones, donde n es el número de pesos de conexión de la red, al evaluar el gradiente del error en un punto de esta superficie se obtendrá la dirección en la cual la función del error tendrá un mayor crecimiento, como el objetivo del proceso de aprendizaje es minimizar el error debe tomarse la dirección negativa del gradiente para obtener el mayor decremento del error y de esta forma su minimización, condición requerida para realizar la actualización de la matriz de pesos en el algoritmo Backpropagation:

## Minimización del error

Los algoritmos en Aprendizaje Automático pueden ser clasificados en dos categorías: supervisados y no supervisados. Los algoritmos en aprendizaje supervisado son usados para construir "modelos" que generalmente predicen ciertos valores deseados. Para ello, los algoritmos supervisados requieren que se especifiquen los valores de salida (output) u objetivo (target) que se asocian a ciertos valores de entrada (input). Ejemplos de objetivos pueden ser valores que indican éxito/fallo, venta/no-venta, pérdida/ganancia, o bien ciertos atributos multi-clase como cierta gama de colores o las letras del alfabeto. El conocer los valores de salida deseados permite determinar la calidad de la aproximación del modelo obtenido por el algoritmo.
La especificación de los valores entrada/salida se realiza con un conjunto consistente en pares de vectores con entradas reales de la forma $({\boldsymbol {x}},{\boldsymbol {t}})$, conocido como conjunto de entrenamiento o conjunto de ejemplos, donde $({\boldsymbol {x}})$ serán nuestros parámetros de entrada y $({\boldsymbol {t}})$ los de salida de la red. Los algoritmos de aprendizaje generalmente calculan los parámetros ${\boldsymbol {W}}$ de una función $N({\boldsymbol {x}};{\boldsymbol {W}})$ que permiten aproximar los valores de salida en el conjunto de entrenamiento.
Si $({\boldsymbol {x}}^{(q)},{\boldsymbol {t}}^{(q)})$, $q=1,\ldots ,p$, son los elementos del conjunto de entrenamiento, la calidad de la aproximación en el ejemplo $q$ se puede medir a través del error cuadrático:
$E({\boldsymbol {x}}^{(q)};{\boldsymbol {W}})=\|N({\boldsymbol {x}}^{(q)};{\boldsymbol {W}})-{\boldsymbol {t}}^{(q)}\|^{2}$,
donde $\|\cdot \|$ es la norma euclidiana.
El error total es la suma de los errores de los ejemplos:
$E({\boldsymbol {W}})=\sum _{q=1}^{p}E({\boldsymbol {x}}^{(q)};{\boldsymbol {W}})$.
Un método general para minimizar el error es el actualizar los parámetros de manera iterativa. El valor nuevo de los parámetros se calcula al sumar un incremento $\Delta {\boldsymbol {W}}$ al valor actual:
${\boldsymbol {W}}:={\boldsymbol {W}}+\Delta {\boldsymbol {W}}$
El algoritmo se detiene cuando ${\boldsymbol {W}}$ converge o bien cuando el error alcanza un mínimo valor deseado.
Si la función $N({\boldsymbol {x}};{\boldsymbol {W}})$ usada para aproximar los valores de salida es diferenciable respecto a los parámetros ${\boldsymbol {W}}$, podemos usar como algoritmo de aprendizaje el método de gradiente descendiente. En este caso, el incremento de los parámetros se expresa como
$\Delta {\boldsymbol {W}}=-\gamma {\frac {\partial E({\boldsymbol {W}})}{\partial {\boldsymbol {W}}}},$
donde $0<\gamma <1$ es un parámetro conocido como factor de aprendizaje.
Antes de continuar introduciremos un poco de notación. Definimos ${\bar {\boldsymbol {v}}}=(v_{1},\ldots ,v_{n},1)^{T}$ como el vector extendido del vector ${\boldsymbol {v}}=(v_{1},\ldots ,v_{n})^{T}$. El par $({\boldsymbol {x}},{\boldsymbol {t}})$ representará a un elemento del conjunto de entrenamiento y una relación de entrada-salida, a menos que se indique otra cosa.

## Red neuronal con una capa oculta

La función la usaremos para aproximar los valores de salida de una red neuronal artificial con una capa oculta. La red está constituida por una capa de entrada (input layer), una capa oculta (hidden layer) y una capa de salida (output layer), tal como se ilustra con la siguiente figura:
Los elementos que constituyen la red neuronal son los siguientes:
* $s$ es una función de valores reales, conocida como la función de transferencia.
* ${\bar {\boldsymbol {o}}}^{(0)}$ es la capa de entrada, considerado como el vector extendido del ejemplo ${\boldsymbol {o}}^{(0)}={\boldsymbol {x}}=(x_{1},\ldots ,x_{n})^{T}$.
* ${\bar {\boldsymbol {o}}}^{(1)}$ es la capa oculta, el vector extendido de ${\boldsymbol {o}}^{(1)}=(o_{1}^{(1)},\ldots ,o_{k}^{(1)})^{T}$.
* ${\boldsymbol {o}}^{(2)}=(o_{1},\ldots ,o_{m})^{T}$ es la capa de salida, considerado como el vector que aproxima al valor deseado ${\boldsymbol {t}}=(t_{1},\ldots ,t_{m})^{T}$.
* ${\boldsymbol {W}}^{(1)}$ es una matriz de tamaño $(n+1)\times k$ cuyos valores $W_{ij}^{(1)}$ son los pesos de la conexión entre las unidades ${\bar {o}}_{i}^{(0)}$ y $o_{j}^{(1)}$.
* ${\boldsymbol {W}}^{(2)}$ es una matriz de tamaño $(k+1)\times m$ cuyos valores $W_{ij}^{(2)}$ son los pesos de la conexión entre las unidades ${\bar {o}}_{i}^{(1)}$ y $o_{j}^{(2)}$.
De estos elementos, únicamente las matrices ${\boldsymbol {W}}^{(l)}$ son consideradas como los parámetros de la red, ya que los valores ${\bar {\boldsymbol {o}}}^{(l)}$ son el resultado de cálculos que dependen de las matrices de pesos, del valor de entrada ${\bar {\boldsymbol {x}}}$ y de la función de transferencia $s$.
La función de transferencia $s$ que consideraremos en nuestro algoritmo es conocida como función sigmoidal, y está definida como
$s(u)={\frac {1}{1+\exp(-u)}}$
esta función además de ser diferenciable, tiene la particularidad de que su derivada se puede expresar en términos de sí misma:
${\frac {ds(u)}{du}}=s(u)(1-s(u)).$
esto nos servirá para simplificar los cálculos en el algoritmo de aprendizaje aquí descrito.

## Descripción del algoritmo

A grandes rasgos:
* Calcular la salida de la red ${\boldsymbol {o}}^{(2)}$ a partir de uno de los conjuntos de valores de prueba $x$.
* Comparar con la salida correcta $t$ y calcular el error según la fórmula:
    $E({\boldsymbol {x}};{\boldsymbol {W}}^{(1)},{\boldsymbol {W}}^{(2)})={\frac {1}{2}}\sum _{i=1}^{m}(t_{i}-o_{i}^{(2)})^{2}.$
* Calcular las derivadas parciales del error con respecto a los pesos ${\boldsymbol {W}}^{(2)}$ que unen a la última capa oculta con la de salida.
* Calcular las derivadas parciales del error con respecto a los pesos ${\boldsymbol {W}}^{(1)}$ que unen la capa de entrada con la oculta.
* Ajustar los pesos de cada neurona para reducir el error.
* Repetir el proceso varias veces por cada par de entradas-salidas de prueba.
O = Xj*F(netj)