- Aproximación de Funciones con Redes Neuronales: De Tablas a DQN
Aproximación de Funciones con Redes Neuronales: De Tablas a DQN
En los métodos tabulares clásicos (como Q-Learning con tabla), cada par estado-acción tiene su propio valor almacenado explícitamente. Pero cuando el espacio de estados es continuo o enormemente grande (por ejemplo, los píxeles de una pantalla de videojuego), una tabla resulta inviable. La alternativa natural es aproximar la función Q(s, a) mediante una red neuronal, dando origen a las Deep Q-Networks (DQN). Esta lección recorre el puente entre lo tabular y lo profundo.
Motivación: ¿Por qué aproximar funciones?
Imagina un agente que debe aprender a jugar a un juego de Atari: la entrada son 210×160 píxeles con 128 colores posibles. El número de estados posibles es astronómico (12833600). Una tabla jamás podría almacenar todos esos valores. Además, los estados continuos (como coordenadas y velocidades en robótica) requieren generalización: la red neuronal aprende una representación compacta que interpola entre experiencias similares.
- Espacios grandes/continuos → inviables para tablas.
- Generalización → la red aprende patrones y transfiere conocimiento entre estados parecidos.
- Eficiencia de memoria → unos pocos pesos representan millones de pares estado-acción.
Arquitectura DQN: de píxeles a valores Q
Una Deep Q-Network recibe como entrada el estado (por ejemplo, los últimos 4 frames de un juego, cada uno procesado a 84×84 píxeles en escala de grises). La arquitectura clásica (Mnih et al., 2015) combina capas convolucionales para extraer características espaciales y capas fully connected para producir los valores Q de cada acción posible.
- Entrada: tensor 4×84×84 (4 canales temporales).
- Capas convolucionales: filtros 32, 64, 64 (kernel 8×8, 4×4, 3×3) + ReLU.
- Capas fully connected: 512 neuronas, luego salida con número de acciones (ej. 18 en Atari).
- Salida: vector de valores Q(s, a) para cada acción.
# pseudocódigo de la arquitectura (PyTorch estilo)
class DQN(nn.Module):
def __init__(self, num_acciones):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(4, 32, 8, stride=4), nn.ReLU(),
nn.Conv2d(32, 64, 4, stride=2), nn.ReLU(),
nn.Conv2d(64, 64, 3, stride=1), nn.ReLU(),
nn.Flatten()
)
self.fc = nn.Sequential(
nn.Linear(64*7*7, 512), nn.ReLU(),
nn.Linear(512, num_acciones)
)
def forward(self, x):
return self.fc(self.conv(x))
Mecanismos clave: replay buffer y target network
Entrenar una red neuronal con Q-Learning ingenuo es inestable por dos razones: (1) las transiciones consecutivas están correlacionadas; (2) la función objetivo (target) cambia con cada actualización, causando oscilaciones. DQN introduce dos innovaciones para resolverlo:
1 Replay Buffer (buffer de experiencia)
Almacena las transiciones (s, a, r, s', done) en una memoria circular. Durante el entrenamiento, se muestrea un mini-batch aleatorio de experiencias pasadas, rompiendo la correlación temporal y suavizando la distribución de datos.
2 Target Network (red objetivo)
Una copia congelada de la red principal (Q-network) se usa para calcular los targets de Bellman. Cada cierto número de pasos (por ejemplo, cada 10 000 iteraciones) se copian los pesos de la red principal a la target. Esto estabiliza el objetivo de regresión:
yi = r + γ · maxa' Qtarget(s', a')
Función de pérdida: Mean Squared Error (MSE)
La red principal se actualiza minimizando el error cuadrático medio entre el valor Q actual y el valor Q objetivo (target). Para una transición (s, a, r, s') la pérdida es:
- Q actual: Qmain(s, a) — predicción de la red principal.
- Q objetivo (target): r + γ · maxa' Qtarget(s', a') — usando la red target.
- Pérdida: L = (r + γ · maxa' Qtarget(s', a') − Qmain(s, a))2
Se propaga el gradiente solo a través de la red principal (la target no se actualiza por gradiente).
# pseudocódigo de la actualización
if len(replay_buffer) > batch_size:
batch = replay_buffer.sample(batch_size)
estados, acciones, recompensas, sig_estados, done = batch
# Q actual
q_actuales = red_principal(estados).gather(1, acciones)
# Q objetivo (con red target)
with torch.no_grad():
q_siguientes = red_target(sig_estados).max(1, keepdim=True)[0]
q_objetivo = recompensas + gamma * q_siguientes * (1 - done)
perdida = F.mse_loss(q_actuales, q_objetivo)
optimizador.zero_grad()
perdida.backward()
optimizador.step()
Algoritmo DQN detallado (paso a paso)
El procedimiento completo integra todos los elementos anteriores:
- Inicializar la red principal Q con pesos aleatorios θ y la red target Q̂ con θ− = θ.
- Inicializar replay buffer D con capacidad máxima N.
- Para cada episodio:
- Obtener estado inicial s (por ejemplo, preprocesar frames).
- Para cada paso del episodio:
- Seleccionar acción a usando política ε-greedy (con probabilidad ε elegir aleatoria, sino a = argmax Q(s, a; θ)).
- Ejecutar acción a, observar recompensa r y siguiente estado s'.
- Almacenar transición (s, a, r, s', done) en D.
- Muestrear mini-batch aleatorio de D.
- Calcular pérdida MSE con Q objetivo (usando Q̂).
- Actualizar θ mediante descenso de gradiente (Adam, lr=0.00025).
- Si el paso es múltiplo de C (ej. 10 000): copiar θ → θ− (actualizar red target).
Resumen visual del flujo de datos:
| Componente | Función |
|---|---|
| Entorno (Atari / simulación) | Produce estados y recompensas |
| Replay Buffer | Almacena y mezcla experiencias |
| Red principal (Q) | Selecciona acciones y se actualiza |
| Red target (Q̂) | Genera targets estables |
| Función de pérdida (MSE) | Guía el aprendizaje por regresión |
Convergencia y buenas prácticas
DQN demostró ser capaz de aprender a jugar a docenas de juegos de Atari a nivel sobrehumano. Para lograr estabilidad se recomienda:
- Preprocesamiento: reducir resolución a 84×84, escala de grises, y apilar 4 frames como estado.
- Clipping de recompensas: recortar recompensas a [-1, 1] para estabilizar gradientes.
- Exploración ε-greedy: empezar con ε=1.0 y decaer linealmente hasta 0.1.
- Replay buffer grande: capacidad típica 1 000 000 de transiciones.
- Frecuencia de copia a target: cada 10 000 pasos es un valor clásico.
Nota pedagógica: Has recorrido el camino desde la limitación de las tablas hasta la potencia de las redes profundas con DQN. La combinación de aproximación de funciones + replay buffer + target network es la base de los algoritmos modernos de deep reinforcement learning. Practica implementando este algoritmo en un entorno de Gym para consolidar cada detalle.
No hay comentarios por ahora.
Compartir este contenido
Compartir enlace
Compartir en redes sociales
Compartir por correo electrónico
Please iniciar sesión para compartir esto Artículo por correo electrónico.