Moyenne mobile exponentielle
Une moyenne lissée récente
Une moyenne mobile exponentielle (EMA) suit une valeur en pondérant les échantillons récents plus que les anciens, avec des poids décroissant exponentiellement. Formule :
EMA(t) = (1 - alpha) EMA(t-1) + alpha value(t)
Où alpha (le facteur de lissage) se situe dans (0, 1). ANDREA utilise alpha = 0.1 pour le suivi de la perte par source.
Terme par terme
- value(t) : dernière observation. Pour ANDREA, il s'agit de la perte rapportée par CUDA après un passage avant sur un document de la source k.
- EMA(t-1) : valeur EMA précédente pour la source k. Stockée dans l'état proxy.
- alpha = 0.1 : chaque nouvelle perte contribue à 10 % ; l'historique roulant contribue à 90 %.
- (1 - alpha) = 0.9 : poids sur l'historique.
Pourquoi EMA au lieu de la moyenne simple
Une moyenne mobile simple pondère chaque étape de manière égale. L'étape 1 a le même poids que l'étape 100 000. Cela fonctionne si les données sont stationnaires. Les pertes d'ANDREA ne sont PAS stationnaires : la capacité du modèle augmente pendant l'entraînement, donc la perte d'une source à l'étape 5 000 diffère de sa perte à l'étape 50 000.
EMA résout cela. Les anciennes valeurs de perte s'estompent de manière exponentielle. L'EMA reflète la réalité récente, pas une moyenne des conditions initiales.
Par source
ANDREA maintient une EMA par bras (par source). Seize bras = seize EMAs. À chaque étape, seule l'EMA de la source tirée est mise à jour. Les autres 15 EMAs restent figées jusqu'à leur prochain tirage.
Calculer une étape EMA
La Formule de Récompense
Récompense = Amélioration, Échelonnée
ANDREA définit la récompense par étape pour le bras k comme suit :
reward_k = max(0, EMA_k(t-1) - loss_k(t)) * 1000
Trois parties :
1. EMA_k(t-1) - loss_k(t) : amélioration. Si la nouvelle perte est inférieure à la moyenne glissante, la différence est positive : la source k a performé mieux que prévu.
2. max(0, ...) : clippe les améliorations négatives à zéro. Si la nouvelle perte est pire que l'EMA, pas de récompense (mais pas de pénalité non plus).
3. \* 1000 : augmenter l'échelle pour rendre le signal comparable au bonus d'exploration UCB.
Pourquoi max(0, ...)
Des récompenses négatives abaisseraient mean_reward(k), biaisant UCB contre les bras dont les pertes fluctuent vers le haut. Mais la fluctuation est normale : un seul document difficile augmente la perte sans signifier que la source est mauvaise. Clipper à zéro traite la fluctuation comme « aucune information » plutôt que « pénalité ».
Les sources peuvent accumuler des récompenses nulles à répétition sans couler. Leur rang UCB reste déterminé par le bonus d'exploration (élevé quand n_k est petit) plus les victoires passées.
Ce que CUDA rapporte
À chaque passage avant+arrière, le noyau CUDA émet un enregistrement :
{source: 'hermes3-general', doc_index: 4231, loss: 4.520}
Le proxy reçoit l'enregistrement, recherche l'EMA pour cette source, calcule la récompense, met à jour l'EMA, alimente la récompense dans l'accumulateur mean_reward(k) du bandit.
Calculer une récompense
Adapter la Récompense au Bonus d'Exploration
Le Problème d'Amplitude
Les améliorations de loss par étape sont petites. Loss passe de 4.521 à 4.520 : différence 0.001. De 4.520 à 4.518 : différence 0.002. Sur une exécution d'entraînement entière, les différences brutes se situent grosso modo dans [0, 0.01].
Regardez maintenant le bonus d'exploration de UCB avec C=0.5, N=1000 et n_k=20 :
0.5 sqrt(ln(1000) / 20) = 0.5 sqrt(6.91 / 20) = 0.5 * 0.588 = 0.294
Le bonus s'élève à 0.294. La récompense brute s'élève à 0.001. Le bonus est 300x plus grand que la récompense. L'argmax de UCB trie presque entièrement par le bonus ; mean_reward fournit essentiellement zéro signal.
Résultat sans mise à l'échelle : le bandit d'ANDREA choisit le bras avec le plus petit n_k à chaque étape. Mean_reward est ignoré. Le bandit devient une politique d'exploration pure.
La Solution : 1000x
Multipliez la récompense brute par 1000. Maintenant, la récompense est à 1.0 (contre 0.001 brute). Comparez avec le même bonus d'exploration 0.294 :
récompense mise à l'échelle 1.0 vs bonus 0.294 = récompense domine par 3.4x
Maintenant, mean_reward domine le classement UCB. L'exploration ajoute de la nuance à la queue (les bras rares obtiennent un boost de 0.3), mais le corps du classement provient de la récompense observée.
Pourquoi 1000 (et pas 10, ni 100 000)
Correspondance d'ordre de grandeur. Les récompenses brutes sont ~10^-3. Le bonus d'exploration est ~10^0. L'écart est 10^3. Multipliez la récompense brute par 10^3 pour arriver dans la même plage que le bonus.
Un scaling par 100x laisse la récompense à 0,1 (toujours inférieure au bonus de 0,294 -> l'exploration domine encore). Un scaling par 100 000x porte la récompense à 100 (maintenant l'exploration ne peut rien influencer ; UCB se réduit à la moyenne gloutonne mean_reward). 1000x se situe dans la zone de fonctionnement où les deux termes contribuent.
Calibration, pas théorie
Le facteur 1000x est une calibration d'ingénierie, pas une constante théorique. Il dépend de trois choses : l'échelle de la perte d'entraînement (entropie croisée sur un vocabulaire de 8K tokens autour de 4,5), le taux de décroissance de la perte par étape (lent), & la constante UCB C=0,5. Changez l'un d'eux, & 1000 ne sera peut-être plus le bon multiplicateur.
Raisonner sur le facteur d'échelle
À Venir Prochainement
Ce Que Vous Avez
L'attribution de récompense convertit les rapports de perte de CUDA en signal prêt pour UCB en trois opérations : les EMA par source suivent l'historique des pertes (alpha=0.1, lent), reward = max(0, EMA - loss) clippe les négatifs, & mise à l'échelle 1000x fait correspondre la magnitude de la récompense à la magnitude du bonus d'exploration UCB.
Ce qui reste
Les planchers & pénalités d'époque (activité 79) fonctionnent au-dessus de la sortie UCB. Les planchers sources garantissent un échantillonnage minimum pour les sources prioritaires indépendamment du rang UCB. Les pénalités d'époque réduisent le poids des sources qui ont été tirées plus de fois qu'elles n'ont de documents, empêchant la mémorisation des petits ensembles de données tout en gardant les grands ensembles de données frais.
Référence
ANDREA whitepaper, section 3.3.