Para el cálculo y entrenamiento de redes neuronales se utiliza la operación XOR .Este una operación lógica booleana que recibe dos bits de entrada y emite un solo bit de salida. En estas operaciones cuando las entradas son iguales, la salida es 0 y cuando son diferentes, la salida es 1. Asi como en la siguiente tabla a continuacion:
## x1 x2 y
## 1 0 0 0
## 2 0 1 1
## 3 1 0 1
## 4 1 1 0
Para el modelo de red neuronal que entrenaremos a continuación, se utilizarán dos bits de entrada con valores 0 y 1, y se buscarán los valores óptimos de los pesos para que la salida Y sea 1. Es decir, los valores de la fila 2 en la tabla anterior.
El modelo de red neuronal que se va a entrenar es el siguiente:
## Warning: package 'DiagrammeR' was built under R version 4.4.3
Para el modelo a continuacion, la funcion de activacion a usar va a ser la funcion sigmoide.
\[ f(z) = \frac{1}{1 + e^{-z}} \]
library(knitr)
library(kableExtra)
sigmoid <- function(z) 1 / (1 + exp(-z))
x1 <- 0; x2 <- 1
y <- 1
w1 <- 0.1; w2 <- 0.5; w3 <- -0.7; w4 <- 0.3; w5 <- 0.2; w6 <- 0.4
b1 <- 0; b2 <- 0; b3 <- 0
alpha <- 0.25 # learning rate
tabla <- data.frame(
Epoca = integer(),
w1=numeric(), w2=numeric(), w3=numeric(), w4=numeric(),
w5=numeric(), w6=numeric(),
b1=numeric(), b2=numeric(), b3=numeric(),
O1=numeric(), E_total=numeric()
)
# Entrenamiento
for (epoch in 1:2) {
h1_in <- w1*x1 + w3*x2 + b1
h1_out <- sigmoid(h1_in)
h2_in <- w2*x1 + w4*x2 + b2
h2_out <- sigmoid(h2_in)
o_in <- w5*h1_out + w6*h2_out + b3
o_out <- sigmoid(o_in)
error <- 0.5*(y - o_out)^2
# Backpropagation
delta_o <- (o_out - y) * o_out * (1 - o_out)
delta_h1 <- (w5 * delta_o) * h1_out * (1 - h1_out)
delta_h2 <- (w6 * delta_o) * h2_out * (1 - h2_out)
dw5 <- h1_out * delta_o
dw6 <- h2_out * delta_o
dw1 <- x1 * delta_h1
dw3 <- x2 * delta_h1
dw2 <- x1 * delta_h2
dw4 <- x2 * delta_h2
db3 <- delta_o
db1 <- delta_h1
db2 <- delta_h2
# Actualizacion pesos
w1 <- w1 - alpha*dw1
w2 <- w2 - alpha*dw2
w3 <- w3 - alpha*dw3
w4 <- w4 - alpha*dw4
w5 <- w5 - alpha*dw5
w6 <- w6 - alpha*dw6
b1 <- b1 - alpha*db1
b2 <- b2 - alpha*db2
b3 <- b3 - alpha*db3
tabla <- rbind(tabla, data.frame(
Epoca=epoch,
w1=round(w1,6), w2=round(w2,6), w3=round(w3,6), w4=round(w4,6),
w5=round(w5,6), w6=round(w6,6),
b1=round(b1,6), b2=round(b2,6), b3=round(b3,6),
O1=round(o_out,6), E_total=round(error,6)
))
}
tabla %>%
kbl(caption = " Valores de los pesos y error total por epoca") %>%
kable_classic(full_width = FALSE, html_font = "Calibri") %>%
row_spec(0, bold = TRUE, background = "#dce6f1") %>%
column_spec(10:11, bold = TRUE, color = "black")
| Epoca | w1 | w2 | w3 | w4 | w5 | w6 | b1 | b2 | b3 | O1 | E_total |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0.1 | 0.5 | -0.698844 | 0.302550 | 0.208654 | 0.414982 | 0.001156 | 0.002550 | 0.026080 | 0.573499 | 0.090952 |
| 2 | 0.1 | 0.5 | -0.697669 | 0.305121 | 0.217081 | 0.429581 | 0.002331 | 0.005121 | 0.051439 | 0.582811 | 0.087024 |
Después de entrenar el modelo durante 2 épocas para aproximar la salida XOR=1 (teniendo en cuenta x1=0 y x2=1), se observa que el valor de O1 aumenta progresivamente de 0.573 a 0.583), aproximandose poco a poco al valor esperado. De la misma manera, el error total disminuye en cada iteracion de 0.091 a 0.087, lo que indica que la red neuronal está entrenandose correctamente.
Aunque todavía no alcanza el valor esperado en solo 2 épocas, se espera que con mayor numero de iteraciones, el modelo seguirá reduciendo el error y mejorará su aproximacion hasta 1. Esto muestra que el modelo esta optimizando los parámetros en la dirección correcta.