hllinas2023

1 Paquetes utilizados

2 Introducción

eXclusive OR (XOR) es una operación lógica booleana muy utilizada en criptografía y en la generación de bits de paridad para la comprobación de errores y la tolerancia a fallos. XOR compara dos bits de entrada y genera un bit de salida. La lógica es sencilla. Si los bits son iguales, el resultado es 0. Si los bits son diferentes, el resultado es 1. Los resultados de esta operación pueden resumirse en la tabla de abajo:

##   x1 x2 y
## 1  0  0 0
## 2  0  1 1
## 3  1  1 0
## 4  1  0 1

3 Ejemplo 1

3.0.1 El modelo

Para este ejemplo, vamos a utilizar una red neuronal con dos inputs (basados en la tabla anterior), dos neuronas ocultas y una neurona de salida. Además, tendremos en cuenta la función logística como función de activación. En este sentido, la estructura básica será:

Aplicaremos el método de retropropagación, cuyo objetivo es optimizar los pesos para que la red neuronal pueda aprender a asignar correctamente entradas arbitrarias a salidas. Para empezar, debemos ver qué predice actualmente la red neuronal dados unos pesos, unos sesgos y algunos valores de las variables como entradas iniciales. Con estos valores, alimentaremos esas entradas a través de la red. En este sentido, calculamos la entrada neta total a cada neurona de la capa oculta, obtenemos la salida correspondiente de cada neurona transformando la entrada neta total con ayuda de una función de activación (aquí utilizamos la función logística) y, a continuación, repetimos el proceso con las neuronas de la capa de salida.

3.0.2 Valores iniciales

En la gráfica de abajo se presentan los pesos iniciales (\(W_i\)), los sesgos (\(b_i\)) y las entradas/salidas de entrenamiento (\(X_i\)/\(O_1\)), que utilizaremos en este ejemplo:

Como se puede ver, en este ejemplo vamos a trabajar con un único conjunto de entrenamiento: dadas las entradas 0 y 1, queremos que la red neuronal produzca la salida 1.

3.0.3 Primera época

Neurona \(h_1\):

Entrada: \[z_1 \;=\; w_1 X_1 + w_3 X_2 + b_1 \;=\; (0.1)(0) +(-0.7)(1) + 0 \;=\; -0.7\]

Salida: \[f_1(z_1) \;=\; \frac{1}{1+ e^{-z_1}} \;=\; \frac{1}{1+ e^{0.7}} \;=\; 0.3318\]

Neurona \(h_2\):

Entrada: \[z_2 \;=\; w_2 X_1 + w_4 X_2 + b_2 \;=\; (0.5)(0) +(0.3)(1) + 0 \;=\; 0.3\]

Salida: \[f_2(z_2) \;=\; \frac{1}{1+ e^{-z_2}} \;=\; \frac{1}{1+ e^{-0.3}} \;=\; 0.5744\]

Neurona \(O_1\):

Entrada: \[z_3 \;=\; w_5 f_1(z_1) + w_6 f_2(z_2) + b_3 \;=\; (0.2)(0.332) +(0.4)(0.574) + 0 \;=\; 0.2996\]

Salida: \[f_3(z_3) \;=\; \frac{1}{1+ e^{-z_3}} \;=\; \frac{1}{1+ e^{-0.296}} \;=\; 0.5735\]

3.0.4 Error total

Ahora podemos calcular el error de cada neurona de salida utilizando la función de error al cuadrado y sumarlos para obtener el error total para la red neuronal: \[E_{total} \;=\; \sum\limits_{i=1}^n \frac{1}{2} (O_i-\hat{O}_i)^2 \;=\; \frac{1}{2} [O_1-f_3(z_3)]^2 \;=\; \frac{1}{2} (1-0.5735)^2 \;=\; 0.090952\]

3.0.5 Backpropagation

Nuestro objetivo con la retropropagación es actualizar cada uno de los pesos de la red de forma que hagan que la salida real se acerque más a la salida objetivo, minimizando así el error de cada neurona de salida y de la red en su conjunto.

3.0.5.1 Output layer

Por ejemplo, considere \(w_5\). Queremos saber cuánto un cambio en \(w_5\) afecta el error total. Es decir, estamos interesado en \(\frac{\partial E_{total}}{\partial w_5}\). Por la regla de la cadena, téngase en cuenta que:

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_3} &=& \frac{\partial E_{total}}{\partial f_3}\cdot \frac{\partial f_3}{\partial z_3}\\ &=& (O_1-\hat{O}_1)(1-f_3)f_3 \\ &=& (1-0.5735) (1-0.5735)(0.5735)\\ &=& 0.10432 \end{eqnarray*}\]

Por lo tanto,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_5} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial w_5}\;=\; (0.10432) f_1 \;=\; (0.10432)(0.3318) \;=\; 0.034615 \end{eqnarray*}\]

Al considerar \(w_6\):

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_6} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial w_6}\;=\; (0.10432) f_2 \;=\; (0.10432)(0.5744) \;=\; 0.059927 \end{eqnarray*}\]

Para reducir el error, restamos estos valores del peso actual (opcionalmente multiplicado por una tasa de aprendizaje, \(\alpha\), que fijaremos en 0.25) y, así obtendremos nuevos pesos para la neurona \(O_1\) (solo hay una). Es decir, aplicaremos la fórmula:

\[w_i^* \;=\; w_i \;-\; \alpha \frac{\partial E_{total}}{\partial w_i}\] Con base en lo anterior,

\[\begin{eqnarray*} w_5^* &=& w_5 - 0.25 \frac{\partial E_{total}}{\partial w_5} \;=\; 0.2 - (0.25)(0.034615) \;=\; 0.191346\\ && \\ w_6^* &=& w_6 - 0.25 \frac{\partial E_{total}}{\partial w_6} \;=\; 0.4 - (0.25)(0.059927) \;=\; 0.385018 \end{eqnarray*}\]

Realizamos las actualizaciones reales en la red neuronal después de tener los nuevos pesos que conducen a las neuronas de la capa oculta (es decir, utilizamos los pesos originales, no los actualizados, cuando continuamos con el algoritmo de retropropagación a continuación).

3.0.5.2 Hidden layer

Ahora, continuamos el proceso calculando nuevos valores para \(w_1\), \(w_2\), \(w_3\) y \(w_4\).

Neurona \(h_1\):

Téngase en cuenta que: \[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_1} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial f_1} \cdot \frac{\partial f_1}{\partial z_1} \\ &=& (0.10432)\cdot w_5\cdot (1-f_1)f_1\\ &=& (0.10432) (0.2)(1-0.3318)(0.3318)\\ &=& 0.004626 \end{eqnarray*}\]

Entonces,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_1} &=& \frac{\partial E_{total}}{\partial z_1} \cdot \frac{\partial z_1}{\partial w_1}\; = \; (0.004626) X_1\; = \; (0.004626) (0)\; = \; 0 && \\ &&\\ \frac{\partial E_{total}}{\partial w_3} &=& \frac{\partial E_{total}}{\partial z_1} \cdot \frac{\partial z_1}{\partial w_3}\; = \; (0.004626) X_2\; = \; (0.004626) (1)\; = \; 0.004626 \end{eqnarray*}\]

Con base en lo anterior, los nuevos pesos para \(w_1\) y \(w_3\) son:

\[\begin{eqnarray*} w_1^* &=& w_1 - 0.25 \frac{\partial E_{total}}{\partial w_1} \;=\; 0.1 - (0.25)(0) \;=\; 0.1\\ && \\ w_3^* &=& w_3 - 0.25 \frac{\partial E_{total}}{\partial w_3} \;=\; -0.7 - (0.25)(0.004626) \;=\; -0.70116 \end{eqnarray*}\]

Neurona \(h_2\):

Téngase en cuenta que: \[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_2} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial f_2} \cdot \frac{\partial f_2}{\partial z_2} \\ &=& (0.104321)\cdot w_6\cdot (1-f_2)f_2\\ &=& (0.104321) (0.4)(1-0.5744)(0.5744)\\ &=& 0.010201 \end{eqnarray*}\]

Por lo tanto,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_2} &=& \frac{\partial E_{total}}{\partial z_2} \cdot \frac{\partial z_2}{\partial w_2}\; = \; (0.010201) X_1\; = \; (0.010201) (0)\; = \; 0 && \\ &&\\ \frac{\partial E_{total}}{\partial w_4} &=& \frac{\partial E_{total}}{\partial z_2} \cdot \frac{\partial z_2}{\partial w_4}\; = \; (0.010201) X_2\; = \; (0.010201) (1)\; = \; 0.010201 \end{eqnarray*}\]

Con base en lo anterior, los nuevos pesos para \(w_2\) y \(w_4\) son:

\[\begin{eqnarray*} w_2^* &=& w_2 - 0.25 \frac{\partial E_{total}}{\partial w_2} \;=\; 0.5 - (0.25)(0) \;=\; 0.5\\ && \\ w_4^* &=& w_4 - 0.25 \frac{\partial E_{total}}{\partial w_4} \;=\; 0.3 - (0.25)(0.010211) \;=\; 0.29745 \end{eqnarray*}\]

3.0.6 Pesos actualizados

Finalmente, ¡hemos actualizado todos nuestros pesos! (véase la figura de abajo).

Pasamos a la segunda época.

3.0.7 Segunda época

Neurona \(h_1\):

Entrada: \[z_1 \;=\; w_1 X_1 + w_3 X_2 + b_1 \;=\; (0.1)(0) +(-0.70116)(1) + 0 \;=\; -0.70116\]

Salida: \[f_1(z_1) \;=\; \frac{1}{1+ e^{-z_1}} \;=\; \frac{1}{1+ e^{0.7116}} \;=\; 0.3316\]

Neurona \(h_2\):

Entrada: \[z_2 \;=\; w_2 X_1 + w_4 X_2 + b_2 \;=\; (0.5)(0) +(0.29745)(1) + 0 \;=\; 0.29745\]

Salida: \[f_2(z_2) \;=\; \frac{1}{1+ e^{-z_2}} \;=\; \frac{1}{1+ e^{-0.29745}} \;=\; 0.5738\]

Neurona \(O_1\):

Entrada: \[z_3 \;=\; w_5 f_1(z_1) + w_6 f_2(z_2) + b_3 \;=\; (0.191346)(0.3316) +(0.385018)(0.5738) + 0 \;=\; 0.28437\]

Salida: \[f_3(z_3) \;=\; \frac{1}{1+ e^{-z_3}} \;=\; \frac{1}{1+ e^{-0.28437}} \;=\; 0.5706\]

3.0.8 Error total

Ahora podemos calcular el error de cada neurona de salida utilizando la función de error al cuadrado y sumarlos para obtener el error total para la red neuronal: \[E_{total} \;=\; \sum\limits_{i=1}^n \frac{1}{2} (O_i-\hat{O}_i)^2 \;=\; \frac{1}{2} [O_1-f_3(z_3)]^2 \;=\; \frac{1}{2} (1-0.5706)^2 \;=\; 0.092184\]

3.0.9 Backpropagation

Nuestro objetivo con la retropropagación es actualizar cada uno de los pesos de la red de forma que hagan que la salida real se acerque más a la salida objetivo, minimizando así el error de cada neurona de salida y de la red en su conjunto.

3.0.9.1 Output layer

Por ejemplo, considere \(w_5\). Queremos saber cuánto un cambio en \(w_5\) afecta el error total. Es decir, estamos interesado en \(\frac{\partial E_{total}}{\partial w_5}\). Por la regla de la cadena, téngase en cuenta que:

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_3} &=& \frac{\partial E_{total}}{\partial f_3}\cdot \frac{\partial f_3}{\partial z_3}\\ &=& (O_1-\hat{O}_1)(1-f_3)f_3 \\ &=& (1-0.5706) (1-0.5706)(0.5706)\\ &=& 0.105204 \end{eqnarray*}\]

Por lo tanto,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_5} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial w_5}\;=\; (0.105204) f_1 \;=\; (0.105204)(0.3316) \;=\; 0.034881 \end{eqnarray*}\]

Al considerar \(w_6\):

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_6} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial w_6}\;=\; (0.105204) f_2 \;=\; (0.105204)(0.5738) \;=\; 0.060368 \end{eqnarray*}\]

Para reducir el error, restamos estos valores del peso actual (opcionalmente multiplicado por una tasa de aprendizaje, \(\alpha\), que fijaremos en 0.25) y, así obtendremos nuevos pesos para la neurona \(O_1\) (solo hay una). Es decir, aplicaremos la fórmula:

\[w_i^* \;=\; w_i \;-\; \alpha \frac{\partial E_{total}}{\partial w_i}\] Con base en lo anterior,

\[\begin{eqnarray*} w_5^* &=& w_5 - 0.25 \frac{\partial E_{total}}{\partial w_5} \;=\; 0.191346 - (0.25)(0.034881) \;=\; 0.182626\\ && \\ w_6^* &=& w_6 - 0.25 \frac{\partial E_{total}}{\partial w_6} \;=\; 0.385018 - (0.25)(0.060368) \;=\; 0.369926 \end{eqnarray*}\]

Realizamos las actualizaciones reales en la red neuronal después de tener los nuevos pesos que conducen a las neuronas de la capa oculta (es decir, utilizamos los pesos originales, no los actualizados, cuando continuamos con el algoritmo de retropropagación a continuación).

3.0.9.2 Hidden layer

Ahora, continuamos el proceso calculando nuevos valores para \(w_1\), \(w_2\), \(w_3\) y \(w_4\).

Neurona \(h_1\):

Téngase en cuenta que: \[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_1} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial f_1} \cdot \frac{\partial f_1}{\partial z_1} \\ &=& (0.105204)\cdot w_5\cdot (1-f_1)f_1\\ &=& (0.105204) (0.182626)(1-0.3316)(0.3316)\\ &=& 0.004461 \end{eqnarray*}\]

Entonces,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_1} &=& \frac{\partial E_{total}}{\partial z_1} \cdot \frac{\partial z_1}{\partial w_1}\; = \; (0.004461) X_1\; = \; (0.004461) (0)\; = \; 0 && \\ &&\\ \frac{\partial E_{total}}{\partial w_3} &=& \frac{\partial E_{total}}{\partial z_1} \cdot \frac{\partial z_1}{\partial w_3}\; = \; (0.004461) X_2\; = \; (0.004461) (1)\; = \; 0.00463 \end{eqnarray*}\]

Con base en lo anterior, los nuevos pesos para \(w_1\) y \(w_3\) son:

\[\begin{eqnarray*} w_1^* &=& w_1 - 0.25 \frac{\partial E_{total}}{\partial w_1} \;=\; 0.1 - (0.25)(0) \;=\; 0.1\\ && \\ w_3^* &=& w_3 - 0.25 \frac{\partial E_{total}}{\partial w_3} \;=\; -0.70116 - (0.25)(0.004461) \;=\; -0.7022718 \end{eqnarray*}\]

Neurona \(h_2\):

Téngase en cuenta que: \[\begin{eqnarray*} \frac{\partial E_{total}}{\partial z_2} &=& \frac{\partial E_{total}}{\partial z_3}\cdot \frac{\partial z_3}{\partial f_2} \cdot \frac{\partial f_2}{\partial z_2} \\ &=& (0.105204)\cdot w_6\cdot (1-f_2)f_2\\ &=& (0.105204) (0.369926)(1-0.5738)(0.5738)\\ &=& 0.009906 \end{eqnarray*}\]

Por lo tanto,

\[\begin{eqnarray*} \frac{\partial E_{total}}{\partial w_2} &=& \frac{\partial E_{total}}{\partial z_2} \cdot \frac{\partial z_2}{\partial w_2}\; = \; (0.009906) X_1\; = \; (0.010211) (0)\; = \; 0 && \\ &&\\ \frac{\partial E_{total}}{\partial w_4} &=& \frac{\partial E_{total}}{\partial z_2} \cdot \frac{\partial z_2}{\partial w_4}\; = \; (0.009906) X_2\; = \; (0.009906) (1)\; = \; 0.009906 \end{eqnarray*}\]

Con base en lo anterior, los nuevos pesos para \(w_2\) y \(w_4\) son:

\[\begin{eqnarray*} w_2^* &=& w_2 - 0.25 \frac{\partial E_{total}}{\partial w_2} \;=\; 0.5 - (0.25)(0) \;=\; 0.5\\ && \\ w_4^* &=& w_4 - 0.25 \frac{\partial E_{total}}{\partial w_4} \;=\; 0.29745 - (0.25)(0.009906) \;=\; 0.294973 \end{eqnarray*}\]

Cuando alimentamos las entradas de 0 y 1 originalmente, el error de la red fue de 0.090952. Después de esta primera ronda de retropropagación, el error total ahora es 0.092184.

4 REFERENCES