Promedio Móvil Exponencial
Un Promedio Reciente Suavizado
Un promedio móvil exponencial (EMA) rastrea un valor ponderando más las muestras recientes que las antiguas, con pesos que decaen exponencialmente. Fórmula:
EMA(t) = (1 - alpha) EMA(t-1) + alpha value(t)
Donde alpha (el factor de suavizado) se encuentra en (0, 1). ANDREA usa alpha = 0.1 para el seguimiento de pérdida por fuente.
Término por Término
- value(t): observación más reciente. Para ANDREA, esta es la pérdida reportada por CUDA después de un pase forward en un documento de la fuente k.
- EMA(t-1): valor EMA anterior para la fuente k. Almacenado en el estado proxy.
- alpha = 0.1: cada nueva pérdida contribuye el 10%; el historial acumulado contribuye el 90%.
- (1 - alpha) = 0.9: peso en el historial.
Por qué EMA en lugar de Media Simple
Una media móvil simple pondera cada paso por igual. El paso 1 tiene el mismo peso que el paso 100,000. Eso funciona si los datos son estacionarios. Las pérdidas de ANDREA NO son estacionarias: la capacidad del modelo crece durante el entrenamiento, por lo que la pérdida de una fuente en el paso 5,000 difiere de su pérdida en el paso 50,000.
EMA resuelve esto. Los valores antiguos de pérdida se desvanecen exponencialmente. La EMA refleja la realidad reciente, no un promedio de condiciones iniciales.
Por Fuente
ANDREA mantiene una EMA por brazo (por fuente). Dieciséis brazos = dieciséis EMAs. Cada paso actualiza solo la EMA de la fuente que fue seleccionada. Las otras 15 EMAs permanecen congeladas hasta su próximo turno.
Calcula un paso de EMA
La Fórmula de Recompensa
Recompensa = Mejora, Escalada
ANDREA define la recompensa por paso para el brazo k como:
reward_k = max(0, EMA_k(t-1) - loss_k(t)) * 1000
Tres partes:
1. EMA_k(t-1) - loss_k(t): mejora. Si la nueva pérdida es inferior al promedio en ejecución, la diferencia es positiva: la fuente k desempeñó mejor de lo esperado.
2. max(0, ...): recorta las mejoras negativas a cero. Si la nueva pérdida es peor que la EMA, no hay recompensa (pero tampoco penalización).
3. \* 1000: escalar hacia arriba para hacer que la señal sea comparable al bono de exploración UCB.
Por qué max(0, ...)
Las recompensas negativas bajarían mean_reward(k), sesgando UCB contra brazos cuyas pérdidas fluctuaron hacia arriba. Pero la fluctuación es normal: un solo documento difícil eleva la pérdida sin significar que la fuente es mala. Recortar a cero trata la fluctuación como 'sin información' en lugar de 'penalización'.
Las fuentes pueden ganar recompensa cero repetidamente sin hundirse. Su rango UCB sigue impulsado por el bono de exploración (alto cuando n_k es pequeño) más victorias pasadas.
Lo que reporta CUDA
Cada pasada forward+backward, el kernel de CUDA emite un registro:
{source: 'hermes3-general', doc_index: 4231, loss: 4.520}
El proxy recibe el registro, busca el EMA para esa fuente, calcula la recompensa, actualiza el EMA, alimenta la recompensa en el acumulador mean_reward(k) del bandit.
Calcular una Recompensa
Ajustando la Recompensa al Bono de Exploración
El Problema de Magnitud
Las mejoras en loss por paso son pequeñas. Loss cae de 4.521 a 4.520: diferencia 0.001. De 4.520 a 4.518: diferencia 0.002. A lo largo de una ejecución de entrenamiento completa, las diferencias crudas viven aproximadamente en [0, 0.01].
Ahora observa el bono de exploración de UCB con C=0.5, N=1000 y n_k=20:
0.5 sqrt(ln(1000) / 20) = 0.5 sqrt(6.91 / 20) = 0.5 * 0.588 = 0.294
El bono opera a 0.294. La recompensa cruda opera a 0.001. El bono es 300x más grande que la recompensa. El argmax de UCB ordena casi enteramente por el bono; mean_reward proporciona esencialmente cero señal.
Resultado sin escalado: el bandido de ANDREA elige el brazo con el n_k más pequeño en cada paso. Mean_reward se ignora. El bandido se convierte en una política de exploración pura.
La Solución: 1000x
Multiplica la recompensa cruda por 1000. Ahora la recompensa se sitúa en 1.0 (vs cruda 0.001). Compara con el mismo bono de exploración 0.294:
recompensa escalada 1.0 vs bono 0.294 = recompensa lidera por 3.4x
Ahora mean_reward domina el ranking UCB. La exploración añade matices a la cola (brazos raros obtienen un impulso de 0.3), pero el cuerpo del ranking proviene de la recompensa observada.
Por qué 1000 (y no 10, ni 100,000)
Coincidencia de orden de magnitud. Las recompensas crudas están en ~10^-3. El bono de exploración está en ~10^0. La brecha es 10^3. Multiplica la recompensa cruda por 10^3 para aterrizar en el mismo rango que el bono.
Escalar por 100x deja la recompensa en 0.1 (aún menor que el bono de 0.294 -> la exploración aún domina). Escalar por 100,000x eleva la recompensa a 100 (ahora la exploración no puede influir en nada; UCB colapsa a la media codiciosa de recompensa). 1000x se encuentra en la zona de trabajo donde ambos términos contribuyen.
Calibración, no teoría
El factor de 1000x es una calibración de ingeniería, no una constante teórica. Depende de tres cosas: escala de pérdida de entrenamiento (entropía cruzada en un vocabulario de 8K tokens está cerca de 4.5), tasa de decaimiento de pérdida por paso (lenta) y constante UCB C=0.5. Cambia cualquiera de esas, y 1000 podría no ser ya el multiplicador correcto.
Razonamiento sobre el factor de escalado
Próximo
Lo Que Tienes
La atribución de recompensas convierte los reportes de pérdida de CUDA en una señal lista para UCB en tres operaciones: rastreadores EMA por fuente siguen el historial de pérdida (alpha=0.1, lento), reward = max(0, EMA - loss) recorta negativos, y escalado 1000x iguala la magnitud de la recompensa a la magnitud del bono de exploración UCB.
Lo que queda
Los pisos & penalizaciones de época (actividad 79) operan sobre la salida de UCB. Los pisos de origen garantizan una muestreo mínimo para orígenes prioritarios independientemente del rango UCB. Las penalizaciones de época reducen el peso de orígenes que han sido seleccionados más veces de las que tienen documentos, previniendo la memorización de conjuntos de datos pequeños mientras los conjuntos de datos grandes permanecen frescos.
Referencia
ANDREA whitepaper, sección 3.3.