|
| 1 | +# AtaxxZero - Post-mortem 03: por que los modelos no mejoraban y por que `v6` si despego |
| 2 | + |
| 3 | +> **Resumen:** durante varias semanas el entrenamiento parecia "estable" pero no |
| 4 | +> producia checkpoints claramente mejores. El problema no era una sola cosa ni |
| 5 | +> se resolvia eligiendo otro bootstrap. Habia varias fugas de calidad en la |
| 6 | +> generacion de datos, en la representacion del estado y en la integracion del |
| 7 | +> search con el training. `policy_spatial_v6` fue la primera corrida que junto |
| 8 | +> suficientes fixes correctos como para producir una mejora real. |
| 9 | +
|
| 10 | +--- |
| 11 | + |
| 12 | +## Sintoma |
| 13 | + |
| 14 | +Los checkpoints anteriores mostraban uno o varios de estos patrones: |
| 15 | + |
| 16 | +- `eval_composite` clavado en `0.0` |
| 17 | +- head-to-head contaminado por lineas de apertura degeneradas |
| 18 | +- modelos que "se movian" pero no parecian entender el juego |
| 19 | +- mejoras marginales entre iteraciones, pero sin salto real de fuerza |
| 20 | + |
| 21 | +El punto importante es este: |
| 22 | + |
| 23 | +> El pipeline corria, pero el modelo estaba aprendiendo sobre datos de calidad |
| 24 | +> insuficiente o inconsistente. |
| 25 | +
|
| 26 | +--- |
| 27 | + |
| 28 | +## Diagnostico correcto |
| 29 | + |
| 30 | +El error operativo durante un tiempo fue leer el problema como: |
| 31 | + |
| 32 | +- "faltan mas iteraciones" |
| 33 | +- "falta otro bootstrap" |
| 34 | +- "hay que empezar de cero" |
| 35 | + |
| 36 | +Esas hipotesis eran incompletas. |
| 37 | + |
| 38 | +La causa real era acumulativa: el sistema tenia varios defectos pequenos o |
| 39 | +medianos que, juntos, degradaban justo la parte mas importante del proyecto: |
| 40 | + |
| 41 | +1. la calidad del self-play; |
| 42 | +2. la coherencia entre estado, reward e inferencia; |
| 43 | +3. la utilidad de heuristicas y checkpoints como teachers. |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +## Causas raiz |
| 48 | + |
| 49 | +### 1. Cache de inferencia de MCTS incoherente con la observacion real |
| 50 | + |
| 51 | +**Problema** |
| 52 | + |
| 53 | +La cache de inferencia de `MCTS` estaba indexada por `grid` y jugador actual, |
| 54 | +pero la red tambien veia `half_moves`. |
| 55 | + |
| 56 | +Eso permitia reutilizar policy/value entre estados distintos desde el punto de |
| 57 | +vista del modelo. |
| 58 | + |
| 59 | +**Efecto** |
| 60 | + |
| 61 | +- priors stale dentro del search |
| 62 | +- evaluacion inconsistente de estados similares pero no equivalentes |
| 63 | +- contaminacion de self-play, eval y comparacion de checkpoints |
| 64 | + |
| 65 | +**Fix** |
| 66 | + |
| 67 | +La cache se paso a construir desde la observacion real que entra a la red. |
| 68 | + |
| 69 | +--- |
| 70 | + |
| 71 | +### 2. La red no veia todo el estado que define draws por repeticion |
| 72 | + |
| 73 | +**Problema** |
| 74 | + |
| 75 | +El juego podia terminar por repeticion y el reward shaping tambien castigaba |
| 76 | +forced draws, pero esa informacion no estaba en la observacion. |
| 77 | + |
| 78 | +Habia estados con el mismo input para la red que podian diferir en: |
| 79 | + |
| 80 | +- `is_game_over()` |
| 81 | +- `is_forced_draw()` |
| 82 | + |
| 83 | +**Efecto** |
| 84 | + |
| 85 | +El target de valor no era Markoviano en la zona donde el modelo mas se atascaba: |
| 86 | +los loops. |
| 87 | + |
| 88 | +**Fix** |
| 89 | + |
| 90 | +Se agrego un canal de presion de repeticion y tambien se corrigio la |
| 91 | +serializacion para preservar `_position_counts`. |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +### 3. Las heuristicas fuertes castigaban, pero casi no enseñaban policy |
| 96 | + |
| 97 | +**Problema** |
| 98 | + |
| 99 | +En partidas contra heuristicas, el buffer guardaba sobre todo los turnos del |
| 100 | +modelo. Cuando movia el rival heuristico, su jugada normalmente no entraba como |
| 101 | +target de policy. |
| 102 | + |
| 103 | +**Efecto** |
| 104 | + |
| 105 | +`hard`, `apex`, `gambit` y `sentinel` funcionaban mas como castigo para el |
| 106 | +value head que como teacher real para la policy. |
| 107 | + |
| 108 | +**Fix** |
| 109 | + |
| 110 | +Las jugadas de heuristica pasaron a guardarse como ejemplos supervisados en el |
| 111 | +buffer. |
| 112 | + |
| 113 | +--- |
| 114 | + |
| 115 | +### 4. Training e inferencia no usaban el mismo espacio de decision |
| 116 | + |
| 117 | +**Problema** |
| 118 | + |
| 119 | +En inferencia/MCTS se aplicaba mascara legal. En training, no. |
| 120 | + |
| 121 | +La red tenia que gastar capacidad en aprender "que acciones son ilegales" en |
| 122 | +vez de concentrarse en ordenar bien las legales. |
| 123 | + |
| 124 | +**Efecto** |
| 125 | + |
| 126 | +- peor eficiencia del trunk y la policy head |
| 127 | +- mismatch entre lo que la red aprende y como se usa en runtime |
| 128 | + |
| 129 | +**Fix** |
| 130 | + |
| 131 | +Training paso a construir la legal-action mask desde el board y a usarla en el |
| 132 | +forward igual que MCTS. |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +### 5. Self-play paralelo estaba cayendo a CPU cuando mas importaba |
| 137 | + |
| 138 | +**Problema** |
| 139 | + |
| 140 | +En configuraciones cortas de Kaggle, la generacion de experiencia estaba |
| 141 | +corriendo peor de lo necesario porque los workers de self-play terminaban en CPU. |
| 142 | + |
| 143 | +**Efecto** |
| 144 | + |
| 145 | +El sistema estaba optimizando mas el fit que la calidad/cantidad de experiencia. |
| 146 | +Eso es la direccion equivocada para AlphaZero-style training. |
| 147 | + |
| 148 | +**Fix** |
| 149 | + |
| 150 | +Se cambio la politica de devices: |
| 151 | + |
| 152 | +- `CUDA x1`: sin pool paralelo, self-play secuencial en GPU |
| 153 | +- `CUDA xN`: workers repartidos por GPU |
| 154 | +- `CPU`: pool normal en CPU |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +### 6. El sampler de ejemplos recientes repetia demasiado |
| 159 | + |
| 160 | +**Problema** |
| 161 | + |
| 162 | +`sample_recent_mix()` usaba reemplazo de manera agresiva. |
| 163 | + |
| 164 | +**Efecto** |
| 165 | + |
| 166 | +Aunque el buffer fuera grande, el set efectivo de entrenamiento repetia |
| 167 | +demasiado ejemplos recientes y estrechaba la diversidad. |
| 168 | + |
| 169 | +**Fix** |
| 170 | + |
| 171 | +El sampler ahora evita reemplazo cuando puede y reparte repeticiones de manera |
| 172 | +mucho menos degenerada cuando no queda otra. |
| 173 | + |
| 174 | +--- |
| 175 | + |
| 176 | +### 7. Los oponentes checkpoint tampoco estaban enseñando policy |
| 177 | + |
| 178 | +**Problema** |
| 179 | + |
| 180 | +Cuando el rival era otro checkpoint del pool, su politica tampoco se estaba |
| 181 | +aprovechando del todo como teacher. |
| 182 | + |
| 183 | +**Efecto** |
| 184 | + |
| 185 | +La liga interna y el pool de checkpoints aportaban oposicion, pero no tanta |
| 186 | +senal de imitacion como podian. |
| 187 | + |
| 188 | +**Fix** |
| 189 | + |
| 190 | +Los turnos del checkpoint pasaron a guardarse como targets de policy y, ademas, |
| 191 | +se agrego temperatura temprana para que esas aperturas no fueran demasiado |
| 192 | +rigidas. |
| 193 | + |
| 194 | +--- |
| 195 | + |
| 196 | +### 8. La observacion era demasiado pobre para la estructura real de Ataxx |
| 197 | + |
| 198 | +**Problema** |
| 199 | + |
| 200 | +La red veia piezas, vacios, progreso y repeticion, pero seguia teniendo que |
| 201 | +inferir desde cero demasiada estructura del espacio tactico. |
| 202 | + |
| 203 | +**Efecto** |
| 204 | + |
| 205 | +Aprendizaje mas lento de: |
| 206 | + |
| 207 | +- movilidad |
| 208 | +- distincion clone/jump |
| 209 | +- actividad real de piezas |
| 210 | +- cierre y bloqueo de posiciones |
| 211 | + |
| 212 | +**Fix** |
| 213 | + |
| 214 | +La observacion se expandio a 11 canales: |
| 215 | + |
| 216 | +- piezas propias |
| 217 | +- piezas rivales |
| 218 | +- vacias |
| 219 | +- progreso de `half_moves` |
| 220 | +- presion de repeticion |
| 221 | +- destinos legales de clone propios |
| 222 | +- destinos legales de jump propios |
| 223 | +- destinos legales de clone rivales |
| 224 | +- destinos legales de jump rivales |
| 225 | +- piezas propias activas |
| 226 | +- piezas rivales activas |
| 227 | + |
| 228 | +Esto no mete libro de aperturas ni heuristicas duras. Solo le da a la red una |
| 229 | +representacion mas fiel y util del estado. |
| 230 | + |
| 231 | +--- |
| 232 | + |
| 233 | +### 9. La liga interna fallaba al guardar resultados de eval |
| 234 | + |
| 235 | +**Problema** |
| 236 | + |
| 237 | +La liga esperaba resumentes estilo duelo: |
| 238 | + |
| 239 | +- `checkpoint_a_wins` |
| 240 | +- `checkpoint_b_wins` |
| 241 | + |
| 242 | +Pero `evaluate_model()` producia: |
| 243 | + |
| 244 | +- `wins` |
| 245 | +- `losses` |
| 246 | +- `draws` |
| 247 | + |
| 248 | +**Efecto** |
| 249 | + |
| 250 | +La corrida no se caia, pero salia el warning: |
| 251 | + |
| 252 | +`league update failed, continuing training: 'checkpoint_a_wins'` |
| 253 | + |
| 254 | +**Fix** |
| 255 | + |
| 256 | +`record_checkpoint_in_league()` ahora normaliza ambos formatos de resumen antes |
| 257 | +de llamar a la liga Elo. |
| 258 | + |
| 259 | +--- |
| 260 | + |
| 261 | +## Lo que no era la causa principal |
| 262 | + |
| 263 | +### "Solo faltaban mas iteraciones" |
| 264 | + |
| 265 | +No. Varias corridas anteriores ya estaban entrenando sobre datos suboptimos o |
| 266 | +inconsistentes. Mas iteraciones sobre eso solo reforzaban una politica mediocre. |
| 267 | + |
| 268 | +### "Solo habia que cambiar bootstrap" |
| 269 | + |
| 270 | +Tampoco. El bootstrap importaba, pero no era el cuello de botella dominante. |
| 271 | +El problema principal era la calidad del loop de aprendizaje. |
| 272 | + |
| 273 | +### "Solo hacia falta otra heuristica" |
| 274 | + |
| 275 | +No por si sola. El problema era que las heuristicas no estaban dejando suficiente |
| 276 | +senal de policy en el buffer. |
| 277 | + |
| 278 | +--- |
| 279 | + |
| 280 | +## Por que `v6` si mejoro |
| 281 | + |
| 282 | +`policy_spatial_v6_iter_180` fue la primera corrida que combino suficientes fixes |
| 283 | +correctos a la vez: |
| 284 | + |
| 285 | +- observacion mas rica y coherente |
| 286 | +- search sin cache incoherente |
| 287 | +- repeticion visible para la red |
| 288 | +- heuristicas y checkpoints funcionando como teachers reales |
| 289 | +- training alineado con legal-action mask |
| 290 | +- mejor uso de GPU para generar experiencia |
| 291 | +- sampler menos degenerado |
| 292 | + |
| 293 | +El resultado ya no fue solo "se mueve distinto". Hubo mejora medible. |
| 294 | + |
| 295 | +Benchmarks locales posteriores al run: |
| 296 | + |
| 297 | +- `v6_180 vs v2_093`: `40-0` |
| 298 | +- `v6_180 vs v4_135`: `24-0` |
| 299 | +- gauntlet `v6_180`: |
| 300 | + - vs `hard`: `9-3` |
| 301 | + - vs `apex`: `4-8` |
| 302 | + - vs `sentinel`: `8-4` |
| 303 | + |
| 304 | +Y el checkpoint final quedo con: |
| 305 | + |
| 306 | +- `iteration = 180` |
| 307 | +- `best_eval_score = 0.8055555555555555` |
| 308 | + |
| 309 | +Eso ya es una mejora real, no una ilusion de logs. |
| 310 | + |
| 311 | +--- |
| 312 | + |
| 313 | +## Lecciones |
| 314 | + |
| 315 | +### 1. En AlphaZero, "que el loop corra" no significa "que el loop sirva" |
| 316 | + |
| 317 | +Un pipeline puede: |
| 318 | + |
| 319 | +- generar checkpoints |
| 320 | +- subir a HF |
| 321 | +- mostrar losses normales |
| 322 | + |
| 323 | +y aun asi estar entrenando sobre una senal mediocre. |
| 324 | + |
| 325 | +### 2. Los bugs de integracion pesan tanto como los hiperparametros |
| 326 | + |
| 327 | +En este caso, varios de los mayores bloqueos no eran: |
| 328 | + |
| 329 | +- learning rate |
| 330 | +- tamano de modelo |
| 331 | +- numero de iteraciones |
| 332 | + |
| 333 | +Eran problemas de integracion entre: |
| 334 | + |
| 335 | +- board state |
| 336 | +- observacion |
| 337 | +- MCTS |
| 338 | +- replay buffer |
| 339 | +- training loop |
| 340 | + |
| 341 | +### 3. Las heuristicas deben enseñar, no solo castigar |
| 342 | + |
| 343 | +Si el rival fuerte solo te gana pero no deja policy targets utiles, el |
| 344 | +aprendizaje de la policy avanza mucho mas lento. |
| 345 | + |
| 346 | +### 4. El modelo necesita ver estado estructural, no solo piezas |
| 347 | + |
| 348 | +Movilidad, actividad de piezas y distincion clone/jump resultaron ser features |
| 349 | +de alto valor sin romper el espiritu de self-play. |
| 350 | + |
| 351 | +--- |
| 352 | + |
| 353 | +## Estado final |
| 354 | + |
| 355 | +La conclusion operativa despues de este post-mortem es: |
| 356 | + |
| 357 | +1. el estancamiento anterior no fue un misterio ni un tema de "mala suerte"; |
| 358 | +2. habia causas tecnicas concretas y acumulativas; |
| 359 | +3. ya se corrigieron las mas importantes; |
| 360 | +4. `v6` confirma que el sistema, con esas correcciones, si puede mejorar; |
| 361 | +5. los siguientes pasos deben enfocarse en escalar bien ese progreso, no en |
| 362 | + volver a discutir eternamente bootstrap vs. reset total. |
| 363 | + |
0 commit comments