Algoritmo Básico De Una Red Neuronal (II)

En este artículo os reproduciré un ejemplo simple de cómo se implementa un algoritmo de red neuronal en Python usando numpy (sin necesidad de librerías de aprendizaje automático como TensorFlow o PyTorch). Este ejemplo será para una red neuronal feedforward básica de una sola capa oculta, y se utilizará para un problema de regresión.

La red neuronal tendrá:

  • Una capa de entrada con 2 neuronas (para 2 características de entrada).
  • Una capa oculta con 2 neuronas.
  • Una capa de salida con 1 neurona.

Algoritmo de Red Neuronal: Ejemplo en Python

import numpy as np

# Paso 1: Inicialización de parámetros
# Definimos el número de neuronas en cada capa
input_layer_size = 2  # 2 características de entrada
hidden_layer_size = 2  # 2 neuronas en la capa oculta
output_layer_size = 1  # 1 neurona en la capa de salida

# Inicialización aleatoria de los pesos y sesgos
np.random.seed(42)  # Fijamos una semilla para reproducibilidad
weights_input_hidden = np.random.randn(input_layer_size, hidden_layer_size)  # Pesos de la capa de entrada a la capa oculta
bias_hidden = np.random.randn(1, hidden_layer_size)  # Sesgos para la capa oculta

weights_hidden_output = np.random.randn(hidden_layer_size, output_layer_size)  # Pesos de la capa oculta a la capa de salida
bias_output = np.random.randn(1, output_layer_size)  # Sesgos para la capa de salida

# Paso 2: Definir la función de activación (ReLU para la capa oculta y sigmoide para la capa de salida)
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

def relu(x):
    return np.maximum(0, x)

def relu_derivative(x):
    return np.where(x > 0, 1, 0)

# Paso 3: Propagación hacia adelante (Forward Propagation)
def forward_propagation(X):
    # Capa oculta
    z_hidden = np.dot(X, weights_input_hidden) + bias_hidden
    a_hidden = relu(z_hidden)  # Activación de la capa oculta

    # Capa de salida
    z_output = np.dot(a_hidden, weights_hidden_output) + bias_output
    a_output = sigmoid(z_output)  # Activación de la capa de salida

    return a_output, a_hidden

# Paso 4: Retropropagación (Backpropagation)
def backward_propagation(X, y, a_output, a_hidden, learning_rate=0.1):
    # Cálculo del error en la capa de salida
    error_output = y - a_output  # Diferencia entre salida esperada y salida predicha
    d_output = error_output * sigmoid_derivative(a_output)  # Gradiente de la capa de salida

    # Cálculo del error en la capa oculta
    error_hidden = d_output.dot(weights_hidden_output.T)
    d_hidden = error_hidden * relu_derivative(a_hidden)  # Gradiente de la capa oculta

    # Actualización de los pesos y sesgos
    weights_hidden_output += a_hidden.T.dot(d_output) * learning_rate
    bias_output += np.sum(d_output, axis=0, keepdims=True) * learning_rate

    weights_input_hidden += X.T.dot(d_hidden) * learning_rate
    bias_hidden += np.sum(d_hidden, axis=0, keepdims=True) * learning_rate

# Paso 5: Entrenamiento del modelo
def train(X, y, epochs=10000, learning_rate=0.1):
    for epoch in range(epochs):
        # Propagación hacia adelante
        a_output, a_hidden = forward_propagation(X)

        # Retropropagación
        backward_propagation(X, y, a_output, a_hidden, learning_rate)

        # Cada cierto número de épocas, imprimimos el error para ver cómo disminuye
        if epoch % 1000 == 0:
            loss = np.mean(np.square(y - a_output))  # Error cuadrático medio (MSE)
            print(f"Epoch {epoch}/{epochs}, Loss: {loss}")

# Paso 6: Probar la red neuronal
def predict(X):
    a_output, _ = forward_propagation(X)
    return a_output

# Datos de entrada (X) y salida esperada (y) para entrenamiento
# X son las características de entrada, y es el valor esperado
X_train = np.array([[0, 0],
                    [0, 1],
                    [1, 0],
                    [1, 1]])  # Ejemplo de datos para una operación lógica

y_train = np.array([[0],  # Salida esperada para 0 AND 0
                    [0],  # Salida esperada para 0 AND 1
                    [0],  # Salida esperada para 1 AND 0
                    [1]])  # Salida esperada para 1 AND 1

# Entrenamos la red neuronal
train(X_train, y_train)

# Hacemos una predicción después del entrenamiento
print("\nPredicciones después del entrenamiento:")
print(predict(np.array([[0, 0]])))  # Predicción para entrada [0, 0]
print(predict(np.array([[0, 1]])))  # Predicción para entrada [0, 1]
print(predict(np.array([[1, 0]])))  # Predicción para entrada [1, 0]
print(predict(np.array([[1, 1]])))  # Predicción para entrada [1, 1]

Explicación del código:

  1. Inicialización:
    • Definimos el tamaño de las capas de entrada, oculta y salida.
    • Inicializamos los pesos y sesgos aleatoriamente para cada capa de la red neuronal.
  2. Funciones de Activación:
    • Usamos ReLU para la capa oculta porque es buena para introducir no linealidades.
    • Usamos sigmoide en la capa de salida, ya que la salida está en el rango (0, 1), ideal para problemas de clasificación o regresión con valores entre 0 y 1.
  3. Propagación hacia adelante:
    • Calculamos las salidas de las capas ocultas y de salida. Primero, las entradas pasan por la capa oculta, luego por la capa de salida.
  4. Retropropagación:
    • Calculamos el error entre la salida predicha y la salida real.
    • Retropropagamos este error para ajustar los pesos y sesgos utilizando el gradiente descendente.
  5. Entrenamiento:
    • Entrenamos la red con el algoritmo de retropropagación, y en cada época, actualizamos los pesos y sesgos para reducir el error.
  6. Predicciones:
    • Después de entrenar, hacemos predicciones con entradas que no han sido vistas para comprobar el funcionamiento de la red.

Salida Esperada:

Al ejecutar el código, deberías ver una reducción en el error (pérdida) a medida que se entrenan las épocas, y finalmente, las predicciones deben ser cercanas a los valores esperados:

Epoch 0/10000, Loss: 0.28950632772032997
Epoch 1000/10000, Loss: 0.03868588393150106
Epoch 2000/10000, Loss: 0.022606473339225327
Epoch 3000/10000, Loss: 0.016220257878795697
...
Predicciones después del entrenamiento:
[[0.0180578]]
[[0.97369339]]
[[0.97381397]]
[[0.98883593]]

Aquí puedes ver cómo la red neuronal aprende a hacer predicciones correctas (en este caso, una operación lógica AND).

¡¡OJO!!:

  • Este ejemplo es muy básico y se puede ampliar con redes más profundas (más capas ocultas), diferentes funciones de activación, y usando técnicas de optimización más avanzadas.
  • El uso de librerías como TensorFlow o PyTorch facilita mucho el proceso de entrenamiento y la implementación de redes neuronales más complejas.

Un comentario sobre “Algoritmo Básico De Una Red Neuronal (II)

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *