Экспоненциальное скользящее среднее
Сглаженное недавнее среднее
Экспоненциальное скользящее среднее (EMA) отслеживает значение, отдавая больший вес недавним выборкам по сравнению со старыми, с экспоненциальным затуханием весов. Формула:
EMA(t) = (1 - alpha) EMA(t-1) + alpha value(t)
Где альфа (фактор сглаживания) находится в (0, 1). ANDREA использует alpha = 0.1 для отслеживания потерь по источникам.
По терминам
- value(t): последнее наблюдение. Для ANDREA это потеря, сообщённая CUDA после прямого прохода по документу из источника k.
- EMA(t-1): предыдущее значение EMA для источника k. Хранится в прокси-состоянии.
- alpha = 0.1: каждая новая потеря вносит 10%; накопленная история вносит 90%.
- (1 - alpha) = 0.9: вес на историю.
Почему EMA вместо простой средней
Простая скользящая средняя придает равный вес каждому шагу. Шаг 1 имеет такой же вес, как шаг 100 000. Это работает, если данные стационарны. Потери ANDREA НЕ являются стационарными: емкость модели растет во время обучения, поэтому потери источника на шаге 5 000 отличаются от его потерь на шаге 50 000.
EMA решает эту проблему. Старые значения потерь затухают экспоненциально. EMA отражает недавнюю реальность, а не усреднение начальных условий.
Per-Source
ANDREA поддерживает одну EMA на каждый рычаг (на каждый источник). Шестнадцать рычагов = шестнадцать EMA. На каждом шаге обновляется только EMA источника, который был выбран. Остальные 15 EMA остаются замороженными до следующего выбора.
Вычислите шаг EMA
Формула вознаграждения
Вознаграждение = Улучшение, масштабированное
ANDREA определяет вознаграждение на шаг для руки k как:
reward_k = max(0, EMA_k(t-1) - loss_k(t)) * 1000
Три части:
1. EMA_k(t-1) - loss_k(t): улучшение. Если новая потеря оказалась ниже скользящего среднего, разница положительная: источник k показал результат лучше ожидаемого.
2. max(0, ...): обрезка отрицательных улучшений до нуля. Если новая потеря оказалась хуже EMA, вознаграждения нет (но и штрафа тоже).
3. \* 1000: масштабируем вверх, чтобы сигнал стал сравнимым с бонусом исследования UCB.
Почему max(0, ...)
Отрицательные награды опустили бы mean_reward(k) вниз, предвзято отталкивая UCB от ручек, чьи потери колебались вверх. Но колебания нормальны: один сложный документ повышает потерю, не означая, что источник плох. Обрезка до нуля трактует колебания как «отсутствие информации», а не «штраф».
Источники могут неоднократно получать нулевую награду, не погружаясь вниз. Их ранг UCB остается определяемым бонусом исследования (высоким, когда n_k мало) плюс прошлыми успехами.
Что сообщает CUDA
Каждый проход forward+backward, ядро CUDA генерирует одну запись:
{source: 'hermes3-general', doc_index: 4231, loss: 4.520}
Прокси получает запись, ищет EMA для этого источника, вычисляет награду, обновляет EMA, передает награду в аккумулятор mean_reward(k) бандита.
Вычислить награду
Согласование награды с бонусом исследования
Проблема масштаба
Улучшения loss на шаг обычно малы. Loss падает с 4.521 до 4.520: разность 0.001. С 4.520 до 4.518: разность 0.002. За весь цикл обучения сырые разности лежат примерно в [0, 0.01].
Теперь посмотрите на бонус исследования UCB при C=0.5, с N=1000 и n_k=20:
0.5 sqrt(ln(1000) / 20) = 0.5 sqrt(6.91 / 20) = 0.5 * 0.588 = 0.294
Бонус составляет 0.294. Сырая награда составляет 0.001. Бонус в 300 раз больше награды. Argmax UCB сортирует почти исключительно по бонусу; mean_reward дает практически нулевой сигнал.
Результат без масштабирования: бандит ANDREA выбирает руку с наименьшим n_k на каждом шаге. Mean_reward игнорируется. Бандит становится чисто исследовательской политикой.
Исправление: умножение на 1000
Умножьте сырую награду на 1000. Теперь награда составляет 1.0 (против сырой 0.001). Сравните с тем же бонусом за исследование 0.294:
масштабированная награда 1.0 против бонуса 0.294 = награда лидирует с преимуществом 3.4x
Теперь средняя награда доминирует в ранжировании UCB. Исследование добавляет нюансы в хвост (редкие рычаги получают прирост 0.3), но основная часть ранжирования определяется наблюдаемой наградой.
Почему 1000 (а не 10 и не 100 000)
Согласование порядка величин. Сырые награды составляют ~10^-3. Бонус за исследование составляет ~10^0. Разрыв — 10^3. Умножьте сырую награду на 10^3, чтобы попасть в тот же диапазон, что и бонус.
Масштабирование в 100 раз оставляет награду на уровне 0.1 (всё ещё меньше бонуса 0.294 → исследование всё ещё доминирует). Масштабирование в 100 000 раз поднимает награду до 100 (теперь исследование не может ничего повлиять; UCB сводится к жадному среднему_reward). 1000x находится в рабочей зоне, где оба члена вносят вклад.
Калибровка, а не теория
Фактор 1000x — это инженерная калибровка, а не теоретическая константа. Он зависит от трёх вещей: масштаба функции потерь при обучении (кросс-энтропия на словаре из 8K токенов составляет около 4.5), скорости затухания потерь на шаг (медленная) и константы UCB C=0.5. Измените что-то из этого, и 1000 может больше не быть правильным множителем.
Размышления о масштабирующем факторе
Далее
Что у вас есть
Приписывание наград преобразует отчеты о потерях CUDA в сигнал, готовый для UCB, в трех операциях: EMA по источникам отслеживает историю потерь (alpha=0.1, медленно), reward = max(0, EMA - loss) обрезает отрицательные значения, и масштабирование 1000x соответствует величине награды величине бонуса исследования UCB.
Что осталось
Полы и штрафы эпох (активность 79) работают поверх вывода UCB. Полы источников гарантируют минимальную выборку для приоритетных источников независимо от ранга UCB. Штрафы эпох снижают вес источников, которые были выбраны больше раз, чем у них документов, предотвращая запоминание малых наборов данных, в то время как большие наборы данных остаются свежими.
Ссылка
ANDREA whitepaper, раздел 3.3.