지수 이동 평균
부드러운 최근 평균
지수 이동 평균(EMA)은 최근 샘플에 더 큰 가중치를 두고 오래된 샘플에 지수적으로 감소하는 가중치를 주어 값을 추적합니다. 공식:
EMA(t) = (1 - alpha) EMA(t-1) + alpha value(t)
알파(평활화 계수)가 (0, 1) 범위에 위치합니다. ANDREA는 소스별 손실 추적을 위해 alpha = 0.1을 사용합니다.
항별 설명
- value(t): 최신 관측값. ANDREA의 경우, 소스 k의 문서에 대한 순전파 후 CUDA가 보고한 손실입니다.
- EMA(t-1): 소스 k에 대한 이전 EMA 값. 프록시 상태에 저장됩니다.
- alpha = 0.1: 각 새로운 손실이 10% 기여; 누적 이력이 90% 기여합니다.
- (1 - alpha) = 0.9: 이력에 대한 가중치.
왜 일반 평균 대신 EMA를 사용하는가
일반적인 이동 평균은 모든 단계를 동일하게 가중합니다. 1단계와 100,000단계가 동일한 가중치를 가집니다. 데이터가 정상적(stationary)일 때 이는 작동합니다. ANDREA의 손실은 정상적이지 않습니다: 훈련 중 모델 용량이 증가하므로, 5,000단계에서의 소스 손실은 50,000단계에서의 손실과 다릅니다.
EMA는 이를 해결합니다. 오래된 손실 값은 지수적으로 사라집니다. EMA는 초기 조건 평균이 아닌 최근 현실을 반영합니다.
소스별
ANDREA는 각 팔(각 소스)당 하나의 EMA를 유지합니다. 16개의 팔 = 16개의 EMA. 각 단계에서 끌린(pulled) 소스의 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, ...): 음수 개선을 0으로 클리핑. 새로운 손실이 EMA보다 나쁘게 들어오면 보상 없음 (하지만 패널티도 없음).
3. \* 1000: UCB 탐색 보너스와 비교할 수 있도록 신호를 확대합니다.
왜 max(0, ...)인가요?
음수 보상은 mean_reward(k)를 낮추어, 손실이 위로 변동한 팔(arm)에 대한 UCB를 편향시킬 것입니다. 하지만 변동은 정상입니다: 하나의 어려운 문서가 손실을 높여도 소스가 나쁘다는 의미는 아닙니다. 0으로 클리핑하면 변동을 '벌칙'이 아닌 '정보 없음'으로 취급합니다.
소스는 반복적으로 0 보상을 받을 수 있으며, 가라앉지 않습니다. 그들의 UCB 순위는 탐색 보너스(n_k가 작을 때 높음)와 과거 승리에 의해 유지됩니다.
CUDA가 보고하는 것
각 forward+backward 패스에서 CUDA 커널은 하나의 레코드를 방출합니다:
{source: 'hermes3-general', doc_index: 4231, loss: 4.520}
프록시가 레코드를 받고, 해당 소스의 EMA를 조회하고, 보상을 계산하고, EMA를 업데이트하고, 보상을 bandit의 mean_reward(k) 누적기에 입력합니다.
보상 계산하기
탐색 보너스에 맞춘 보상
크기 문제
단계별 손실 개선은 작습니다. 손실이 4.521에서 4.520으로 떨어짐: 차이 0.001. 4.520에서 4.518으로: 차이 0.002. 전체 훈련 실행에서 원시 차이는 대략 [0, 0.01] 범위에 있습니다.
이제 C=0.5인 UCB의 탐색 보너스를 보세요. 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배 더 큽니다. UCB의 argmax는 거의 전적으로 보너스에 의해 정렬됩니다; mean_reward는 본질적으로 신호를 제공하지 않습니다.
스케일링 없이 결과: ANDREA의 bandit는 매 단계 가장 작은 n_k를 가진 팔을 선택합니다. Mean_reward는 무시됩니다. Bandit는 순수 탐색 정책이 됩니다.
해결책: 1000배
원시 보상을 1000배 곱합니다. 이제 보상이 1.0에 위치합니다 (원시 0.001 대비). 동일한 탐색 보너스 0.294와 비교:
스케일링된 보상 1.0 vs 보너스 0.294 = 보상이 3.4배 앞섬
이제 mean_reward가 UCB 순위를 지배합니다. 탐색은 꼬리(드문 팔에 0.3 부스트)에 미묘함을 더하지만, 순위의 본체는 관찰된 보상에서 나옵니다.
왜 1000인가 (& 10이 아니고, & 100,000이 아니고)
자릿수 대응. 원시 보상은 ~10^-3 정도입니다. 탐색 보너스는 ~10^0 정도입니다. 차이는 10^3입니다. 원시 보상을 10^3만큼 곱하면 보너스와 같은 범위에 도달합니다.
100배 스케일링하면 보상이 0.1에 머무릅니다 (여전히 0.294 보너스보다 작음 -> 탐색이 여전히 지배). 100,000배 스케일링하면 보상이 100으로 올라갑니다 (이제 탐색이 아무 영향도 미칠 수 없음; UCB가 greedy mean_reward로 붕괴). 1000배는 두 항목이 모두 기여하는 작동 영역에 위치합니다.
캘리브레이션, 이론이 아님
1000배 팩터는 이론적 상수가 아니라 엔지니어링 캘리브레이션입니다. 세 가지에 의존합니다: 훈련 손실 스케일 (8K 토큰 어휘에 대한 크로스-엔트로피는 약 4.5 근처), 단계당 손실 감소율 (느림), & UCB 상수 C=0.5. 이 중 하나라도 변경되면 1000이 더 이상 적절한 곱셈자가 아닐 수 있습니다.
스케일링 팩터에 대한 추론
다음 내용
당신이 배운 것
Reward attribution은 CUDA의 loss 보고를 UCB-ready 신호로 변환하는 세 가지 작업으로 이루어집니다: per-source EMA는 loss 이력을 추적(alpha=0.1, 느림), reward = max(0, EMA - loss)는 음수를 클리핑, & 1000x 스케일링은 reward 크기를 UCB exploration bonus 크기와 맞춥니다.
남은 내용
바닥(floors) 및 에포크 페널티(epoch penalties, activity 79)는 UCB 출력 위에서 작동합니다. 소스 바닥은 UCB 순위와 관계없이 우선순위 소스에 대한 최소 샘플링을 보장합니다. 에포크 페널티는 소스가 문서 수보다 더 많이 pull된 경우 해당 소스의 가중치를 낮춰 작은 데이터셋의 암기를 방지하면서 큰 데이터셋은 신선하게 유지합니다.
참고 자료
ANDREA whitepaper, 섹션 3.3.