Proyecto · snake_red_neuronal · bitácora científica de hipótesis

De 0,2 a 35 manzanas en 13 segundos de CPU

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

Eje horizontal
C1 · Base (6 crudas) C2 · H1+H2 (11 egocéntricas) C3 · H3 (DQN + Replay K=4) C4 · H4 (DQN 14 + Flood-Fill) C5 · H5 (Neuroevolución 14)

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.

1

Resumen de las 5 corridas

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)
2

Por qué la corrida base no aprende nada

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.

Las dos primeras hipótesis (H1 y H2)

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.

3

Corrida 2: H1 y H2 despegan hasta ~19,5 manzanas

registros/historial_c2_egocentrico.csv · 240 episodios · 6,7 s

Antes de correr la Corrida 2 dejamos escritas tres predicciones verificables:

P1

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).
P2

Generalización inmediata a bordes (prueba H1)

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.

Resultado
Cumplida Solo 2 de 30 muertes contra pared (6,7 %).
P3

Salto de puntaje a dos dígitos

La media de evaluación debe superar las 12 manzanas en menos de 240 episodios.

Resultado
Cumplida Media de 19,53 manzanas (máximo 33).

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:

  1. Tiempo de cómputo e inestabilidad: actualizar los pesos con backpropagation en cada turno individual hace que la curva oscile brusco cuando una partida larga pisa los pesos recién aprendidos.
  2. Cómo muere ahora la serpiente: en 28 de las 30 partidas (93 %) la serpiente muere chocando contra su propio cuerpo.
4

H3: Replay Buffer y cadencia K = 4 para entrenar en 4 segundos

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.

H3 · El cambio de ingeniería para velocidad y estabilidad

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.

P4

Reducción del tiempo de entrenamiento

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.

Resultado
Cumplida Baja de 6,68 s a 4,25 s (y en igualdad de arquitectura 64 ocultas en la lección 4 acelera 3,41×).
P5

Diagnóstico del techo de ~19 manzanas

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.

Resultado
Confirmada Queda en 18,40 manzanas (máx 34) con 28 de 30 muertes contra el cuerpo.

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.

5

H4: Por qué se encierra la serpiente larga y el sensor Flood-Fill

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:

H4 · Tres sensores topológicos de espacio libre (Flood-Fill)

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.

P6

Ruptura de la barrera de las 20 manzanas

Con las 3 entradas de espacio alcanzable (estado_14), la media en las 30 partidas de evaluación debe superar las 30 manzanas.

Resultado
Cumplida Salta de 18,40 a 35,57 manzanas de media (mediana 36,5 y máximo 50 manzanas).
P7

Supervivencia más de 2 veces mayor

El promedio de pasos sobrevividos por partida debe más que duplicarse respecto a C3.

Resultado
Cumplida Sube de 325 pasos por partida en C3 a 964 pasos en C4 (2,96× más vida).

C3 (11 entradas, ciega a callejones) contra C4 (14 entradas con Flood-Fill)

C3 · 11 entradas (techo en ~19 manzanas) C4 · 14 entradas con Flood-Fill (llega a 35,6 de media)

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.

6

H5: Deep Q-Learning contra Neuroevolución

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 probadaQué pasabaMedia 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)

Comparación final: ¿DQN (C4) o Neuroevolución (C5)?

  • En puntaje máximo y eficiencia por segundo: gana Double DQN (C4). Aprovecha cada paso individual de la partida para ajustar los pesos con gradiente exacto, alcanzando 35,57 manzanas de media (máximo 50) en 13,8 segundos (y ya promedia 26+ manzanas a los 6 segundos).
  • En simplicidad y tamaño de red: destaca Neuroevolución (C5). Con solo 219 parámetros en NumPy puro (5 veces menos pesos que DQN) y sin ecuación de Bellman ni PyTorch, alcanza 29,20 manzanas de media (mediana 30,5) en 30 generaciones.
7

Los mejores parámetros para entrenar en tiempo mínimo

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:

ComponenteValor óptimoPor qué es crítico (Tesis)
Acciones de salida3 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.
Arquitectura14 → 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 cadenciaDouble 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 tasaAdam 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.