Red Neuronal Multicapa

Las redes neuronales multicapa, también conocidas como redes profundas, representan una forma avanzada de inteligencia artificial que consta de múltiples capas de neuronas interconectadas.

Esta arquitectura más compleja permite a las redes multicapa aprender representaciones jerárquicas de datos, lo que las hace especialmente efectivas en tareas de procesamiento de imágenes, procesamiento de lenguaje natural y análisis de datos complejos.

Al igual que las redes monocapa, las redes multicapa utilizan algoritmos de aprendizaje supervisado como la retropropagación para ajustar sus pesos y sesgos durante el entrenamiento. Esto permite que la red aprenda de manera iterativa a partir de ejemplos etiquetados, mejorando gradualmente su capacidad para realizar tareas específicas con precisión y generalización.

A pesar de su mayor complejidad, las redes multicapa siguen siendo una herramienta fundamental en el campo de la inteligencia artificial, proporcionando soluciones poderosas y flexibles para una amplia variedad de problemas de análisis y predicción de datos.

Ejemplo

Implementamos una red neuronal multicapa para resolver el problema del operador lógico XOR.

Recuerde que la función XOR (Exclusive OR), es una función lógica que toma dos entradas binarias y produce una salida binaria.

La salida es 1 si exactamente una de las dos entradas es 1, y es 0 en cualquier otro caso.

Entrada 1Entrada 2Salida (XOR)

0

0

0

0

1

1

1

0

1

1

1

0

Importamos los módulos necesarios

import numpy as np

Definimos los datos de entrenamiento, donde x son los datos de entradas e y son las etiquetas.

# Datos de entrada y salida
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

Definición de la arquitectura de la red

np.random.seed(1)
input_neurons = 2
hidden_neurons = 4
output_neurons = 1

La red tiene una capa de entrada con dos neuronas (que corresponde a las dos características de entrada), una capa oculta con 4 neuronas y una capa de salida con una neurona.

Inicialización de los pesos y sesgos

weights_input_hidden = np.random.uniform(size=(input_neurons, hidden_neurons))
bias_hidden = np.random.uniform(size=(1, hidden_neurons))
weights_hidden_output = np.random.uniform(size=(hidden_neurons, output_neurons))
bias_output = np.random.uniform(size=(1, output_neurons))

Los pesos de las conexiones entre las neuronas se inicializan de manera aleatoria.

Definición de la función de activación

# Función de activación sigmoide
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# Derivada de la función sigmoide
def sigmoid_derivative(x):
    return x * (1 - x)

Está función puede ser cambiada por la función ReLU, por ejemplo.

Hiperparámetros

# Hiperparámetros
learning_rate = 0.1
epochs = 10000

Se definen la tasa de aprendizaje y el número de épocas para el entrenamiento.

Entrenamiento

# Entrenamiento de la red neuronal
for epoch in range(epochs):
    # Paso hacia adelante (Forward pass)
    input_layer = X
    hidden_layer_input = np.dot(input_layer, weights_input_hidden) + bias_hidden
    hidden_layer_output = sigmoid(hidden_layer_input)
    output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
    output = sigmoid(output_layer_input)

    # Cálculo del error
    error = y - output
    mse = np.mean((error) ** 2)
    # Mostrar el progreso
    if (epoch + 1) % 100 == 0:
        _mse = "{:.20f}".format(mse)
        print(f'Época {epoch + 1}, Loss function (MSE): {_mse}')
    
    # Retropropagación (Backpropagation)
    d_output = error * sigmoid_derivative(output)
    error_hidden = d_output.dot(weights_hidden_output.T)
    d_hidden = error_hidden * sigmoid_derivative(hidden_layer_output)

    # Actualización de pesos y sesgos
    weights_hidden_output += hidden_layer_output.T.dot(d_output) * learning_rate
    bias_output += np.sum(d_output, axis=0, keepdims=True) * learning_rate
    weights_input_hidden += input_layer.T.dot(d_hidden) * learning_rate
    bias_hidden += np.sum(d_hidden, axis=0, keepdims=True) * learning_rate

Predicciones

input_layer = X
hidden_layer_input = np.dot(input_layer, weights_input_hidden) + bias_hidden
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
predictions = sigmoid(output_layer_input)

print("Resultados finales:")
for i in range(0, len(X)):
    print(f"Input: {X[i]}, Target: {y[i]}, Predictions {predictions[i]}")

Calcular el error cuadrático medio (MSE)

mse = ((y - predictions) ** 2).mean()
print(f"Error Cuadrático Medio (MSE): {mse}")

Backpropagation

La retropropagación (backpropagation) es un algoritmo fundamental en el entrenamiento de redes neuronales, especialmente en redes neuronales multicapa.

Su objetivo es ajustar los pesos de la red neuronal de manera que minimicen la función de pérdida entre las salidas predichas por la red y las salidas deseadas (etiquetas) de los datos de entrenamiento.

El proceso de retropropagación en general es el siguiente:

  1. Paso hacia adelante (Forward Pass):

    • Durante el paso hacia adelante, las entradas se propagan desde la capa de entrada hasta la capa de salida de la red neuronal.

    • Cada neurona en una capa aplica una función de activación a la suma ponderada de sus entradas y pesos, generando una salida que se convierte en la entrada de la siguiente capa.

    • Finalmente, la red produce una salida predicha que se compara con las salidas deseadas (etiquetas) para calcular el error.

  2. Cálculo del Error:

    • El error se calcula como la diferencia entre las salidas predichas por la red y las salidas deseadas. Este error se utiliza para evaluar qué tan bien está funcionando la red en la tarea que se le ha asignado.

  3. Retropropagación (Backward Pass):

    • En el paso de retropropagación, el error se propaga hacia atrás a través de la red neuronal para ajustar los pesos y sesgos de manera que se reduzca la función de pérdida.

    • Comienza calculando el gradiente de la función de pérdida con respecto a las salidas de la capa de salida. Este gradiente indica cómo cambiar las salidas de la capa de salida para reducir el error.

    • Luego, este gradiente se propaga hacia atrás a través de las capas ocultas de la red mediante la regla de la cadena y el producto matricial. En cada capa oculta, se calcula el gradiente de la función de pérdida con respecto a las salidas de esa capa, utilizando el gradiente de la capa siguiente multiplicado por los pesos entre las capas.

    • Finalmente, se utilizan estos gradientes para ajustar los pesos y sesgos de la red utilizando el algoritmo de optimización elegido, como el descenso de gradiente.

  4. Actualización de Pesos y Sesgos:

    • Los pesos y sesgos se actualizan utilizando el gradiente descendente o alguna variante del mismo, como el descenso de gradiente estocástico (SGD) o el descenso de gradiente con momento (Momentum).

    • La tasa de aprendizaje es un hiperparámetro clave que controla qué tan grandes son los ajustes realizados en cada paso de actualización.

  5. Iteración:

    • Este proceso de paso hacia adelante, cálculo del error, retropropagación y actualización de pesos se repite durante múltiples épocas de entrenamiento hasta que el modelo converja y la función de pérdida se minimice en la medida de lo posible en el conjunto de entrenamiento.

En resumen, la retropropagación es el proceso mediante el cual se calculan los gradientes de la función de pérdida con respecto a los pesos y sesgos de la red neuronal, permitiendo así ajustar estos parámetros para mejorar el rendimiento de la red en la tarea que está aprendiendo.

Last updated