수학

MATH / 중급 55번

선호 쌍에서 보상 모델 손실 유도하기

보상 모델 학습 코드의 손실은 −logsigmoid(r_w − r_l) 한 줄입니다. 「A가 B보다 낫다」는 라벨만으로 실수 점수를 배우는 그 식이 Bradley-Terry 모델에 최대가능도를 적용한 결과임을 유도하고, 보상의 절대값에 왜 의미가 없는지, 비교 n개로 재는 점수차의 오차가 얼마인지를 계산합니다.

PALDYN Team19 MIN READ

보상 모델을 학습하는 코드는 짧습니다.

r_w = reward_model(prompt, chosen).squeeze(-1)     # 사람이 고른 답
r_l = reward_model(prompt, rejected).squeeze(-1)   # 고르지 않은 답
loss = -F.logsigmoid(r_w - r_l).mean()

라벨로 가진 것은 「이 둘 중에서는 왼쪽이 낫다」뿐입니다. 첫 번째 답이 7.2점이라거나 두 번째가 3.1점이라는 정보는 어디에도 없습니다. 그런데 학습이 끝나면 모델은 답 하나를 받아 실수 하나를 내놓습니다. 순서만 알려 주었는데 어떻게 눈금이 생길까요.

지난 글까지 우리는 점수 rr 이 이미 있다고 두고 그것으로 정책을 학습하는 쪽을 봤습니다. 이 글은 그 rr 이 어디서 오는지를 봅니다 — 그리고 저 한 줄이 유도의 결과라는 것을 확인합니다. 손실이 왜 로그 시그모이드인지, 왜 두 점수를 각각이 아니라 차이로만 쓰는지가 같은 유도에서 함께 나옵니다.

순서를 확률로 바꾸는 모델

시작은 가정 하나입니다. 답 하나마다 눈에 보이지 않는 실수 강도 rr 이 있고, 사람이 둘을 비교할 때 강도의 차이가 클수록 더 자주 그쪽을 고른다고 둡니다. 이것을 확률로 적는 가장 단순한 방법이 두 값에 소프트맥스를 씌우는 것입니다.

P(A≻B)=erAerA+erBP(A \succ B) = \frac{e^{r_A}}{e^{r_A} + e^{r_B}}

분자와 분모를 erAe^{r_A} 로 나누면 익숙한 꼴이 됩니다.

P(A≻B)=11+e−(rA−rB)=σ(rA−rB)P(A \succ B) = \frac{1}{1 + e^{-(r_A - r_B)}} = \sigma(r_A - r_B)

σ\sigma 는 시그모이드 함수이고, 여기가 코드의 logsigmoid가 나온 자리입니다. 이 모델을 Bradley-Terry 모델이라 부릅니다 — 1952년에 쌍 비교 실험을 다루려고 나온 통계 모형이고, 항목마다 강도 하나를 두고 비교 결과를 그 차이의 시그모이드로 설명합니다.

강도의 차이가 선택 확률을 정한다

읽어 두면 좋은 값이 몇 개 있습니다. 차이가 0이면 확률은 정확히 0.5입니다 — 우열이 없으면 반반입니다. 차이가 1이면 0.731, 2면 0.881, 3이면 0.953입니다. 그러니까 점수차 1은 「열 번 중 일곱 번쯤 이긴다」는 뜻입니다. 이 대응이 나중에 보상 모델의 출력을 읽을 때 눈금이 됩니다.

여기서 이미 보이는 것이 있습니다. 오른쪽 식에 rAr_A 와 rBr_B 가 차이로만 들어갑니다. 이 성질은 아래에서 다시 붙잡습니다.

최대가능도를 적용한다

이제 데이터가 붙습니다. 비교 결과 nn 개가 있고, ii 번째에서 사람이 yw(i)y_w^{(i)} 를 골랐고 yl(i)y_l^{(i)} 를 버렸다고 합시다. 모델의 파라미터 ϕ\phi 는 답을 받아 점수를 내는 함수 rϕr_\phi 를 정합니다.

최대가능도의 절차는 늘 같습니다 — 데이터가 나올 확률을 파라미터의 함수로 적고, 그것을 가장 크게 만드는 파라미터를 고릅니다. 비교들이 서로 독립이라고 두면 가능도는 곱입니다.

L(ϕ)=∏i=1nP(yw(i)≻yl(i))=∏i=1nσ(rϕ(yw(i))−rϕ(yl(i)))\mathcal{L}(\phi) = \prod_{i=1}^{n} P\big(y_w^{(i)} \succ y_l^{(i)}\big) = \prod_{i=1}^{n} \sigma\big(r_\phi(y_w^{(i)}) - r_\phi(y_l^{(i)})\big)

곱은 다루기 어려우니 로그를 취해 합으로 바꾸고, 최대화 대신 최소화하려고 부호를 뒤집습니다.

LRM(ϕ)=−1n∑i=1nlog⁡σ(rϕ(yw(i))−rϕ(yl(i)))=− E(x, yw, yl)∼D[log⁡σ(rϕ(x,yw)−rϕ(x,yl))]\begin{aligned} \mathcal{L}_{\text{RM}}(\phi) &= -\frac{1}{n}\sum_{i=1}^{n} \log \sigma\big(r_\phi(y_w^{(i)}) - r_\phi(y_l^{(i)})\big) \\ &= -\,\mathbb{E}_{(x,\,y_w,\,y_l)\sim\mathcal{D}}\Big[\log \sigma\big(r_\phi(x,y_w) - r_\phi(x,y_l)\big)\Big] \end{aligned}

맨 앞 코드의 세 번째 줄이 이 식입니다. 유도에서 새로 들어온 것은 없습니다 — Bradley-Terry 모델 하나와 최대가능도 하나뿐입니다.

손실의 모양도 유도에서 따라옵니다. Δ=rw−rl\Delta = r_w - r_l 로 두면 손실은 −log⁡σ(Δ)-\log\sigma(\Delta) 이고, 미분하면 이렇습니다.

ddΔ[−log⁡σ(Δ)]=−(1−σ(Δ))=−σ(−Δ)\frac{d}{d\Delta}\big[-\log\sigma(\Delta)\big] = -\big(1 - \sigma(\Delta)\big) = -\sigma(-\Delta)

기울기의 크기가 σ(−Δ)\sigma(-\Delta) 입니다 — 이미 크게 벌어져 있는 쌍은 거의 밀지 않고, 뒤집혀 있거나 붙어 있는 쌍을 세게 민다는 뜻입니다. Δ=0\Delta=0 이면 0.5, Δ=3\Delta=3 이면 0.047로 열 배 넘게 줄어듭니다. 순위가 이미 맞은 쌍에 힘을 쓰지 않는 이 성질은 따로 넣은 것이 아니라 가능도에서 저절로 나온 것입니다.

로그 시그모이드 손실과 그 기울기

−log⁡σ(Δ)-\log\sigma(\Delta) 는 Δ\Delta 에 대해 볼록합니다 — 두 번 미분하면 σ(Δ)(1−σ(Δ))\sigma(\Delta)(1-\sigma(\Delta)) 로 늘 양수이기 때문입니다. 그리고 Δ\Delta 는 점수들의 선형 결합이므로, 점수 자체를 파라미터로 두면 이 손실은 전역 최솟값을 하나만 가집니다. 다만 실제 보상 모델은 rr 을 신경망으로 만들므로 그 신경망의 가중치에 대해서는 볼록하지 않습니다. 볼록한 것은 점수 위에서이지 가중치 위에서가 아닙니다.

보상의 절대값에는 의미가 없다

앞에서 붙잡아 둔 성질로 돌아옵니다. 모든 답의 점수에 같은 상수 cc 를 더하면 어떻게 될까요.

σ((rA+c)−(rB+c))=σ(rA−rB)\sigma\big((r_A + c) - (r_B + c)\big) = \sigma(r_A - r_B)

모든 쌍의 확률이 하나도 바뀌지 않습니다. 그러면 가능도도 그대로이고 손실도 그대로입니다. 즉 데이터는 점수의 절대적인 위치에 대해 아무 말도 하지 않습니다. 최적해가 하나가 아니라 한 줄로 이어져 있는 것이고, 통계에서는 이런 상황을 파라미터가 식별되지 않는다고 말합니다.

평행이동해도 모든 쌍의 확률이 같다

실무에서 이것이 드러나는 자리가 셋입니다.

  • 보상 모델 출력의 절대값을 읽으면 안 됩니다. 「이 답은 4.7점」이라는 말은 같은 모델 안에서 다른 답과 비교할 때만 뜻이 있고, 다른 보상 모델의 4.7과 비교하는 것은 무의미합니다.
  • 학습을 안정시키려고 출력을 중심화합니다. 배치 안에서 평균을 0으로 맞추거나 정규화 항을 하나 붙이는 방식인데, 없는 정보를 만들어 내는 것이 아니라 한 줄로 이어진 최적해 중에서 하나를 고르는 것뿐입니다.
  • 정책 학습에서는 이 자유도가 저절로 사라집니다. 지난 글의 베이스라인이 정확히 그 일을 합니다 — 그룹 평균을 빼는 순간 공통 상수가 지워집니다. 그래서 보상 모델의 눈금이 어긋나 있어도 정책 학습은 영향을 받지 않습니다.

같은 성질에 실패 모드도 하나 딸려 옵니다. 어떤 답이 등장한 모든 비교에서 이겼다면, 그 답의 점수를 올릴수록 가능도가 계속 커지므로 최대가능도 해가 무한대로 달아납니다. 데이터가 완전히 갈려 있을 때 생기는 일이고, 그래서 실제 학습에는 정규화나 조기 종료가 함께 붙습니다.

비교 몇 개면 점수차를 알 수 있나

「A가 B보다 낫다」 한 번으로는 아무것도 못 정합니다. 그러면 몇 번이면 될까요. 두 답만 놓고 nn 번 비교했다고 하면, A가 이긴 횟수 ww 는 이항분포를 따르고 점수차의 최대가능도 추정값은 승률의 로짓입니다.

Δ^=log⁡wn−w\hat\Delta = \log\frac{w}{n-w}

이 추정값의 표준오차는 가능도의 곡률에서 나옵니다. 비교 한 번이 Δ\Delta 에 대해 주는 정보량이 p(1−p)p(1-p) 이고 p=σ(Δ)p = \sigma(\Delta) 이므로, nn 번이면

SE(Δ^)≈1n p(1−p)\mathrm{SE}(\hat\Delta) \approx \frac{1}{\sqrt{n\,p(1-p)}}

입니다. 모의실험으로 맞춰 보겠습니다.

import numpy as np

rng = np.random.default_rng(0)
sig = lambda x: 1 / (1 + np.exp(-x))

for delta in (0.0, 1.0, 2.0, 3.0):
    p = sig(delta)
    out = []
    for n in (200, 2000):
        w = rng.binomial(n, p, size=20_000)      # 비교 n번을 2만 번 되풀이
        ok = (w > 0) & (w < n)
        dh = np.log(w[ok] / (n - w[ok]))         # 각 되풀이의 추정 점수차
        out.append(f"n={n:>5}  실측 {dh.std():.3f} / 이론 {1/np.sqrt(n*p*(1-p)):.3f}")
    print(f"Δ={delta:.0f}  P(A≻B)={p:.3f}   " + "   ".join(out))

# Δ=0  P(A≻B)=0.500   n=  200  실측 0.142 / 이론 0.141   n= 2000  실측 0.045 / 이론 0.045
# Δ=1  P(A≻B)=0.731   n=  200  실측 0.160 / 이론 0.159   n= 2000  실측 0.051 / 이론 0.050
# Δ=2  P(A≻B)=0.881   n=  200  실측 0.225 / 이론 0.218   n= 2000  실측 0.070 / 이론 0.069
# Δ=3  P(A≻B)=0.953   n=  200  실측 0.370 / 이론 0.333   n= 2000  실측 0.106 / 이론 0.105

두 가지가 읽힙니다.

첫째, 오차는 1/n1/\sqrt n 으로 줄어듭니다. 비교를 10배로 늘리면 오차가 약 3분의 1이 됩니다(0.142 → 0.045). 점수차를 소수 둘째 자리까지 믿으려면 그 쌍을 수천 번 비교해야 한다는 뜻이고, 실제 선호 데이터셋에서 같은 두 답을 수천 번 비교하는 일은 없습니다. 개별 답의 점수를 정밀한 값으로 읽으면 안 되는 두 번째 이유입니다.

둘째, 차이가 클수록 오차가 커집니다. Δ=0\Delta=0 일 때 0.142였던 것이 Δ=3\Delta=3 에서는 0.370으로 2.6배입니다. 뻔한 비교는 정보를 거의 주지 않기 때문입니다 — 95%를 이기는 쌍을 백 번 더 비교해 봐야 「역시 이긴다」만 확인할 뿐이고, 그 결과로 점수차가 3인지 4인지는 여전히 흐릿합니다. p(1−p)p(1-p) 가 0.5에서 최대라는 것이 이 말입니다.

비교 수와 점수차에 따른 표준오차

이 관찰에 실무적인 결론이 붙습니다. 비슷한 답끼리 비교시켜야 정보가 많이 남습니다. 선호 데이터를 모을 때 한쪽이 명백히 나은 쌍을 잔뜩 넣으면 라벨링 비용에 비해 배우는 것이 적습니다. 아레나 방식의 평가에서 실력이 가까운 상대끼리 붙이는 것도 같은 이유입니다.

항목이 여럿이면 누구와 붙었는지가 정한다

항목이 KK 개로 늘어도 모형과 손실은 그대로입니다 — 어떤 쌍이 비교되든 그 쌍의 점수차에 시그모이드를 씌우면 되니까요. 달라지는 것은 어느 쌍이 실제로 비교되었는가입니다.

항목을 점으로, 비교된 쌍을 선으로 그린 그래프를 생각해 봅시다. 비교가 많이 붙은 항목일수록 그 점수가 촘촘히 묶이고, 몇 번 안 붙은 항목은 헐겁게 매달려 있습니다. 그래프가 두 덩어리로 끊어져 있으면 두 덩어리 사이의 점수차는 데이터가 전혀 정하지 못합니다 — 한쪽 덩어리 전체를 통째로 올려도 비교된 모든 쌍의 차이가 그대로이기 때문입니다. 앞 절에서 본 평행이동 불변이 덩어리마다 따로 생기는 것이고, 그래서 순위가 하나로 정해지지 않습니다.

선호 데이터셋에서는 답이 대부분 같은 프롬프트 안에서만 비교되므로 이 문제가 심각해 보이지만, 실제로는 rϕr_\phi 가 답을 통째로 읽는 신경망이라 서로 다른 프롬프트의 답들이 파라미터를 공유합니다. 끊어진 그래프를 이어 주는 것이 그 공유이고, 대신 이어 준 방식이 맞는지는 데이터가 아니라 모델이 보증합니다.

다시 그 한 줄로

정리하면 맨 앞 코드는 이렇게 읽힙니다. r_w - r_l이 Bradley-Terry 모델의 Δ\Delta 이고, logsigmoid가 그 차이를 「이 사람이 이렇게 고를 확률」로 바꾸며, 앞의 음수 부호와 mean()이 음의 로그가능도입니다. 순서만 있는 라벨에서 실수 눈금이 나오는 이유도 분명합니다 — 눈금을 배운 것이 아니라 차이를 배운 것이고, 절대적인 위치는 애초에 데이터에 없었습니다.

이 유도가 다음에 두 곳에서 다시 쓰입니다. 하나는 중급 78번 · Elo와 아레나 순위입니다. Elo 점수는 정확히 이 모델의 강도이고, 경기 결과마다 점수를 갱신하는 그 공식이 위 손실에 대한 확률적 경사하강 한 걸음입니다.

다른 하나가 이 시리즈의 목적지입니다. 위 손실에는 정책이 등장하지 않고 보상 모델만 있는데, 만약 rr 을 정책으로 적을 수 있다면 보상 모델을 따로 두지 않고 이 손실을 정책에 바로 걸 수 있습니다. 그 다리를 놓으려면 「KL 예산 안에서 보상을 최대화한다」는 문제를 실제로 풀어야 하고, 다음 글이 그 도구를 준비합니다.

정리

  • Bradley-Terry 모델은 항목마다 실수 강도 rr 을 두고 P(A≻B)=σ(rA−rB)P(A\succ B) = \sigma(r_A - r_B) 로 비교 결과를 설명하는 모형이다. 두 값에 소프트맥스를 씌운 것과 같은 식이다.
  • 점수차 1은 승률 0.731, 2는 0.881, 3은 0.953이다. 보상 모델 출력의 차이는 이 눈금으로 읽는다.
  • 비교 nn 개의 가능도는 ∏iσ(rw(i)−rl(i))\prod_i \sigma(r_w^{(i)} - r_l^{(i)}) 이고, 로그를 취해 부호를 뒤집으면 −1n∑ilog⁡σ(rw−rl)-\frac1n\sum_i\log\sigma(r_w - r_l) 이다. 보상 모델 손실은 이 모형에 최대가능도를 적용한 결과일 뿐이다.
  • 손실의 기울기 크기는 σ(−Δ)\sigma(-\Delta) 라 이미 벌어진 쌍은 거의 밀지 않는다. Δ\Delta 에 대해 볼록하지만, rr 을 신경망으로 만들면 그 가중치에 대해서는 볼록하지 않다.
  • 보상은 상수 평행이동에 불변이다. 모두에 cc 를 더해도 모든 쌍의 확률이 그대로라 데이터가 절대값에 대해 아무 말도 하지 않는다. 그래서 출력의 절대값을 읽으면 안 되고, 학습에서는 중심화로 하나를 고르며, 정책 학습에서는 베이스라인이 그 자유도를 지운다.
  • 항목이 여럿이면 비교 그래프가 끊어진 덩어리마다 평행이동 자유도가 따로 생겨 순위가 정해지지 않는다. 선호 데이터에서 그 덩어리들을 이어 주는 것은 데이터가 아니라 rϕr_\phi 가 파라미터를 공유한다는 사실이다.
  • 두 답을 nn 번 비교해 얻는 점수차의 표준오차는 1/n p(1−p)1/\sqrt{n\,p(1-p)} 다. nn 을 10배로 늘려야 오차가 3분의 1이 되고, Δ\Delta 가 클수록 오차가 커진다 — 뻔한 비교는 정보를 거의 주지 않으므로 비슷한 답끼리 비교시키는 편이 낫다.

읽어주셔서 감사합니다. 😊

LATEST

수학의 최신 글

수학2026.09.07

양자화 오차: 격자 사상, 오차 분산, 이상치 채널

실수를 2^b개 격자에 사상할 때 오차의 분산이 왜 Δ²/12인지 유도하고, 그것이 비트당 6.02dB라는 SNR로 번역되는 과정을 실측과 대조했습니다. 이상치 하나가 나머지 값의 유효 비트를 어떻게 먹는지, 그리고 int4에서 성능이 무너지는 지점을 오차 예산으로 미리 계산하는 법까지.

중급18 MIN
수학2026.09.07

수치적으로 안정한 계산 패턴 모음

최댓값 빼기, 로그 공간, log1p·expm1, 분산의 두 공식, 정규화의 ε, fp32 누산, 역행렬 대신 solve — 프레임워크가 몰래 해 주는 일곱 가지를 하나씩 꺼내 각각 어떤 고장을 막는지 직접 재 봤습니다. 수식을 그대로 옮긴 코드가 왜 라이브러리보다 나쁜지에 대한 목록입니다.

중급22 MIN
수학2026.09.07

부동소수점은 어디서 새는가: 반올림, 상쇄, 더하는 순서

0.1 + 0.2가 0.3이 아닌 이유부터 시작해 머신 엡실론을 유도하고, 같은 16비트인데 fp16과 bf16이 서로 다른 지점에서 터지는 이유, 비슷한 수를 뺄 때 유효자리가 사라지는 파괴적 상쇄, 그리고 1,000만 개를 순서만 바꿔 더했을 때 오차가 백만 배 갈리는 실험까지 직접 재 봤습니다.

중급23 MIN