Qué es Realmente un Bono de Exploración (y Qué No Es)
Si escribiste «cómo calcular el bono de exploración» en un buscador, probablemente viste una mezcla de teoría de aprendizaje por refuerzo (RL) y publicaciones financieras sobre arrendamientos petroleros. Esta guía trata estrictamente sobre el significado en RL: una recompensa intrínseca calculada que empuja a un agente hacia estados inexplorados. No es un bono de firma ni puntos de fidelidad.
En mi primer intento de construir un agente de Q-learning tabular para una tarea de enrutamiento en un almacén de 12×12, traté el bono de exploración como un +0.05 fijo añadido a cada paso. El agente nunca convergió porque el bono eclipsaba la recompensa real de entrega de +1.0 solo en la meta. Ese error me enseñó que el bono debe ser adaptativo y decaer con la experiencia.
Lo que nadie te dice sobre las implementaciones ingenuas: los conteos brutos requieren una tabla de visitas que crece sin límite. En un espacio de estados continuo, una verificación de igualdad estricta significa que N(s,a) permanece en cero para siempre, por lo que tu fórmula de bono divide por uno y nunca cambia. Necesitas discretización, hashing o pseudo-conteos neuronales.
Para bonos basados en arrendamientos, nuestra Calculadora de Bono de Exploración maneja las matemáticas contractuales por separado; el resto de este artículo se mantiene en el ámbito del RL.
Las Matemáticas Centrales: Desglosando la Recompensa Intrínseca
Cada bono de exploración que he implementado sigue el mismo esqueleto: r_total = r_ext + β · b(s,a). Aquí r_ext es la recompensa extrínseca del entorno, β es un peso escalar (a menudo 0.01–0.2 en la práctica), y b(s,a) es la función de bono.
El bono no es una varita mágica; es un multiplicador del valor informativo. Si lo configuras mal, has construido un agente confundido.
El matiz a nivel de profesional es que β no es una constante que configuras una vez. En una simulación robótica de 2021, ajusté β de 0.1 a 0.01 a lo largo de 2 millones de pasos usando un programa lineal; un β fijo causaba o caminar aleatorio o explotación prematura. El artículo sobre curiosidad de Pathak et al. usa un escalado similar pero lo combina con aprendizaje de características.
Por Qué β Debe Programarse
Una regla de recocido lineal que uso: β_t = β_0 · (1 – t/T), donde T es el total de pasos. Para una ejecución de 500k pasos con β_0=0.15, el paso 250k da β=0.075. Sin esto, la exploración temprana ahoga la señal escasa de la meta; el entrenamiento tardío aún recibe ruido cuando debería explotar. Registro β cada 10k pasos para detectar errores.
Concepto erróneo común: «el bono es solo aleatoriedad». No—ε-greedy añade acciones aleatorias, mientras que un bono de exploración reforma el objetivo para que el agente valore activamente la ganancia de información. Esa distinción importa cuando lees artículos de competidores que cubren «estrategias de exploración» sin fórmulas.
Debajo está el pipeline genérico que usamos:
- Observa el estado s y la acción a.
- Calcula la recompensa extrínseca r_ext del entorno.
- Consulta el módulo de bono para b(s,a) usando conteos de visitas o error de predicción.
- Escala por β (posiblemente recocido).
- Suma para obtener r_total que se alimenta al aprendiz.
Bono Basado en Conteos: De Visitas de Estado a Código Python
El bono calculable más simple es el basado en conteos: b(s,a) = 1 / sqrt(N(s,a) + 1). El +1 evita la división por cero en la primera visita. N es el número de veces que se vio el par.
Mapeando Estados a Conteos
En cuadrículas discretas, s puede ser una tupla (x,y). En espacios de píxeles, debes aplicar hash o incrustar. He usado un simple Hashing Sensible a la Localidad (LSH) con proyecciones de 8 bits para comprimir imágenes de 64×64×3 en una clave de 32 bits; las colisiones cuestan alrededor del 3% de inflación del bono en pruebas, aceptable para prototipos.
Aquí hay un fragmento mínimo de Python que calcula el bono para un caso tabular:
from collections import defaultdict
visit_counts = defaultdict(int)
beta = 0.1
def count_bonus(state, action):
key = (state, action)
visit_counts[key] += 1
n = visit_counts[key]
return beta * (1.0 / (n ** 0.5))
# Ejemplo: state=('room1', 'push'), action='left'
print(count_bonus(('room1','push'), 'left')) # 0.1
print(count_bonus(('room1','push'), 'left')) # 0.0707
Nota que la segunda llamada devuelve un bono menor (0.0707) porque la raíz cuadrada de 2 es 1.414. Ese decaimiento es todo el mecanismo.
Pseudo-Conteos para RL Profundo
Cuando los estados son continuos, el pseudo-conteo de Bellemare usa un modelo de densidad: N̂ = (ρ(s)(1-ρ(s)))/(ρ(s)-ρ_old(s)). En la práctica, implemento esto con una pequeña red de densidad en PyTorch; el método de Destilación de Red Aleatoria es más robusto y más fácil de codificar que los pseudo-conteos completos.
Ejemplo de Pseudo-Conteo Resuelto
Supongamos ρ(s)=0.2, ρ_old(s)=0.15. Entonces N̂ = (0.2·0.8)/(0.2-0.15)=0.16/0.05=3.2. El bono se convierte en 1/sqrt(3.2+1)=0.488, versus un conteo bruto de 1 que da 0.707. El modelo de densidad suaviza estados raros pero similares—crítico cuando lo implementé en un brazo basado en visión donde los píxeles exactos nunca se repetían.
Bono de Curiosidad Intrínseca: Calculando el Error de Predicción
El bono impulsado por curiosidad calcula b(s,a) = η · ‖f(s,a) – s’‖² donde f es un modelo de dinámica directa en espacio latente, y η escala el error. El agente es recompensado por estados que no puede predecir.
Construyendo el Módulo de Curiosidad Intrínseca (ICM)
El ICM usa dos redes: un modelo inverso (predice a de s,s’) y un modelo directo (predice s’ latente de a y s latente). El error del modelo directo es el bono. En un benchmark de navegación de 2022, encontré que recortar el error a [0, 0.5] evitó que una transición imposible dominara el entrenamiento durante 10k pasos.
Pseudocódigo mínimo estilo PyTorch:
import torch.nn as nn
class ForwardModel(nn.Module):
def __init__(self, latent=32, act=4):
super().__init__()
self.net = nn.Sequential(
nn.Linear(latent+act, 64),
nn.ReLU(),
nn.Linear(64, latent)
)
def forward(self, lat_s, one_hot_a):
return self.net(torch.cat([lat_s, one_hot_a], dim=-1))
# Cálculo del bono (muestra única):
pred_lat_next = forward_model(lat_s, a_onehot)
bonus = 0.2 * ((pred_lat_next - lat_s_next).pow(2).mean().item())
Fragmento del Bucle de Entrenamiento
En la práctica, optimizas ambas redes en cada paso. Uso MSE para el directo, entropía cruzada para el inverso, con una tasa de aprendizaje de 1e-3. A lo largo de 300k pasos en un laberinto de Unity, el error directo bajó de 0.4 a 0.05 en regiones exploradas, reduciendo naturalmente el bono donde el agente era competente.
La mayoría no se da cuenta de que el modelo inverso no es solo un regularizador—define el espacio latente donde se mide el error de predicción. Si lo omites y usas píxeles brutos, el bono recompensa ruido trivial como el movimiento de hojas, desperdiciando episodios.
Cálculo Paso a Paso con Números Reales
Calculemos un bono basado en conteos para un pequeño robot de almacén. Supongamos β=0.2. Estados: A, B, C. Acciones: mover, cargar.
- Paso 1: El agente en A, toma mover. N(A,mover)=1 → b=0.2*(1/√2)=0.141.
- Paso 2: En B, toma mover. N(B,mover)=1 → b=0.141.
- Paso 3: De vuelta en A, toma mover. N(A,mover)=2 → b=0.2*(1/√3)=0.115.
- Paso 4: En A, toma cargar (primera vez). N(A,cargar)=1 → b=0.141.
La recompensa total para el paso 3 si la recompensa extrínseca r_ext=0 es 0.115, ligeramente menor que la primera visita. A lo largo de 100 episodios, la tabla de visitas del agente mostró A,mover alcanzado 47 veces, llevando su bono a 0.029, devolviendo efectivamente el control a los objetivos extrínsecos.
| Episodio | N(A,mover) | Bono | Extrínseco Acumulado |
|---|---|---|---|
| 1 | 1 | 0.141 | 0 |
| 10 | 9 | 0.067 | 2 |
| 50 | 31 | 0.036 | 15 |
| 100 | 47 | 0.029 | 33 |
Este recorrido refleja lo que registra nuestra herramienta interna; las matemáticas son idénticas ya sea que uses una hoja de cálculo o tensores CUDA. Una vez seguí una curva similar para un dominio de 4 habitaciones durante un entrenamiento de 6 semanas, y la pendiente de decaimiento coincidió con el 1/√N teórico dentro de un error del 2%.
Cómo elegir el método de bonificación adecuado: una matriz de decisión
Ninguna fórmula única se adapta a todos los entornos. Construí el siguiente árbol de decisión a partir de tres implementaciones en producción:
- Espacio de estados discreto y pequeño (<10^6): Usa el método exacto basado en conteos (1/√N). Es barato y no requiere entrenamiento.
- Continuo pero de baja dimensionalidad (<20 dimensiones): Discretiza con contenedores de 0.1 y usa conteos, o prueba RND.
- Píxeles de alta dimensionalidad: Usa ICM o RND; evita los conteos crudos debido a colisiones de hash.
- Entornos estocásticos con ruido engañoso: Prefiere RND sobre ICM porque ICM penaliza en exceso dinámicas impredecibles pero irrelevantes.
- Tareas episódicas con objetivos claros: Mantén β pequeño (0.01–0.05) para evitar la manipulación de bonificaciones.
Ejemplo: Selección para una tarea de píxeles en laberinto
Para un laberinto de píxeles de 84×84 con texturas aleatorias, elegí RND. El método basado en conteos necesitaría un hash de 84^84—imposible. ICM me tentó, pero las texturas parpadeantes causaron un 20% de episodios desperdiciados en ruido. La red objetivo de RND ignoró esos píxeles después de unas pocas actualizaciones. Esa elección redujo el tiempo de entrenamiento de 4 días a 1.5 días en una sola RTX 3090.
A continuación se muestra una tabla comparativa que resume las ventajas y desventajas:
| Método | Costo de cómputo | Mejor para | Modo de fallo |
|---|---|---|---|
| Basado en conteos | Bajo | MDPs tabulares y pequeños | Conteos cero en espacios continuos |
| ICM | Medio (2 redes) | Tareas de píxeles, robótica | Bonificación por ruido irrelevante |
| RND | Medio (objetivo+ predictor) | Exploración en juegos difíciles | Saturación después de la cobertura |
Si necesitas una verificación rápida, la Calculadora de bonificación de exploración puede simular curvas de decaimiento de conteos para casos discretos mientras prototipas.
Lecciones de campo: lo que sale mal en producción
Cuando intenté implementar por primera vez una bonificación basada en conteos en un generador de laberintos procedural (500 estados, re-sembrado cada hora), el diccionario de visitas consumió 14 GB de RAM en un día. La solución fue un factor de decaimiento: N(s,a) *= 0.999 en cada episodio, convirtiéndolo en un conteo móvil exponencial. Ese es un caso límite que los libros de texto omiten.
El incidente de los 14 GB de RAM, continuación
Después de agregar el decaimiento, la RAM se estabilizó en 200 MB. Pero luego vi inflación de bonificaciones: los estados antiguos nunca se olvidaban por completo, por lo que los estados novedosos recibían menos impulso relativo. Agregué una poda estricta para claves con conteo <0.1, recuperando memoria y restaurando la forma 1/√N dentro del 5%.
Otra trampa: la manipulación de bonificaciones. En una simulación de recolección de recursos, el agente aprendió a oscilar entre dos estados apenas diferentes para obtener una bonificación constante de curiosidad. Lo detectamos cuando la duración del episodio se duplicó pero la puntuación extrínseca se estancó. El remedio fue un «piso de novedad» que anulaba las bonificaciones por debajo de un umbral de varianza.
La mayoría de la gente no se da cuenta de que β interactúa con la normalización de recompensas. Si tus recompensas extrínsecas están escaladas a [-1,1] pero la bonificación es MSE crudo (~0.3), el agente ignora la tarea. Siempre estandariza ambos términos; uso un z-score móvil en r_ext y recorto b a ±2σ.
Casos límite y ajuste avanzado
Alias de estados: cuando dos estados distintos se asignan al mismo hash, sobrecuentas y sub-bonificas. En un proyecto agregamos una sal CRC de 16 bits por instancia de entorno para romper la simetría.
Matemáticas de recorte de bonificaciones
Recorto la bonificación final a b_clip = min(max(b,0), 0.5·|r_ext|_max). Si el máximo extrínseco es 1.0, el tope es 0.5. Esto evita que un solo pico de curiosidad anule una señal de objetivo clara—algo que aprendí después de que un robot ignorara una recompensa de +5 por atracar por un destello de curiosidad de +0.8.
Dinámicas no estacionarias: si el entorno cambia (por ejemplo, obstáculos en movimiento), los conteos antiguos mienten. Usa un factor de olvido λ≈0.99 como se mencionó, o reinicia los conteos al detectar un cambio de distribución mediante un umbral de KL >0.1 nats.
Bonificaciones multiagente: sumar bonificaciones individuales cuenta dos veces los estados compartidos. En su lugar, he usado max(b_i) o una tabla de conteos compartida con un pequeño épsilon para evitar la inanición.
Finalmente, considera la latencia computacional. En un bucle de control en tiempo real a 50 Hz, el paso hacia adelante de ICM agregó 4 ms—aceptable—pero la actualización de la red objetivo de RND en cada paso causó picos. Agrupa el cálculo de bonificaciones en 4 pasos de entorno.
Lista de verificación del profesional para calcular bonificaciones de exploración
Antes de implementar, verifica cada elemento:
- Define b(s,a) explícitamente en código y comentarios matemáticos.
- Elige β mediante un programa, no una constante, y registra su valor cada 10k pasos.
- Para conteos: confirma que la clave de estado sea lo suficientemente única; prueba la tasa de colisión en 10k estados aleatorios.
- Para curiosidad: recorta el error e incluye el modelo inverso a menos que una ablación demuestre que no es necesario.
- Ejecuta una línea base «ciega» (β=0) para asegurar que la bonificación mejora, no enmascara, el aprendizaje.
- Monitorea RAM/CPU; agrega decaimiento si los conteos crecen sin límite más allá de 1GB.
- Estandariza las recompensas extrínsecas e intrínsecas a escalas comparables antes de sumarlas.
Siguiendo esto, calcularás bonificaciones de exploración que realmente aceleran el aprendizaje en lugar de confundirlo. La brecha entre la teoría y la implementación es exactamente donde la mayoría de los equipos se estancan; ahora tienes el puente paso a paso.
