넓히기와 좁히기

GRPO의 KL 항: 값과 그래디언트가 다른 KL을 가리킨다

“식에 KL(π‖πref) 라고 적어 두면, 학습은 정말 그 KL을 줄이는가?”

KL의 방향 절에서, 방향이 결과를 바꿀 수 있음을 보았다. 모델 족이 목표를 다 담지 못할 때, KL(목표‖π) 는 봉우리들 사이에 넓게 걸치고 KL(π‖목표) 는 한쪽 봉우리를 고른다. 그렇다면 실제 구현이 어느 방향의 KL을 줄이고 있는지가 중요해지는데, 그 방향은 식에 적힌 것과 다를 수 있다.

GRPO에서의 실현

DeepSeekMath(Shao 외 2024)가 제안한 GRPO(한 문제에 답을 여러 개 뽑아 서로 비교해 보상을 매기는 강화학습)는 보상에 KL을 섞지 않고 손실에 KL 항을 직접 더한다. 샘플 하나로 KL(π‖πref) 를 추정하는 데는 슐먼(John Schulman)이 2020년 블로그 글 「KL 발산 근사하기(Approximating KL Divergence)」에서 정리한 추정량을 쓴다.

샘플 하나로 KL 을 추정하기

답변의 가짓수가 너무 많으면 KL 을 모든 답변에 걸쳐 더해 계산할 수 없으므로, 정책에서 답변을 몇 개 뽑아 추정해야 한다. 슐먼의 글은 그 추정식을 차례로 고치는데, 아래에서는 ρ(로) = πref(y)/π(y) 라 쓴다. 첫째 식 −log ρ 는 평균이 KL 과 정확히 같지만, 샘플의 절반쯤에서 음수가 나와 분산이 크다. KL 은 늘 0 이상인데 샘플 하나하나는 그렇지 않은 것이다. 둘째 식 ½(log ρ)² 는 늘 0 이상이고 분산도 작지만, 평균이 KL 과 조금 다르다(편향이 있다). 셋째 식은 첫째 식에 평균이 0 인 양 ρ − 1 을 더해 분산을 줄인 것인데, log x ≤ x − 1 이므로 더한 결과는 늘 0 이상이다. 글은 세 추정량을 k1, k2, k3 이라 불렀으므로, k3 은 k 곱하기 3 이 아니라 「셋째 추정량」이라는 이름이다.

k3(y)=πref(y)π(y)−log⁡πref(y)π(y)−1Ey∼π[k3]=KL(π ∥ πref)\begin{gathered} \textcolor{#c078a0}{k_3}(\textcolor{#506890}{y}) = \frac{\textcolor{#139696}{\pi_{\mathrm{ref}}}(\textcolor{#506890}{y})}{\textcolor{#7f8f10}{\pi}(\textcolor{#506890}{y})} - \log\frac{\textcolor{#139696}{\pi_{\mathrm{ref}}}(\textcolor{#506890}{y})}{\textcolor{#7f8f10}{\pi}(\textcolor{#506890}{y})} - 1 \\ \mathbb{E}_{\textcolor{#506890}{y}\sim\textcolor{#7f8f10}{\pi}}[\textcolor{#c078a0}{k_3}] = \textcolor{#c2398a}{\mathrm{KL}}(\textcolor{#7f8f10}{\pi}\,\|\,\textcolor{#139696}{\pi_{\mathrm{ref}}}) \end{gathered}
k3샘플 하나로 만든 KL 추정량 (항상 0 이상)π학습하는 정책πref참조 정책KLKL 발산y정책에서 뽑은 답변\begin{array}{ll} \textcolor{#c078a0}{k_3} & \text{샘플 하나로 만든 KL 추정량 (항상 0 이상)} \\ \textcolor{#7f8f10}{\pi} & \text{학습하는 정책} \\ \textcolor{#139696}{\pi_{\mathrm{ref}}} & \text{참조 정책} \\ \textcolor{#c2398a}{\mathrm{KL}} & \text{KL 발산} \\ \textcolor{#506890}{y} & \text{정책에서 뽑은 답변} \end{array}
가로축은 ρ = π_ref(y)/π(y), 세로축은 샘플 하나로 낸 추정값이다. k1 = −log ρ 는 ρ 가 1 보다 크면 음수가 되고, k2 = ½(log ρ)² 와 k3 = ρ − 1 − log ρ 는 늘 0 이상이다. 세 식 모두 ρ = 1(두 정책이 그 답변에 같은 확률을 줌)에서 0 이다
가로축은 ρ = π_ref(y)/π(y), 세로축은 샘플 하나로 낸 추정값이다. k1 = −log ρ 는 ρ 가 1 보다 크면 음수가 되고, k2 = ½(log ρ)² 와 k3 = ρ − 1 − log ρ 는 늘 0 이상이다. 세 식 모두 ρ = 1(두 정책이 그 답변에 같은 확률을 줌)에서 0 이다

값으로서는 흠이 없어서, π 에서 뽑은 샘플로 평균 내면 정확히 KL(π‖πref) 다. 문제는 k3 을 손실로 두고 미분할 때 생긴다. 샘플을 뽑은 분포는 미분하지 않고(샘플은 이미 뽑혔으니까) k3 만 미분하면, ρ = πref/π 라 할 때 ∇k3 = (1 − ρ)∇log π 이고, 그 기댓값은

Ey∼π[(1−ρ) ∇log⁡π(y)]=−∑yπref(y) ∇log⁡π(y)=∇ KL(πref ∥ π)\begin{aligned} &\mathbb{E}_{\textcolor{#506890}{y}\sim\textcolor{#7f8f10}{\pi}}\big[(1-\textcolor{#7888e8}{\rho})\,\nabla\log\textcolor{#7f8f10}{\pi}(\textcolor{#506890}{y})\big] \\ &= -\sum_y \textcolor{#139696}{\pi_{\mathrm{ref}}}(\textcolor{#506890}{y})\,\nabla\log\textcolor{#7f8f10}{\pi}(\textcolor{#506890}{y}) \\ &= \nabla\,\textcolor{#c2398a}{\mathrm{KL}}(\textcolor{#139696}{\pi_{\mathrm{ref}}}\,\|\,\textcolor{#7f8f10}{\pi}) \end{aligned}
ρπref(y)/π(y)∇정책 파라미터에 대한 그래디언트π학습하는 정책 (샘플도 여기서 뽑음)πref참조 정책KLKL 발산\begin{array}{ll} \textcolor{#7888e8}{\rho} & \textcolor{#139696}{\pi_{\mathrm{ref}}}(\textcolor{#506890}{y})/\textcolor{#7f8f10}{\pi}(\textcolor{#506890}{y}) \\ \nabla & \text{정책 파라미터에 대한 그래디언트} \\ \textcolor{#7f8f10}{\pi} & \text{학습하는 정책 (샘플도 여기서 뽑음)} \\ \textcolor{#139696}{\pi_{\mathrm{ref}}} & \text{참조 정책} \\ \textcolor{#c2398a}{\mathrm{KL}} & \text{KL 발산} \end{array}

첫 등호는 Eπ[∇log π] = Σ ∇π = 0 을 쓴 것이다. 값은 KL(π‖πref) 를 재면서, 그래디언트는 KL(πref‖π) 를 줄이는 방향을 가리킨다. Tang과 Munos(2025)가 이 함정을 정리했다. “KL 추정값을 손실로 두고 미분하면 대개 KL의 올바른 그래디언트가 나오지 않는다.” 그러면 어떤 손실을 써야 올바른 그래디언트가 나오는지, 그리고 실제 GRPO처럼 샘플을 한 스텝 전의 정책 πold 에서 뽑으면 무엇이 더 달라지는지(Zhang 외 2025)는 아래 문제에서 따진다.

값과 그래디언트가 서로 다른 KL을 가리킨다는 차이가 작아 보이지만, 우리 교재의 언어로는 사영 방향의 차이다. 식에 적힌 것은 π 쪽에 무게를 둔 KL, 실제로 미는 방향은 참조 쪽에 무게를 둔 KL.

한 가지 덧붙이면, 2025년의 RLVR 연구 여럿은 이 KL 항을 아예 뺀다. KL 벌칙은 원래 RLHF에서 온 것인데, 거기서는 보상 모델이 참조 모델 근처의 답들로 학습되어 그 근처에서만 믿을 만하니 정책을 참조에서 멀리 가지 못하게 묶어 둘 필요가 있었다. DAPO(Yu 외 2025)는 기본 GRPO가 학습 중에 엔트로피가 무너지는 것 같은 문제를 보인다며 손질 몇 가지를 내놓았고, KL 항을 빼는 것도 그 하나였다. 긴 추론을 학습하는 동안에는 모델이 초기 모델에서 크게 벗어나는 것이 자연스러우니 이 제약이 필요 없다는 것이 그 근거였다. Dr. GRPO(Liu 외 2025)는 GRPO가 답의 길이와 보상의 표준편차로 나누면서 생기는 편향(틀린 답이 갈수록 길어지는 것)을 고친 방법인데, 규칙 기반 검증기는 보상 모델처럼 참조 근처에서만 믿을 만한 것이 아니라며 β = 0 으로 두었다. 그러면 기울이기 절의 닫힌꼴 π* ∝ πref·er/β 은 β → 0 극한, 정답 집합으로의 조건부화 쪽으로 간다.

파이썬

세 답변 위의 소프트맥스 정책으로 k3 손실의 그래디언트 기댓값을 직접 계산한다.

import numpy as np

def softmax(z): e = np.exp(z - z.max()); return e / e.sum()
theta = np.array([1.0, 0.0, -0.5])               # 정책 로짓
ref = np.array([0.2, 0.5, 0.3])                  # 참조 정책
pi = softmax(theta)
J = np.eye(3) - pi[None, :]                      # J[y] = ∇ log π(y)  (로짓에 대한 그래디언트)
rho = ref / pi

print("E[k3]        ", np.sum(pi * (rho - np.log(rho) - 1)).round(4),
      " KL(π‖ref)", np.sum(pi * np.log(pi / ref)).round(4))
print("k3 손실 그래디언트", ((pi * (1 - rho)) @ J).round(4))
print("∇KL(ref‖π)    ", (-(ref @ J)).round(4))
print("∇KL(π‖ref)    ", ((pi * np.log(pi / ref)) @ J).round(4))
# E[k3]         0.4347  KL(π‖ref) 0.4347
# k3 손실 그래디언트 [ 0.4285 -0.2688 -0.1598]
# ∇KL(ref‖π)     [ 0.4285 -0.2688 -0.1598]
# ∇KL(π‖ref)     [ 0.4465 -0.2788 -0.1676]

값은 KL(π‖πref) 와 같고, 그래디언트는 KL(πref‖π) 의 것과 같다.

이 절의 결론

“추정량의 값과 그래디언트는 서로 다른 KL을 가리킬 수 있다. GRPO의 k3 항은 값으로는 KL(π‖πref) 를 재지만, 손실로 미분하면 KL(πref‖π) 를 줄이는 방향을 가리킨다.”

문제 9. 값이 편향된 추정량의 그래디언트 (킬러)

정책 π = softmax(θ), θ = (0, 1, 0.5), 참조 πref = (0.5, 0.3, 0.2), ρ = πref(y)/π(y) 이다. (가) Ey∼π[k3] 가 KL(π‖πref) 와 같음을 보이고, 숫자로 확인하라. 둘째 추정량 ½(log ρ)² 의 기댓값도 구해 비교하라. (나) 샘플을 고정하고 ½(log ρ)² 를 손실로 두어 θ 로 미분하면, 그 그래디언트의 기댓값은 어느 KL의 그래디언트인가? k3 의 경우와 비교하라. (다) 샘플을 π 가 아닌 πold = softmax(0.5, 0.5, 0) 에서 뽑으면 k3 그래디언트의 기댓값은 어떻게 되는가?

세 답에 정책 π = softmax(0, 1, 0.5), 참조 π_ref, 샘플을 뽑는 이전 정책 π_old = softmax(0.5, 0.5, 0) 이 준 확률
세 답에 정책 π = softmax(0, 1, 0.5), 참조 π_ref, 샘플을 뽑는 이전 정책 π_old = softmax(0.5, 0.5, 0) 이 준 확률

함께 풀기

김민준 M01
김민준

(가)는 바로 나와요. Eπ[ρ] = Σ πref = 1 이니까 1 − Eπ[log ρ] − 1 = Eπ[log π/πref]. 숫자로도 둘 다 0.2132 요. ½(log ρ)² 의 기댓값은 0.1885 라서 KL 보다 작아요. 편향된 추정량이 맞네요.

김민준 M01
김민준

그럼 (나)는 볼 것도 없죠. 기댓값부터 KL이 아닌데, 그걸 미분한 게 KL의 그래디언트일 리가 없어요. 값이 정확한 k3 도 그래디언트는 KL(πref‖π) 쪽이었잖아요. 값이 틀린 쪽은 더 엉뚱할 거예요.

선생님 T01
선생님

값이 맞는 것과 그래디언트가 맞는 것이 같은 일인지부터 봐요. k3 에서는 둘이 왜 갈렸죠?

김민준 M05
김민준

기댓값은 π 로 냈는데 π 는 θ 에 의존하고… 코드에서는 샘플을 먼저 뽑고 손실만 미분해요. 샘플을 뽑은 분포는 미분 안 하고요. 그러면 값이 맞는지와 그래디언트가 맞는지는 따로 봐야 하는 거네요.

이서연 S01
이서연

그럼 직접 해 보자. ∇½(log ρ)² = log ρ·∇log ρ 이고, ∇log ρ = ∇log π 니까 log ρ·∇log π. 부호는 이게 맞나?

선생님 T01
선생님

한 단계씩 다시 써 봐요.

이서연 S04
이서연

log ρ = log πref − log π 이고 πref 는 θ 와 무관하니까 ∇log ρ = −∇log π 예요. 그러면 ∇½(log ρ)² = −log ρ·∇log π = log(π/πref)·∇log π. 제가 부호를 뒤집었네요.

이서연 S01
이서연

이제 π 로 평균 내면 Σ π log(π/πref)∇log π. KL(π‖πref) = Σ π log(π/πref) 를 미분하면 이 항에, Σ π∇log(π/πref) = Σ ∇π = 0 이 더해질 뿐이에요.

이서연 S08
이서연

KL(π‖πref) 의 그래디언트예요. 값은 편향돼 있는데, 그래디언트는 식에 적은 바로 그 KL을 줄여요. k3 하고 거꾸로네요.

김민준 M01
김민준

숫자로 확인했어요. ½(log ρ)² 손실의 그래디언트가 (−0.2236, 0.1573, 0.0664) 로 ∇KL(π‖πref) 와 똑같아요. k3 쪽은 (−0.3137, 0.2065, 0.1072) 로 ∇KL(πref‖π) 와 같고요. 방향은 비슷한데 크기가 꽤 달라요.

선생님 T01
선생님

방향이 비슷한 이유는요?

이서연 S01
이서연

두 분포가 가까우면 두 KL 모두 ½ dθᵀI dθ(I 는 피셔 정보 행렬, 파라미터에 대한 스코어의 공분산)로 가니까요. 가까운 곳에서는 KL이 대칭이 돼요. 멀어질수록 차이가 커져요.

김민준 M01
김민준

그럼 (다)는 제가 해 볼게요. 실제 GRPO는 이전 정책 πold 에서 뽑잖아요. πold = softmax(0.5, 0.5, 0) 으로 하면 k3 그래디언트의 기댓값이 (−0.5698, 0.3632, 0.2066) 으로, 두 KL의 그래디언트 어느 쪽과도 달라요.

이서연 S01
이서연

Eπold[∇log π] 가 이제 0이 아니니까요. 위에서 쓴 「Eπ[∇log π] = 0」이 무너져요. π/πold 중요도 가중치를 곱해 주면 (−0.3137, 0.2065, 0.1072) 로 돌아가요.

선생님 T13
선생님

둘 다 잘 왔어요. 이 문제에서 가져갈 건 세 가지예요. 추정량에 편향이 없다(불편, unbiased)는 것은 값에 대한 말이지 그래디언트에 대한 말이 아니고, 거꾸로 값이 편향된 추정량이 올바른 그래디언트를 줄 수도 있다. 샘플을 뽑은 분포도 θ 에 의존한다는 걸 잊으면 KL의 방향이 바뀐다. 그리고 샘플이 다른 정책에서 왔으면 중요도 가중치로 다시 맞춰야 한다.

김민준 M01
김민준

보고서 분량을 "평균 10쪽"으로 맞춰 놓고, 채점은 가장 짧은 보고서 기준으로 하는 거랑 비슷하네요. 평균은 맞는데 미는 방향이 다른 거.

이서연 S01
이서연

수학 수업에서 "적분 기호 안으로 미분을 넣으려면 적분 영역이 변수에 의존하지 않아야 한다"고 했던 것과 같아요. 여기서는 적분의 무게 π 가 θ 에 의존하는데 그걸 빼고 미분한 거예요.