18. GRPO의 변종들 — 부품을 하나씩 의심하다

(h) 학습과 생성의 불일치: 시스템이 알고리즘이 되다

여기까지는 목적함수 안의 이야기였다. 2025년 후반, 문제는 목적함수 바깥에서 터졌다.

대규모 RL은 응답 생성을 빠른 생성 엔진(vLLM, SGLang — 여러 요청을 한꺼번에 빠르게 생성하도록 만든 프로그램)에 맡기고, 그래디언트 계산은 학습 프레임워크(FSDP, Megatron — 큰 모델을 여러 GPU에 나눠 학습시키는 프로그램)가 한다. 한 스텝마다 응답 수천 개, 토큰 수백만 개의 확률을 두 프로그램이 따로 계산하는 셈이다. 생성 엔진은 뽑으면서 그 토큰의 확률을 적어 두고, 학습 엔진은 같은 토큰의 확률을 다시 계산해 비율 r\textcolor{#c2185b}{r}의 분모와 분자로 쓴다. 같은 파라미터로 같은 토큰의 확률을 두 번 계산하면, 늘 같은 값이 나올까?

같은 파라미터 θ 생성 엔진 (vLLM · SGLang) 응답을 뽑고, 그때 πrollout 을 적는다 학습 엔진 (FSDP · Megatron) 같은 토큰의 확률 πtrain 을 다시 계산 뽑힌 토큰을 넘긴다 πtrain ÷ πrollout ≠ 1 커널·연산 순서·수치 정밀도가 달라 1에서 조금씩 어긋난다

나오지 않는다. 두 엔진은 커널(GPU에서 도는 계산 코드), 연산 순서, 수치 정밀도가 달라서 같은 토큰에 조금 다른 확률을 계산한다. 그러면 “온폴리시”(지금 정책이 뽑은 샘플로 배우기) 학습이 실제로는 조용한 오프폴리시(다른 정책이 뽑은 샘플로 배우기) 학습이 된다. 다른 분포에서 뽑은 샘플로 기대값을 구하는 임포턴스 샘플링 문제가 돌아오는 것이다.

역사: 보상이 오르지 않던 학습

이 문제를 먼저 정면으로 다룬 기록은 MiniMax-M1 보고서(2025년 6월)다. 그 팀은 RL 학습 중 보상이 오르지 않는 것을 보고, 같은 토큰을 두 엔진이 계산한 확률을 점으로 찍어 견줬다. 완전히 같다면 점이 대각선 위에 놓여야 하는데 눈에 띄게 흩어져 있었다. 원인을 좇아 보니 마지막 출력층(어휘마다 점수를 내는 층)의 큰 활성값에서 생기는 정밀도 차이였다. 출력층만 FP32(32비트 실수)로 계산하게 바꾸자, 두 확률의 상관계수가 0.9대에서 0.99대로 올라 보상이 다시 자랐다.

뒤이은 연구들은 고치는 자리를 한 걸음씩 옮겨 갔다. 첫걸음은 차이를 토큰마다 보정하는 것이었다. TIS(Truncated Importance Sampling, 잘라낸 임포턴스 샘플링. Yao et al., 블로그 “Your Efficient RL Framework Secretly Brings You Off-Policy RL Training”, 2025년 8월)는 토큰마다 두 엔진 확률의 비율을 가중치로 곱하되, 너무 커지지 않게 위를 자른다.

wt=min⁡ ⁣(πtrain(ot)πrollout(ot), C)\textcolor{#c2185b}{w_t} = \min\!\Big(\frac{\textcolor{#1565c0}{\pi_\text{train}}(\textcolor{#1c9c60}{o_t})}{\textcolor{#6f6f78}{\pi_\text{rollout}}(\textcolor{#1c9c60}{o_t})},\ \textcolor{#1f6d7a}{C}\Big)
wt토큰 t의 보정 가중치πtrain학습 엔진이 계산한 확률πrollout생성 엔진이 뽑으며 적은 확률ott번째로 뽑힌 토큰C가중치의 상한 \small\begin{array}{ll} \textcolor{#c2185b}{w_t} & \text{토큰 t의 보정 가중치} \\ \textcolor{#1565c0}{\pi_\text{train}} & \text{학습 엔진이 계산한 확률} \\ \textcolor{#6f6f78}{\pi_\text{rollout}} & \text{생성 엔진이 뽑으며 적은 확률} \\ \textcolor{#1c9c60}{o_t} & \text{t번째로 뽑힌 토큰} \\ \textcolor{#1f6d7a}{C} & \text{가중치의 상한} \end{array}

다음 걸음은 응답 단위였다. 응답 하나의 비율은 토큰 비율의 곱이다. MIS(Masked Importance Sampling, 가리는 임포턴스 샘플링. Liu et al., 블로그 “When Speed Kills Stability”, 2025년 가을)와 이를 정리한 Trust Region Masking(arXiv:2512.23075, 2025년 12월)은 토큰 하나하나가 아니라 응답 전체의 비율을 보고, 크게 어긋난 응답을 통째로 버렸다(마스킹). 왜 토큰 단위로는 모자란지는 아래 문제에서 직접 셈해 본다.

버리는 것은 증상을 덮는 일이다. 셋째 걸음은 차이 자체를 줄이는 것이었다. Dr. GRPO를 낸 같은 팀의 FP16 연구(Qi et al., arXiv:2510.26788, 2025년 10월)는 근본 원인을 BF16의 짧은 가수부(유효숫자를 담는 비트, BF16은 7비트, FP16은 10비트)로 보고, 정밀도를 FP16으로 바꿔 두 엔진의 불일치를 약 24배 줄였다. MoE 모델에서는 두 엔진이 같은 토큰을 다른 전문가에게 보내는 것도 원인이었다. R3(Rollout Routing Replay, 생성 때의 라우팅을 학습 때 재생. Ma et al., arXiv:2510.11370, 2025년 10월)는 생성 엔진이 고른 라우팅을 기록해 학습에서 그대로 쓴다.

같은 무렵 Qwen 팀(Zheng et al., arXiv:2512.01374, 2025년 12월)은 이 기법들이 왜 듣는지 한 틀로 설명했다. 토큰 단위 목적함수는 응답 단위 목적의 1차 근사이고, 그 근사는 학습-생성 차이와, 샘플을 뽑은 정책이 지금 정책보다 뒤처진 정도가 둘 다 작을 때만 맞는다. 위 기법들은 모두 이 둘을 작게 유지하는 방법이다.

연구 진단 처방
MiniMax-M1 (2025년 6월) 출력층의 정밀도 차이로 두 엔진의 확률이 흩어짐 출력층을 FP32로
TIS (2025년 8월) 생성 엔진과 학습 엔진의 확률 차이 토큰 가중치 min⁡(πtrain/πrollout, C)\min(\textcolor{#1565c0}{\pi_\text{train}}/\textcolor{#6f6f78}{\pi_\text{rollout}},\, \textcolor{#1f6d7a}{C})
MIS → Trust Region Masking (2025년 가을, 12월) 토큰 단위 보정으로는 응답 단위의 어긋남을 못 잡음 비율이 크게 어긋난 응답 전체를 버림
FP16 (2025년 10월) 근본 원인은 BF16의 짧은 가수부 FP16으로 바꿔 불일치 약 24배 감소
R3 (2025년 10월) MoE 라우팅이 두 엔진에서 다름 생성 엔진의 라우팅을 기록해 학습에서 재생
Qwen 팀 (2025년 12월) 토큰 단위 목적함수는 응답 단위 목적의 1차 근사 위 기법들이 왜 듣는지에 대한 한 틀

DeepSeek-V3.2(arXiv:2512.02556, 2025년 12월)는 이 흐름을 한 번에 반영한 네 가지 수정을 발표했다.

  1. 치우침 없는 KL 추정: k3 추정량(KL을 πrefπθ−log⁡πrefπθ−1\frac{\pi_\text{ref}}{\pi_\theta} - \log\frac{\pi_\text{ref}}{\pi_\theta} - 1로 어림하는, 늘 0 이상인 값)에 비율 πθ/πold\pi_\theta/\pi_\text{old}를 곱한다. 원래 k3는 πθ≪πref\pi_\theta \ll \pi_\text{ref}일 때 과도하게 큰 가중치를 준다.
  2. 오프폴리시 시퀀스 마스킹: 어드밴티지가 음수이고 동시에 옛 정책과의 평균 로그비율이 문턱을 넘는 응답은 학습에서 뺀다. 너무 달라진 정책으로 "나쁜 답"을 억누르면 엉뚱한 방향으로 밀기 때문이다.
  3. Keep Routing: 생성 때의 MoE 라우팅을 학습에서 재사용.
  4. Keep Sampling Mask: 생성 때 top-p/top-k(확률이 높은 토큰 몇 개만 남기고 그 안에서 뽑는 설정)로 잘린 어휘 마스크를 학습 때도 적용.

셋째와 넷째는 알고리즘이라기보다 시스템의 일관성이다. 규모가 커지면 알고리즘과 시스템의 경계가 사라진다는 것이 2025년 후반의 교훈이다. 이 흐름은 2026년에도 이어지고 있다(예: 두 엔진 사이에서 한쪽으로 쌓이는 치우침을 덧셈 한 항으로 보정하는 Score Centering, arXiv:2609.20807, 2026년 9월).

문제 12 — (킬러) 1%의 차이

한 팀이 vLLM으로 응답을 생성하고 FSDP로 학습한다. 같은 파라미터인데 토큰별 로그확률이 평균 0, 표준편차 0.01 정도로 어긋난다. (가) "0.01이면 1% 차이니 무시해도 된다"는 주장을 4,000토큰 응답에 대해 검토하시오. (나) 토큰 단위로 비율을 CC에서 잘라내는 TIS만으로 충분한가? (다) 근본 해결책으로 무엇이 제안되었는가?

민준이 두 엔진의 로그확률 차이를 히스토그램으로 띄운다. 0 근처에 뾰족하게 몰려 있다.
김민준 (자신만만)
김민준
보세요, 거의 다 0이에요. 표준편차 0.01이면 비율로 치면 1% 차이인데, 이 정도는 무시해도 되죠.
선생님 (질문)
선생님
서연 학생, 4,000토큰짜리 응답 하나의 비율은 어떻게 계산하죠?
이서연 (평상)
이서연
토큰 비율의 곱이니까 로그비율의 합이요. 토큰마다 독립이라고 치면 합의 표준편차는 0.01 × √4000 ≈ 0.63이에요.
이서연 (놀람)
이서연
e0.63e^{0.63}이면 1.9배. 2σ면 e1.26≈3.5e^{1.26} \approx 3.5배예요. 토큰 하나는 1%인데 응답 하나는 몇 배씩 어긋나는 거네요.
선생님 (짚어주기)
선생님
방금 "독립이라고 치면"이라고 했죠. 어긋남이 늘 같은 쪽이라면요? 토큰마다 +0.01씩.
이서연 (평상)
이서연
그럼 합이 0.01 × 4000 = 40이에요. e40≈2.4×1017e^{40} \approx 2.4 \times 10^{17}배.
이서연 (놀람)
이서연
√n이 아니라 n으로 자라네요.
선생님 (평상)
선생님
그래요. 2026년에 나온 Score Centering 연구는 무작위 흔들림보다 이렇게 두 엔진 사이에서 한쪽으로 쌓이는 치우침이 불안정의 주범이라고 봤어요.
김민준 (당황)
김민준
그럼 토큰마다 C에서 잘라내면요? TIS처럼요. 토큰 비율은 1% 근처라 거의 안 잘리겠지만, 잘못된 건 없잖아요.
이서연 (평상)
이서연
바로 그게 문제 아냐? 토큰 하나하나는 범위 안이라 안 잘리는데, 곱해지면 몇 배가 되는 거. 토큰 단위 보정으로는 응답 단위로 쌓인 차이를 못 본다고.
선생님 (평상)
선생님
그래요. 그래서 MIS와 Trust Region Masking은 응답 전체를 보고 크게 어긋난 응답을 통째로 버렸어요. 그리고 드물게, 생성 엔진이 뽑은 낮은 확률 토큰에서 두 엔진이 크게 어긋나는 경우도 있어요. 평균이 아니라 꼬리가 사고를 치죠.
김민준 (평상)
김민준
(다)는… 그럼 애초에 차이를 안 만드는 게 답이겠네요. 정밀도를 맞추거나.
선생님 (평상)
선생님
맞아요. FP16 연구는 BF16의 짧은 가수부가 근본 원인이라 보고, FP16으로 바꿔서 불일치를 약 24배 줄였어요. MoE라면 라우팅까지 맞춰야 하고요(R3, Keep Routing).
이서연 (평상)
이서연
수치해석 시간에 반올림 오차가 한 번은 작아도 수천 번 누적되면 결과가 망가진다고 배웠는데, 이게 딱 그거네요. 무작위면 √n으로 자라는 랜덤워크, 한쪽으로 치우치면 n으로 자라고.
김민준 (평상)
김민준
실험 보고서에서 유효숫자 하나 아끼다가 마지막 계산에서 틀린 적 있어요. 조교님이 중간값은 넉넉하게 들고 가라고 했는데.

정리 (가) 로그비율의 합은 표준편차가 0.014000≈0.630.01\sqrt{4000} \approx 0.63 — 응답 단위 비율은 흔히 e±0.63≈e^{\pm 0.63} \approx 0.5–1.9배, 2σ면 3.5배까지 어긋난다. 어긋남이 한쪽으로 치우쳐 있으면 합이 0.01×4000=400.01 \times 4000 = 40으로 nn에 비례해 자란다. 토큰 하나의 1%는 무시할 수 없다. (나) 토큰 단위 잘라내기는 개별 토큰이 범위 안이면 아무것도 못 한다. 응답 단위 마스킹(MIS, Trust Region Masking)이 필요하다. (다) 차이 자체를 줄이는 것: FP16 정밀도, MoE 라우팅 재생(R3, Keep Routing), 샘플링 마스크 일치.