DPO 수식에는 logπ(y∣x) 꼴의 로그확률이 네 번 나온다. 학습 중인 모델 πθ 로 둘, 레퍼런스(학습을 묶어 두는 기준 모델) πref 로 둘이다. 사실 이 양은 DPO만의 것이 아니다. 정책(프롬프트를 받아 응답을 뽑는 모델 πθ)을 학습하는 정책 그래디언트는 R⋅∇θlogπθ(y) — 바로 이 로그확률의 그래디언트에 보상을 곱한다. PPO가 계산하는 비율 πθ/πold(업데이트 직전 정책과의 비율)도 로그확률 둘의 차이를 지수로 올린 것이다. 이 책의 모든 알고리즘이 이 숫자 위에서 돌아간다.
뜻은 단순하다. "모델 πθ가 프롬프트 x를 받았을 때 응답 y 전체를 만들어낼 확률"의 로그다. 결과는 −0.5, −2.4 같은 숫자 하나다. DPO는 데이터셋의 (프롬프트, 선호 응답, 비선호 응답)마다 이 숫자를 구해 손실을 만든다.
그러면 이 숫자는 어떻게 구하는가?
문장 로그확률: 토큰 로그확률의 합
언어모델은 문장 전체에 확률을 한 번에 매기지 않는다. 토큰을 하나씩 만들 뿐이다. 그런데 DPO가 필요로 하는 것은 "서울입니다"라는 문장 전체의 확률이다. 토큰 하나하나의 확률에서 문장의 확률을 어떻게 얻을까?
토큰 자리마다의 확률표
언어모델이 토큰을 "하나씩 생성한다"는 말은, 토큰 하나를 만들 때마다 먼저 확률표를 얻는다는 뜻이다.
[1단계: 확률표 얻기] 프롬프트와 지금까지의 토큰을 트랜스포머에 넣으면, 다음에 올 수 있는 모든 토큰의 확률 분포가 나온다. 표의 길이는 모델이 아는 토큰의 가짓수(어휘 크기)다. 메타가 2024년에 공개한 언어모델 라마 3(Llama 3)는 어휘가 약 128,000개라서, 표 하나가 128,000칸이다. “대한민국의 수도는” 다음이라면 이런 표가 나온다(확률 값은 설명을 위해 정한 것이다):
다음 토큰
확률
로그확률
서울
0.74
−0.30
부산
0.03
−3.51
대전
0.02
−3.91
… (약 128,000개, 합 = 1)
생성할 때는 이 표에서 토큰 하나를 실제로 고르는 단계가 뒤따른다. 이 절에서는 표만 쓴다. 여기서 필요한 것은 표 하나가 “앞 토큰들이 주어졌을 때 다음 토큰의 확률”, 즉 조건부 확률이라는 점이다.
곱을 합으로
"서울입니다"는 토큰 둘이다. 이 응답이 나오려면 첫 자리에서 "서울"이 나오고(0.74), "서울"까지 나온 뒤에 "입니다"가 나와야 한다(0.82라고 하자). 둘째 확률은 "서울"이 나온 경우 가운데서의 비율이므로 두 수를 곱하면 된다. 0.74×0.82=0.607. 로그를 취하면 곱이 합이 된다. log0.74+log0.82=−0.30+(−0.20)=−0.50.
"대한민국의 수도는?"에 대한 두 응답을 이렇게 계산해 보자.
첫 토큰
둘째 토큰
합 logπθ(y)
yw
서울: log0.74=−0.30
입니다 | 서울: log0.82=−0.20
−0.50
yl
부산: log0.03=−3.51
입니다 | 부산: log0.74=−0.30
−3.81
토큰이 몇 개든 같다. 확률의 곱셈 규칙 P(a,b)=P(a)P(b∣a) 를 거듭 쓰면(확률의 연쇄 법칙 — 미분의 연쇄 법칙과 이름만 같다) 문장 확률은 토큰별 조건부 확률의 곱이고, 로그를 취하면 합이 된다.
마진 3.31 가운데 3.21(97%)이 두 응답이 갈라지는 분기 토큰(forking token — 결말을 가르는 토큰) “서울” vs "부산"에서 나온다. 두 응답에 똑같이 들어 있는 토큰은 마진에 얼마를 보탤까? 아래 문제 3에서 따져 본다.
위젯에서 "부산"의 확률을 올려 보라. 마진은 거의 분기 토큰 하나에 따라 움직인다.
문제 1 — 서류, 필기, 면접
어느 회사의 채용은 세 단계다. 지원자 가운데 서류를 통과하는 비율은 0.2, 서류를 통과한 사람 가운데 필기를 통과하는 비율은 0.5, 필기를 통과한 사람 가운데 면접을 통과하는 비율은 0.4다. (가) 지원자 한 사람이 최종 합격할 확률은? (나) 지원자가 1,000명이면 단계마다 몇 명이 남는가? (다) 누군가 "필기 통과율이 0.5니까 지원자의 절반이 필기에 붙는다"고 말했다. 맞는가?
김민준
(다)는 맞죠. 필기 통과율 0.5면 1,000명 중 500명이 필기에 붙어요.
선생님
민준 학생, 필기 시험장에는 몇 명이 들어오죠?
김민준
서류를 붙은 사람만… 200명이네요. 그 절반이니까 100명. 500명은 필기장에 들어오지도 않은 사람까지 센 거였어요.
이서연
그러면 (나)는 1,000 → 200 → 100 → 40명이고, (가)는 0.2×0.5×0.4=0.04. 단계마다의 비율이 "앞 단계를 통과한 사람 가운데서"라서 그냥 곱하면 되는 거야.
선생님
그래요. 곱할 수 있는 것은 각 비율이 앞 단계까지 통과했다는 조건 아래의 비율이기 때문이에요.
김민준
동아리 가입률 조사할 때 "설명회 온 사람 중 가입률"을 전교생 가입률로 발표했다가 조교님한테 분모가 다르다고 지적받은 거랑 같네요.
정리 (가) 0.2×0.5×0.4=0.04. (나) 1,000 → 200 → 100 → 40명. (다) 틀렸다. 0.5는 서류를 통과한 200명 가운데의 비율이다. 단계마다의 비율이 앞 단계를 통과했다는 조건 아래의 비율이라서 곱으로 이어진다.
문제 2 — 곱과 합
세 토큰의 조건부 확률이 0.5, 0.25, 0.8이다. 문장의 로그확률과 확률을 구하시오.
김민준
로그 더하면 −0.30−0.60−0.10=−1.0. 확률은 10−1.0 이니까 0.1이에요.
이서연
확률은 맞는데 로그확률 값이 이상해. log0.5 가 −0.30 이면 상용로그잖아. 딥러닝에서 로그는 자연로그야. −0.69−1.39−0.22=−2.30.
김민준
아, 머릿속에서 계산기 log 버튼을 눌렀네. torch.log는 자연로그지.
선생님
확률은 둘 다 0.1인데 로그확률 숫자는 2.3배 차이가 나네요. 논문의 로그확률과 비교할 때 어느 쪽을 써야 할까요?
김민준
자연로그 쪽이요. 밑이 다르면 숫자가 ln 10배만큼 달라지니까요.
선생님
그래요. 그럼 애초에 왜 굳이 로그로 더할까요? 토큰이 1000개면요?
김민준
0.8을 천 번 곱하면 10−97 쯤? float32는 그 전에 0이 되겠네요.
선생님
그래요. 로그로 더하면 −223 같은 평범한 숫자로 남아요.
김민준
실험 과제에서 dB 단위랑 선형 단위 섞어 써서 그래프가 이상하게 나왔던 거랑 같네요. 단위부터 맞춰야 하는.
이서연
곱하는 세 수가 앞 토큰까지 나왔다는 조건 아래의 확률인 건 아까 채용 문제랑 같고, 여기서는 그 곱을 로그로 바꿔 더한 것만 달라.
정리logπ=−2.30, π=0.1. 긴 문장의 확률은 곱하면 부동소수점 아래로 사라지므로(언더플로) 로그의 합으로 다룬다.
문제 3 — 공유 토큰은 상쇄되는가
두 응답 앞에 똑같이 "음,"이 붙었다. yw = “음, 서울입니다”, yl = “음, 부산입니다”. 모델은 프롬프트 바로 뒤의 "음,"에 확률 0.10을 주고, 나머지 토큰의 확률은 본문 표와 같다(서울 0.74, 부산 0.03, 서울 뒤의 입니다 0.82, 부산 뒤의 입니다 0.74). (가) 두 응답의 문장 로그확률과 마진을 구하시오. (나) 토큰 자리 셋(“음,” / 서울·부산 / 입니다)이 마진에 각각 얼마를 보태는가? (다) 두 응답에 똑같이 들어 있는 토큰 둘 가운데 마진에 정확히 0을 보태는 것은 어느 쪽이고, 왜 그런가?
김민준
"음,"이 붙어서 두 응답 모두 확률이 확 작아졌으니까, 마진도 본문의 3.31에서 달라지겠네요.
선생님
민준 학생, (가)부터 계산해서 확인해 볼까요?
김민준
yw 는 −2.30−0.30−0.20=−2.80, yl 은 −2.30−3.51−0.30=−6.11. 마진은 3.31… 그대로네요. 두 응답에서 똑같이 2.30씩 빠져서 빼기에서 지워졌어요.
선생님
그럼 (나)에서 "입니다"는요? 그것도 두 응답에 똑같이 있는데요.
이서연
"입니다"의 몫은 (−0.20)−(−0.30)=+0.10. 전체 3.31 중 0.10이야.
김민준
공유 토큰이면 같은 토큰이니까 0이어야 하는 거 아냐? 계산 실수 같은데.
이서연
같은 토큰이어도 조건이 달라. 하나는 “서울” 뒤, 하나는 “부산” 뒤잖아. π(입니다∣서울) 이랑 π(입니다∣부산) 은 다른 조건부확률이야.
선생님
그럼 "음,"은 왜 정확히 0이죠? 그것도 두 응답에 같은 글자로 들어 있는데요.
이서연
"음,"은 두 응답 모두 프롬프트 바로 뒤예요. 앞에 놓인 것까지 똑같으니 조건도 같고, 확률도 0.10으로 같아요. 분기 앞에 있어서요.
선생님
그래요. 분기 뒤의 공유 토큰은 “비슷하게” 상쇄될 뿐이에요. 같은 글자인지가 아니라 앞에 놓인 것까지 같은지를 봐야 해요. DPO의 그래디언트도 두 응답의 로그확률 그래디언트를 빼는 꼴이라, "음,"의 두 항은 똑같아서 지워지고 학습이 힘을 쓰는 곳은 분기 토큰과 그 뒤예요.
이서연
조건부 기대값 수업에서 E[X∣A] 와 E[X∣B] 를 같은 X 라고 퉁치다 틀린 거랑 같다.
김민준
그래서 "음,"을 붙여도 마진이 3.31 그대로였구나. 분기 앞에 똑같이 붙는 말은 마진에 안 들어가네.
정리 (가) logπθ(yw)=−2.80, logπθ(yl)=−6.11, 마진 3.31. (나) “음,” 0, 분기 토큰 3.21, “입니다” +0.10. (다) “음,”. 분기 앞의 공유 토큰은 조건이 같아 정확히 상쇄되고, 분기 뒤의 공유 토큰은 조건이 달라 근사적으로만 상쇄된다. (민준처럼 "같은 글자 = 같은 확률"로 보면 틀린다.)