Fin de las muertes por hambre (prueba H2)
Con la penalización asimétrica de oscilación (+0,20 / −0,25), ninguna de las 30 partidas de evaluación debe terminar por hambre.
- Resultado
- Cumplida 0 de 30 por hambre (antes: 25 de 30).
Proyecto · snake_red_neuronal · bitácora científica de hipótesis
Esta página documenta paso a paso cómo encontramos la arquitectura, las entradas y los hiperparámetros para que una red neuronal aprenda a jugar Snake en el menor tiempo posible. En cada etapa partimos de un fallo concreto medido en los registros, formulamos una tesis con predicciones numéricas antes de correr, ejecutamos el experimento en CPU y comprobamos qué ocurrió.
Panorama experimental · Las 5 corridas medidas en 30 partidas de evaluación
Media móvil de manzanas comidas durante el entrenamiento. Usa el botón de arriba a la derecha para cambiar el eje X entre episodios de entrenamiento y segundos reales de CPU.
entrenar.py · registros/historial_*.csv · evaluación sin azar en 30 semillas fijas
Todas las corridas se evaluaron en las mismas 30 semillas de prueba (5000 a 5029) con exploración apagada (ε = 0):
| Corrida | Tesis probada | Entradas y red | Tiempo CPU | Media eval. | Máximo | Muertes (pared / cuerpo / hambre) |
|---|
registros/historial_c1_base.csv · 240 episodios · 8,1 s
La Corrida 1 (c1_base) es el intento directo: le damos a una red de 48 neuronas ocultas las 6 coordenadas normalizadas
del juego (cabeza_x, cabeza_y, manzana_x, manzana_y, dx, dy) y la entrenamos con Q-Learning dando +10 al comer,
−10 al chocar y 0 en cualquier otro paso.
El resultado después de 240 partidas es 0,23 manzanas por partida (igual que jugar al azar). Al inspeccionar cómo terminan las
30 partidas de evaluación aparece la causa: 25 de las 30 partidas terminan por límite de pasos sin comer y solo 4 por choque contra la pared.
La red descubrió que girar siempre hacia el mismo lado no recibe el castigo de −10.
H1 · Invarianza egocéntrica. Con coordenadas crudas (hx, hy, fx, fy), aprender a esquivar una pared en
(0, 2) no enseña nada sobre (9, 7). Si reemplazamos las coordenadas por 11 entradas relativas a la cabeza
(3 peligros a 1 paso, 4 de dirección actual y 4 indicando el cuadrante de la manzana), las 100 casillas del tablero colapsan en un
mismo espacio de menos de 300 estados posibles.
H2 · Guía asimétrica por distancia y hambre. Para que girar en círculo deje de ser gratis, sumamos +0,20 cuando un
paso reduce la distancia Manhattan a la manzana y −0,25 cuando la aumenta (cada vuelta en círculo pierde −0,10),
y cortamos la vida con castigo −10 si pasa 100 × largo pasos sin comer.
registros/historial_c2_egocentrico.csv · 240 episodios · 6,7 s
Antes de correr la Corrida 2 dejamos escritas tres predicciones verificables:
Con la penalización asimétrica de oscilación (+0,20 / −0,25), ninguna de las 30 partidas de evaluación debe terminar por hambre.
Al compartir los 3 sensores de peligro en todas las casillas, los choques contra las 4 paredes deben bajar a menos del 15 % de las partidas antes del episodio 100.
La media de evaluación debe superar las 12 manzanas en menos de 240 episodios.
La mejora es dramática: de 0,23 a 19,53 manzanas. Pero al revisar las estadísticas de la Corrida 2 aparecen dos cuellos de botella:
registros/historial_c3_replay_rapido.csv · Double DQN
¿Cuánto tiempo de CPU se va en simular el tablero de Snake y cuánto en calcular gradientes de PyTorch? Medimos ambos tiempos por separado:
dar un paso en snake.py tarda ~12 microsegundos, mientras que un paso de backward() + step() tarda ~350 microsegundos.
Además, entrenar con estados consecutivos viola el supuesto de muestras independientes.
Guardamos las transiciones en un ReplayBuffer de 10 000 muestras, agregamos una Red Objetivo (Double DQN sincronizada cada
8 episodios) y actualizamos un mini-batch de 64 muestras solo cada K = 4 pasos del juego.
Entrenar cada K = 4 pasos en lote debe reducir el tiempo total de los 240 episodios al menos un 35 % respecto a entrenar en cada paso.
Si el techo de ~19 manzanas se debiera a gradientes inestables, Double DQN + Replay debería superar las 25 manzanas. Si se mantiene en ~18–20 con >85 % de muertes contra el cuerpo, el límite está en las 11 entradas.
El resultado de P5 es clave: ni el mejor optimizador del mundo puede evitar que la serpiente se encierre si sus sensores no ven el callejón.
registros/historial_c4_floodfill.csv · 14 entradas
Repetimos cuadro a cuadro las muertes de c3_replay_rapido cuando la serpiente supera las 20 casillas de largo. En casi todas pasa lo mismo:
el cuerpo forma un anillo o bolsillo contra una pared; la casilla de entrada al bolsillo está vacía (así que el sensor de peligro a 1 casilla vale 0),
y como la manzana está en esa dirección, la red entra al bolsillo. Tres turnos después se le acaban las casillas libres.
Una forma de ver todo el tablero sería pasar la grilla de 10×10 por una red convolucional (CNN), pero eso multiplicaría por 20 el número de parámetros y por 50 el tiempo de entrenamiento. En cambio, formulamos H4:
Agregamos solo 3 números al vector de estado (pasando de 11 a 14 entradas): para cada acción candidata (recto, derecha,
izquierda), contamos con una búsqueda en anchura (BFS acotada a 2,5 × largo casillas) qué fracción del espacio libre es alcanzable
desde esa casilla. Además, si la red elige entrar a una cavidad cerrada (< 65 % del mejor camino disponible), recibe una penalización proporcional.
Con las 3 entradas de espacio alcanzable (estado_14), la media en las 30 partidas de evaluación debe superar las 30 manzanas.
El promedio de pasos sobrevividos por partida debe más que duplicarse respecto a C3.
C3 (11 entradas, ciega a callejones) contra C4 (14 entradas con Flood-Fill)
A partir del episodio 60 (~3 segundos de entrenamiento), C4 aprende a leer los 3 sensores de espacio libre y despega por encima del techo donde se estancan todas las redes de 11 entradas.
registros/historial_c5_neuroevolucion.csv · 30 generaciones · 45 individuos
Con las 14 entradas de H4 ya validadas, nos hicimos la última pregunta: ¿qué método entrena mejor una red para Snake, el aprendizaje por refuerzo con gradientes (Double DQN) o evolucionar una población de redes sin derivadas (Neuroevolución / Algoritmo Genético)?
Para que la búsqueda evolutiva fuera rápida, redujimos la red a 14 → 12 → 3 (219 parámetros en vez de los 1 155 de DQN).
En el camino tuvimos que resolver tres hipótesis internas dentro de la propia neuroevolución:
| Variante de Neuroevolución probada | Qué pasaba | Media en evaluación |
|---|---|---|
| H5a · Cruza uniforme + mutación Mezclar 50 % de los pesos de 2 padres de la élite |
Problema de las convenciones competitivas: la neurona oculta k codifica cosas distintas en cada padre; cruzarlas destruye a los hijos. | 1,03 manzanas |
| H5b · Reproducción clonal + mutación suave Sin cruza; mutar 15 % de pesos con σ = 0,22, pesos iniciales normales |
Al inicio de la partida (largo = 3) el tablero está vacío y los 3 sensores flood-fill valen siempre 1,0, saturando las neuronas ocultas antes de aprender a no chocar. |
3,83 manzanas |
| H5c · Atenuación inicial de sensores de cola Multiplicar por 0,1 los pesos iniciales de las entradas 11..13 |
Las primeras generaciones aprenden rápido a comer y esquivar paredes con las entradas 0..10; después las mutaciones activan gradualmente las entradas 11..13 cuando las serpientes ya son largas. | 29,20 manzanas (máx 35) |
Configuración ganadora verificada en entrenar.py
Si quieres entrenar desde cero una red que juegue un Snake excelente en apenas 6 a 14 segundos de CPU, esta es la combinación óptima encontrada tras resolver las 5 tesis:
| Componente | Valor óptimo | Por qué es crítico (Tesis) |
|---|---|---|
| Acciones de salida | 3 giros relativos (recto, der, izq) | Elimina de raíz el choque de 180° contra el propio cuello. |
| Entradas (Estado) | 14 números (estado_14) | H1 + H4: 11 sensores egocéntricos dan invarianza espacial; los 3 sensores flood-fill evitan encerrarse en la cola. |
| Arquitectura | 14 → 64 (ReLU) → 3 (DQN) 14 → 12 (ReLU) → 3 (Evolución) | Suficiente capacidad sin desperdiciar tiempo de CPU en multiplicaciones de matrices grandes. |
| Recompensas | +10 comer · −10 morir +0,20 acercarse · −0,25 alejarse castigo cavidad si espacio < 65% | H2 + H4: la asimetría +0,20 / −0,25 impide ganar puntos bailando en círculo, y el castigo de cavidad enseña rápido a no meterse en callejones. |
| Algoritmo y cadencia | Double DQN · lote 64 · K = 4 Replay 12 000 · Target cada 8 ep | H3: entrenar cada 4 pasos acelera 3,4× el entrenamiento en CPU y estabiliza los valores Q. |
| Exploración y tasa | Adam lr = 0,0035 · γ = 0,90 ε: 0,65 × 0,945ep (mín 0,005) | Con solo 14 entradas invariantes, la exploración puede bajar rápido: en el episodio 50 ya explota lo aprendido. |