Actividad 6

Introduccion XOR

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

Planteamiento Modelo

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

Modelo

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")
Valores de los pesos y error total por epoca
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.