¿Qué son las Redes Neuronales Recurrentes (RNN)?

Las Redes Neuronales Recurrentes (RNN, por sus siglas en inglés) son un tipo de red neuronal diseñada para trabajar con datos secuenciales. A diferencia de las redes neuronales tradicionales, las RNN tienen conexiones que forman ciclos, lo que les permite mantener un estado interno y recordar información a lo largo de secuencias de datos.

Características Clave de las RNN:

  • Memoria: Las RNN pueden recordar información de entradas anteriores gracias a sus conexiones recurrentes.
  • Secuencialidad: Son ideales para datos donde el orden importa, como series temporales, texto, audio, etc.
  • Compartición de Parámetros: Los mismos parámetros (pesos) se aplican en cada paso de la secuencia, lo que reduce la complejidad del modelo.

Arquitectura de una RNN

La estructura básica de una RNN incluye una capa recurrente que procesa una secuencia de datos paso a paso. A continuación, se muestra un diagrama simplificado de una RNN:

x_t -> [h_t] -> y_t

Donde:

  • x_t es la entrada en el tiempo t.
  • h_t es el estado oculto en el tiempo t.
  • y_t es la salida en el tiempo t.

Fórmulas Matemáticas

  1. Estado Oculto: \[ h_t = \sigma(W_{hx} \cdot x_t + W_{hh} \cdot h_{t-1} + b_h) \] Donde:

    • \( W_{hx} \) es la matriz de pesos entre la entrada y el estado oculto.
    • \( W_{hh} \) es la matriz de pesos recurrentes.
    • \( b_h \) es el sesgo.
    • \( \sigma \) es una función de activación (por ejemplo, tanh o ReLU).
  2. Salida: \[ y_t = \phi(W_{hy} \cdot h_t + b_y) \] Donde:

    • \( W_{hy} \) es la matriz de pesos entre el estado oculto y la salida.
    • \( b_y \) es el sesgo.
    • \( \phi \) es una función de activación (por ejemplo, softmax para clasificación).

Ejemplo Práctico en Python

Vamos a implementar una RNN simple usando TensorFlow y Keras para predecir la siguiente palabra en una secuencia de texto.

Paso 1: Importar Librerías

import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN, Dense

Paso 2: Preparar Datos

Para este ejemplo, usaremos una secuencia de texto simple:

# Secuencia de texto
text = "hello world"
# Crear un diccionario de caracteres a índices
char_to_idx = {ch: idx for idx, ch in enumerate(sorted(set(text)))}
idx_to_char = {idx: ch for ch, idx in char_to_idx.items()}

# Convertir texto a secuencia de índices
sequence = [char_to_idx[ch] for ch in text]

# Crear datos de entrenamiento
X = []
y = []
seq_length = 3
for i in range(len(sequence) - seq_length):
    X.append(sequence[i:i+seq_length])
    y.append(sequence[i+seq_length])

X = np.array(X)
y = np.array(y)

Paso 3: Definir el Modelo

model = Sequential()
model.add(SimpleRNN(50, input_shape=(seq_length, len(char_to_idx))))
model.add(Dense(len(char_to_idx), activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Paso 4: Entrenar el Modelo

X_one_hot = tf.keras.utils.to_categorical(X, num_classes=len(char_to_idx))
model.fit(X_one_hot, y, epochs=100)

Paso 5: Hacer Predicciones

def predict_next_char(model, char_sequence):
    input_seq = [char_to_idx[ch] for ch in char_sequence]
    input_seq = np.expand_dims(input_seq, axis=0)
    input_seq = tf.keras.utils.to_categorical(input_seq, num_classes=len(char_to_idx))
    predicted_idx = np.argmax(model.predict(input_seq), axis=-1)
    return idx_to_char[predicted_idx[0]]

# Predecir el siguiente carácter después de "hel"
print(predict_next_char(model, "hel"))

Ejercicio Práctico

Ejercicio 1: Implementar una RNN para Predecir Números en una Secuencia

Descripción: Dada una secuencia de números, implementa una RNN que prediga el siguiente número en la secuencia.

Datos de Entrenamiento:

sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Pasos:

  1. Prepara los datos de entrenamiento.
  2. Define y compila el modelo RNN.
  3. Entrena el modelo.
  4. Realiza predicciones.

Solución:

# Paso 1: Preparar Datos
sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
X = []
y = []
seq_length = 3
for i in range(len(sequence) - seq_length):
    X.append(sequence[i:i+seq_length])
    y.append(sequence[i+seq_length])

X = np.array(X)
y = np.array(y)

# Paso 2: Definir el Modelo
model = Sequential()
model.add(SimpleRNN(50, input_shape=(seq_length, 1)))
model.add(Dense(1))

model.compile(loss='mse', optimizer='adam')

# Paso 3: Entrenar el Modelo
X = np.expand_dims(X, axis=-1)
model.fit(X, y, epochs=100)

# Paso 4: Hacer Predicciones
def predict_next_number(model, num_sequence):
    input_seq = np.expand_dims(num_sequence, axis=0)
    input_seq = np.expand_dims(input_seq, axis=-1)
    predicted_num = model.predict(input_seq)
    return predicted_num[0][0]

# Predecir el siguiente número después de [7, 8, 9]
print(predict_next_number(model, [7, 8, 9]))

Conclusión

En esta lección, hemos aprendido sobre las Redes Neuronales Recurrentes (RNN), su arquitectura y cómo se diferencian de las redes neuronales tradicionales. También hemos implementado una RNN simple en Python usando TensorFlow y Keras para predecir la siguiente palabra en una secuencia de texto. Finalmente, hemos practicado con un ejercicio para predecir números en una secuencia.

En la próxima lección, exploraremos variantes avanzadas de RNN como LSTM y GRU, que abordan algunas de las limitaciones de las RNN estándar.

© Copyright 2024. Todos los derechos reservados