Почему существуют минимальные веса
Плохая серия наград может лишить приоритетный источник
Бандит ANDREA выбирает фокусные руки по рангу UCB1. Ранг UCB зависит от mean_reward(k), который зависит от наблюдаемых улучшений потерь. Серия документов с высокими потерями из приоритетного источника (скажем dictionary) может снизить mean_reward(k). Теперь dictionary имеет низкий ранг, получает мало фокусных выборок, & его mean_reward(k) не может восстановиться (нет выборок = нет свежих наблюдений).
Та же опасность касается любого источника, который дизайнер обучения ANDREA хочет включить в смесь независимо от краткосрочного сигнала награды.
Этажи как минимальные веса
Конфигурация обучения ANDREA указывает этаж для каждого источника: минимальный вес выборки, который источник получает независимо от того, что говорит вывод UCB. Этажи варьируются от 0.0 до 1.0. Примеры:
hermes3-general floor = 0.8 (приоритетный разговорный источник)
chat floor = 0.8
dictionary floor = 0.7 (каркас для фактического вспоминания)
gutenberg floor = 0.7 (связность прозы)
синтетический-чат floor = 0.0 (нет пола; бандит решает свободно)
Как применяются полы
После того как UCB1 ранжирует руки, а dice control собирает фокусные наборы, каждый источник получает предварительный вес. Затем запускается принудительное применение пола:
final_weight_k = max(tentative_weight_k, floor_k)
Если бандит присвоил вес 0.3 источнику hermes3-general, но его пол составляет 0.8, побеждает пол: итоговый вес = 0.8. Голос бандита переопределяется только вверх; он никогда не переопределяется вниз.
Разные конфигурации, разные уровни
ANDREA поставляется с несколькими конфигурациями обучения: chatbot, tool-caller, bash-commander. Каждая конфигурация устанавливает разные уровни для своих приоритетных источников. Конфигурация chatbot устанавливает высокие уровни для hermes3-general и chat. Tool-caller поднимает repo-docstrings выше. Bash-commander поднимает repo-commits выше. Тот же алгоритм, разные приоритеты.
Применить уровень
Риск запоминания
Маленькие источники запоминаются
Источники данных ANDREA сильно различаются по размеру. synthetic-chat содержит примерно 1400 документов. gutenberg — более 500 000. Если бандит тянет равномерно, synthetic-chat быстро исчерпает свой пул документов: после 1400 тяг каждый документ будет увиден хотя бы раз. Сделайте 2800 тяг — и каждый документ в среднем будет увиден хотя бы дважды.
Повторное воздействие небольшого набора документов приводит к запоминанию: модель перестает обучаться обобщаемым паттернам и начинает заучивать конкретные последовательности токенов из обучающих данных. Запоминание вредно по двум причинам: (1) оно тратит емкость на механическое воспроизведение вместо обобщения, и (2) оно может привести к утечке обучающих данных через генерацию.
Эпохи как прокси для запоминания
Определим эпоху над источником k как один полный проход по всем документам k:
epochs_k = floor(lifetime_pulls_k / n_docs_k)
Если synthetic-chat (n_docs=1400) был запрошен 2,800 раз, epochs = floor(2800/1400) = 2: источник был просмотрен дважды. Если gutenberg (n_docs=500,000) был запрошен 100,000 раз, epochs = floor(100000/500000) = 0: ещё не полный проход.
Штраф 1/(1+эпохи)
Когда lifetime_pulls / n_docs > 1.0, ANDREA применяет мультипликативный штраф:
penalty = 1 / (1 + epochs)
final_weight = bandit_weight * penalty
Кривая:
| эпохи | штраф | уменьшение веса |
|---|---|---|
| 0 | 1.000 | нет |
| 1 | 0.500 | половина |
| 2 | 0.333 | одна третья |
| 3 | 0.250 | одна четверть |
| 5 | 0.167 | одна шестая |
| 10 | 0.091 | одна одиннадцатая |
Штраф растёт с каждым завершённым проходом. После многих эпох вес источника приближается к нулю, и бандит естественным образом его отдыхает.
Почему Lifetime Pulls сохраняются при перезапусках
Тренировочные запуски ANDREA длятся днями. Происходят сбои. Серверы перезагружаются. Конфигурации корректируются, и обучение возобновляется с чекпоинта. Lifetime pulls сохраняются во всех этих событиях: прокси непрерывно записывает счётчики тяг на диск.
Если тяги сбрасываются при каждом перезапуске, маленький источник мог бы эффективно сбрасываться на эпоху 0 каждый раз при перезапуске обучения. Штраф никогда бы не накапливался, и запоминание продолжалось бы независимо. Сохранение lifetime pulls делает штраф реальным, монотонно растущим ограничением.
Вычислить Штраф Эпохи
Завершение Стэка Бандитского Куррикулума
Что У Вас Есть
Floors гарантируют минимальную выборку для приоритетных источников: final_weight = max(bandit_weight, floor_k). Штрафы эпох ограничивают запоминание на малых источниках: когда lifetime_pulls/n_docs > 1, вес умножается на 1/(1+epochs). Lifetime pulls сохраняются при перезапусках, так что штраф становится монотонным ограничением, а не сбрасываемым счётчиком.
Полный конвейер
Объединяем все четыре активности бандита ANDREA (76-79):
1. Активность 76 (UCB1). На каждом шаге вычисляется UCB(k) = mean_reward(k) + 0.5 * sqrt(ln(N)/n_k). Argmax выбирает рычаг.
2. Активность 77 (фазы кубика). Границы фаз (каждые 7–42 шага) бросают кубик для количества фокусных рычагов. Сначала случайные рычаги, UCB заполняет остальное. 25–33% фаз работают полностью случайно.
3. Активность 78 (приписывание вознаграждения). CUDA сообщает loss; EMA по источникам отслеживает историю; reward = max(0, EMA - loss) * 1000. Масштабированное вознаграждение подаётся в mean_reward(k).
4. Активность 79 (низы & эпохи, этот урок). После выхода UCB низы поднимают приоритетные источники; штрафы эпох снижают вес запомненных источников. Пожизненные вытягивания сохраняются.
Вместе: бандит, который адаптируется (UCB1), надежно исследует (фазы кубика), получает честные сигналы вознаграждения (масштабирование 1000x), уважает приоритеты дизайна обучения (нижние пределы) и избегает запоминания (штраф эпохи).
Справочник
Белая книга ANDREA, разделы 3.5 и 3.6.