지도 미세조정 코드에서 손실은 한 줄입니다.
loss = F.cross_entropy(logits.view(-1, V), labels.view(-1))
정답 토큰이 있고, 모델이 거기에 준 확률의 로그를 재고, 그것을 올리면 됩니다. 그런데 「사람이 보기에 더 나은 답을 내게 한다」는 목표에는 저 labels에 해당하는 것이 없습니다. 있는 것은 답을 통째로 받아 점수를 매기는 채점자 하나뿐입니다. 점수가 0.7이라고 해서 어느 토큰을 어느 쪽으로 밀어야 하는지는 아무도 알려 주지 않습니다.
이 글은 그 목표를 최적화 문제로 정확히 적고, 그렇게 적고 나면 무엇이 막히는지를 봅니다. 강화학습의 알고리즘 전반은 강화학습 기초와 정책 그래디언트가 다루고, 여기서는 목적식의 형식과 그 하나의 난점만 봅니다.
정책과 궤적
확률이 곱이라 로그로 다룬다
언어모델은 프롬프트 를 받아 답 를 냅니다. 답은 토큰을 하나씩 뽑아 만들어지고, 각 토큰은 그 시점까지의 문맥에 대한 확률분포에서 나옵니다. 그러니까 모델은 답 전체에 대한 확률분포를 이미 정의하고 있습니다.
상태를 받아 행동의 확률분포를 내놓는 이런 함수를 정책이라고 부르고, 그렇게 만들어진 행동의 열 하나를 궤적이라고 부릅니다. 언어모델에서 궤적은 답 하나, 즉 토큰 열 하나입니다.
곱이라는 점을 먼저 짚어 둡니다. 토큰마다의 확률이 평균 0.9 정도만 되어도 200토큰짜리 답의 확률은 입니다. 길이가 늘면 지수적으로 작아지고, 32비트 부동소수점의 최소 정규값이 쯤이라 400토큰 남짓에서 0으로 내려앉습니다.
그래서 이 확률을 날로 다루는 코드는 없습니다. 로그를 취하면 곱이 합이 됩니다.
200토큰이면 정도의 흔한 수가 되고, 언더플로가 사라집니다. 미분에도 합이 훨씬 낫습니다 — 곱의 미분은 항이 개로 늘어나지만 합의 미분은 각 항을 따로 미분해 더하면 됩니다. 아래에서 막히는 자리를 뚫을 때 이 성질이 그대로 쓰입니다.
π는 답이 아니라 토큰 열에 확률을 준다
구별해 둘 것이 하나 있습니다. 정책이 확률을 주는 대상은 토큰 열이고, 사람이 말하는 「답」은 그것보다 거친 단위입니다. 같은 내용을 여러 토큰 열로 적을 수 있기 때문입니다.
- 토크나이저가 한 문자열을 여러 방식으로 쪼갤 수 있습니다 —
▁un+happy와▁unhappy는 다른 토큰 열이지만 디코딩하면 같은 글자입니다. - 「4」와 「네 개」처럼 표기가 다른데 채점자가 같은 점수를 주는 경우도 있습니다.
- 공백이나 줄바꿈 하나가 다른 답도 별개의 토큰 열입니다.
그래서 어떤 답 의 확률은 그 답으로 디코딩되는 모든 토큰 열의 확률을 더한 값이고, 가 어느 토큰 열 하나에 준 확률과는 다릅니다. 「모델이 이 답에 얼마의 확률을 주는가」를 한 번의 생성 확률로 읽으면 언제나 과소평가입니다.
이 글의 계산에는 이 구별이 문제가 되지 않습니다. 목적식이 로 뽑은 토큰 열의 평균 점수이고, 같은 내용의 열 여럿은 각자 뽑힐 확률만큼 그 평균에 들어오기 때문입니다. 구별이 걸리는 자리는 확률을 직접 견주는 일 — 답 둘의 가능도를 비교하거나 정규화된 점수를 쓰는 평가 — 입니다.
채점자가 흔들려도 형식은 그대로다
여기에 채점자 가 붙습니다 — 사람의 선호로 학습된 보상 모델일 수도, 단위 테스트 통과 여부일 수도, 정답과의 일치 여부일 수도 있습니다. 무엇이든 답이 다 만들어진 뒤에 점수 하나를 주는 함수라는 점이 같습니다. 은 를 모릅니다.
채점자가 늘 같은 점수를 주지 않는 경우도 있습니다. 사람 평가자가 같은 답에 다른 점수를 주고, LLM 심사자는 온도가 0이 아니면 매번 흔들리며, 플레이키한 테스트는 같은 코드에 통과와 실패를 번갈아 냅니다. 그래도 목적식의 형식은 바뀌지 않습니다. 점수를 대신 조건부 기댓값 로 두면 기댓값이 두 겹이 되고, 두 겹을 하나로 합치면 원래 식과 같아집니다.
바뀌는 것은 형식이 아니라 표본 하나의 값어치입니다. 채점이 흔들리면 같은 답을 여러 번 채점해야 에 가까워지므로, 같은 정확도를 얻는 데 표본이 더 듭니다. 아래에서 표본 비용을 셀 때 이 항이 곱으로 들어옵니다.
목적식
J(θ)를 적기
우리가 원하는 것은 "이 모델이 내는 답들이 평균적으로 좋은 점수를 받는 것"입니다. 그대로 적으면
이고, 이것을 최대화합니다. 프롬프트 쪽 기댓값은 지도학습과 똑같은 데이터 평균이라 특별할 것이 없으므로, 아래에서는 프롬프트 하나를 고정하고 안쪽만 봅니다.
오른쪽 합은 가능한 답이 셀 수 있을 만큼 적을 때의 표현입니다. 실제로는 어휘가 개이고 길이가 이면 답이 가지라 셀 수 없지만, 식이 무엇을 뜻하는지 보는 데는 이 꼴이 편합니다.
지도학습의 손실과 나란히 놓으면 차이가 한눈에 보입니다.
| 지도학습 | 기대 보상 | |
|---|---|---|
| 식 | ||
| 평균을 내는 분포 | 데이터셋 | 정책 |
| 그 분포가 에 의존하는가 | 아니다 | 그렇다 |
| 가 들어간 자리 | 기댓값 안의 | 기댓값 아래 첨자 |
| 표본마다 아는 것 | 정답 | 점수 하나 |
| 방향 | 최소화 | 최대화 |
세 번째 줄이 이 글의 전부입니다. 지도학습에서는 를 바꿔도 뽑히는 표본이 그대로이므로 미분이 기댓값 안으로 그냥 들어갑니다.
표본을 뽑고 각 표본에서 을 계산해 평균 내면 끝입니다. 미니배치 그래디언트가 불편 추정량이었던 것도 이 등식 덕분이었습니다. 기대 보상 쪽에서는 이 등식이 성립하지 않습니다.
점수에 상수를 더해도 그래디언트는 그대로다
목적식을 적고 나면 바로 확인되는 성질이 하나 있습니다. 모든 답의 점수에 같은 상수 를 더해도 가 변하지 않습니다. 확률의 합이 언제나 1이라는 사실 한 줄에서 나옵니다.
를 더하면 그래디언트에 이 얹히므로 아무 일도 일어나지 않습니다. 자체는 만큼 올라가는데 기울기는 한 성분도 안 바뀝니다.
이 한 줄이 뒤에 나올 베이스라인의 씨앗입니다. 점수에서 무엇을 빼도 그래디언트의 참값은 같으니, 값을 잘 골라 빼면 참값은 지키면서 추정의 흔들림만 줄일 수 있습니다. 실제로 「평균보다 얼마나 나은가」를 쓰는 관행이 전부 이 자유에서 나옵니다. 조건이 하나 붙는데 — 빼는 값이 에 의존하지 않아야 합니다. 마다 다른 값을 빼면 가 0이라는 보장이 없어집니다.
같은 J를 주는 정책이 여럿이다
는 와 의 내적이므로 에 대해 일차식입니다. 그런데 는 로짓의 softmax이고 로짓은 신경망의 출력이라, 같은 가 에 대해서는 전혀 일차식이 아닙니다. 어려움이 목적식의 모양에 있는 것이 아니라 라는 사상에 있다는 뜻입니다.
일차식이라는 것을 그림으로 보면 따라오는 사실이 하나 더 있습니다. 답이 셋인 경우 가능한 정책 전체는 삼각형 하나 — 확률 셋이 음이 아니고 합이 1인 점들의 모임 — 이고, 그 위에서 의 등고선은 직선입니다.
한 직선 위의 모든 정책이 같은 를 줍니다. 목적식이 정책을 하나로 못 박지 않는다는 말이고, 최댓값이 언제나 꼭짓점 — 가장 점수가 높은 답에 확률 1을 주는 정책 — 에서 선다는 뜻이기도 합니다. 그래서 만 끝까지 최대화하면 정책이 답 하나로 무너집니다. 앞에서 본 항과 엔트로피 보너스가 하는 일이 이 무너짐을 막는 것입니다.
실제로 쓰는 목적식에는 항이 하나 더 있다
은 대개 사람의 선호로 학습한 근사 모델입니다. 근사이므로 학습 데이터에서 멀리 떨어진 답에 대해서는 점수가 미덥지 않고, 만 최대화하면 모델이 그 틈을 찾아냅니다 — 사람이 보기에는 나쁜데 보상 모델만 높은 점수를 주는 답으로 몰려가는 것입니다. 그래서 처음 모델에서 너무 멀어지지 않도록 항을 하나 더 답니다.
는 학습을 시작할 때의 모델이고, 은 두 분포가 얼마나 다른지를 재는 값입니다. 중요한 것은 이 항도 풀어 쓰면 똑같이 에 대한 기댓값이라는 점입니다.
즉 항이 하나 늘어도 형식은 그대로이고, 아래에서 볼 난점도 그대로 공유합니다. 이 항을 벌점이 아니라 「 예산 안에서 보상을 최대화한다」는 제약으로 적는 방법은 중급 56번 · 라그랑주 승수와 KKT가 맡습니다.
기댓값 안으로 못 들어가는 미분
남는 것은 기댓값이 아니다
합으로 펼쳐서 직접 미분해 보면 무엇이 남는지 알 수 있습니다.
은 를 모르므로 미분되는 것은 뿐입니다. 식 자체는 맞습니다. 문제는 이것이 더 이상 기댓값이 아니라는 것입니다.
기댓값이려면 가중치가 확률이어야 합니다 — 전부 0 이상이고 합이 1이어야 표본평균으로 추정할 수 있습니다. 그런데 여기 가중치는 이고, 이것은 성분이 음수일 수도 있고 합이 1도 아닙니다(합은 앞 절에서 본 대로 0입니다). 표본을 뽑아 평균 내는 방식으로는 이 합에 접근할 수 없습니다.
증상을 더 구체적으로 적으면 이렇습니다. 우리가 실제로 할 수 있는 일은 에서 답 몇 개를 뽑아 보는 것뿐입니다. 그렇게 뽑은 은 의 함수가 아니라 그냥 토큰 열입니다. 이 표본들의 점수 평균 를 로 미분하면 정확히 0이 나옵니다 — 식 어디에도 가 없기 때문입니다.
의 영향은 "그 표본들이 뽑힐 확률"에만 들어 있는데, 그 확률은 이미 표본을 뽑는 과정에서 소비되어 사라졌습니다. 재매개변수화로 우회하는 길도 여기서는 막혀 있습니다. 정규분포에서 뽑을 때는 으로 무작위성을 밖으로 빼낼 수 있지만, 토큰은 이산이라 에 대해 미분 가능한 함수로 적을 수 없습니다. 「토큰 번호 4128」을 로 미분한다는 말이 성립하지 않습니다.
답이 셋이면 끝까지 전개된다
답이 몇 개뿐이고 정책이 로짓 하나짜리 softmax이면 위의 합을 손으로 끝까지 풀 수 있습니다. 필요한 것은 softmax의 편미분 하나입니다.
여기서 는 일 때 1이고 아니면 0인 기호입니다. 이것을 에 넣습니다.
뒤의 합이 자체, 곧 이므로 한 줄로 정리됩니다.
는 성분끼리 곱하는 연산입니다. 이 식이 읽히는 대로 읽어 보면 정책 그래디언트가 하려는 일이 그대로 적혀 있습니다 — 평균보다 나은 답의 확률을 올리고 못한 답의 확률을 내린다, 그리고 그 크기는 그 답이 지금 뽑힐 확률 에 비례한다. 확률이 거의 0인 답은 아무리 점수가 좋아도 기울기를 거의 못 받습니다.
이라는 꼴이 앞 절의 상수 자유와 같은 것이라는 점도 보입니다. 상수를 더해도 이 차가 안 변하고, 그래서 그래디언트도 안 변합니다.
수로 한 번 박아 둡니다. 이고 점수가 이면
입니다. 세 성분의 합이 0인 것 — 위에서 증명한 이 그대로 나타난 자리입니다. 그리고 가운데 성분이 음수인 것도 읽을 거리입니다. 두 번째 답의 점수 0은 세 답 가운데 중간인데, 기준이 0이 아니라 평균 0.1622이므로 평균보다는 못한 답입니다. 「좋은 답」의 기준이 절댓값이 아니라 지금 정책의 평균이라는 것이 이 부호에 적혀 있습니다.
이 세 수가 아래에서 유한차분의 결과를 맞대 볼 기준입니다.
유한차분의 표본 비용
차분이 잡음을 ε으로 나눈다
자체는 표본으로 잘 추정됩니다 — 답을 여러 개 뽑아 점수를 평균 내면 됩니다. 그렇다면 파라미터를 조금씩 흔들어 차분을 재면 되지 않을까요. 위의 장난감 문제로 확인해 보겠습니다.
import numpy as np
R = np.array([1.0, 0.0, -1.0]) # 세 가지 답의 점수
def pi(th):
e = np.exp(th - th.max()); return e / e.sum()
th = np.array([0.3, 0.1, -0.2])
p = pi(th)
print("π(θ) =", np.round(p, 4), " J(θ) =", round(float(p @ R), 6))
exact = p * (R - p @ R) # 답이 셋뿐이라 손으로 구할 수 있다
print("정확한 ∇J =", np.round(exact, 6))
rng = np.random.default_rng(0)
for n in (100, 10_000, 1_000_000): # J 를 표본으로 추정하는 것은 잘 된다
y = rng.choice(3, size=n, p=p)
print(f" 샘플 {n:>9,}개로 추정한 J = {R[y].mean(): .6f}")
eps = 1e-3 # 그 추정값의 차분을 재면?
for n in (10_000, 1_000_000):
g = np.zeros(3)
for k in range(3):
tp = th.copy(); tp[k] += eps
yp = rng.choice(3, size=n, p=pi(tp))
ym = rng.choice(3, size=n, p=p)
g[k] = (R[yp].mean() - R[ym].mean()) / eps
err = np.linalg.norm(g - exact) / np.linalg.norm(exact)
print(f" 유한차분 (샘플 {n:>9,}개 × 파라미터 3개) 상대오차 {err:.2f}")
# π(θ) = [0.4123 0.3376 0.2501] J(θ) = 0.162238
# 정확한 ∇J = [ 0.345432 -0.054769 -0.290663]
# 샘플 100개로 추정한 J = 0.040000
# 샘플 10,000개로 추정한 J = 0.163100
# 샘플 1,000,000개로 추정한 J = 0.161614
# 유한차분 (샘플 10,000개 × 파라미터 3개) 상대오차 47.67
# 유한차분 (샘플 1,000,000개 × 파라미터 3개) 상대오차 2.19
는 만 개만 뽑아도 0.1631로 참값 0.1622에 거의 맞습니다. 그런데 그 추정값의 차분은 상대오차 4,767%입니다. 백만 개를 뽑아도 219%입니다.
이유는 지난 글들에서 계산한 그대로입니다. 의 추정 오차는 표본 수의 제곱근에 반비례해 인데, 차분은 그 오차를 으로 나눕니다. 이면 잡음이 천 배로 증폭되고, 정작 재려는 신호는 에 비례해 작습니다. 을 키우면 근사가 거칠어지고 줄이면 잡음이 커지는데, 여기서는 잡음 쪽이 압도적입니다.
상대오차 10%에 닿으려면 파라미터 하나당 10억 번을 뽑아야 합니다. 그리고 유한차분은 파라미터마다 따로 해야 하므로 파라미터가 개면 이 길은 열려 있지 않습니다. 역전파 한 번에 모든 파라미터의 편미분을 함께 얻는 것과 비교하면 격차가 얼마나 큰지 보입니다.
같은 난수를 두 항에 쓰면
잡음의 정체를 보면 크게 줄일 길이 하나 있습니다. 위 코드는 쪽과 쪽에서 서로 다른 난수로 따로 뽑았습니다. 그러면 두 추정값이 각각 만큼 독립으로 흔들리고, 차를 내면 흔들림이 오히려 배가 됩니다. 정작 재려는 차는 에 비례해 아주 작습니다.
양쪽에 같은 난수를 쓰면 두 흔들림이 대부분 상쇄됩니다. 이산 표집에서 짝을 맞추는 방법은 역변환 표집입니다 — 균등난수 하나를 뽑아 두 분포의 누적확률에 각각 대어 답을 고르는 것입니다. 두 분포가 만큼만 다르므로 대부분의 에서 같은 답이 나오고, 차가 0이 아닌 것은 경계가 지나간 좁은 구간에 떨어진 뿐입니다.
def inv(u, p): # 역변환 표집 — 같은 u 를 두 분포에 댄다
c = 0.0
for i, pi_ in enumerate(p):
c += pi_
if u < c:
return i
return len(p) - 1
def fd(n, common):
g = np.zeros(3)
for k in range(3):
tp = th.copy(); tp[k] += eps
pp = pi(tp)
if common:
u = rng.random(n)
g[k] = np.mean([R[inv(v, pp)] - R[inv(v, p)] for v in u]) / eps
else:
a = np.mean([R[inv(v, pp)] for v in rng.random(n)])
b = np.mean([R[inv(v, p)] for v in rng.random(n)])
g[k] = (a - b) / eps
return np.linalg.norm(g - exact) / np.linalg.norm(exact)
for n in (10_000, 1_000_000):
print(f"n={n:>9,} 독립 난수 {fd(n, False):7.3f} 공통 난수 {fd(n, True):7.3f}")
# n= 10,000 독립 난수 40.802 공통 난수 0.342
# n=1,000,000 독립 난수 4.222 공통 난수 0.038
만 개에서 상대오차가 4,080%에서 34%로 떨어집니다 — 120배입니다. (독립 난수 쪽 수가 앞 블록의 47.67과 조금 다른 것은 표집 방식이 달라서이고, 자릿수는 같습니다.) 잡음을 줄이는 데 표본을 더 쓴 것이 아니라 짝을 맞춘 것만으로 얻은 이득입니다.
그런데 이것이 유한차분을 살려 주지는 않습니다. 파라미터마다 따로 흔들어야 하는 구조가 그대로이기 때문입니다. 70억 개짜리 모델에서 파라미터당 만 번씩 답을 생성하는 것은 34%든 4,080%든 시작할 수 없는 계산입니다.
중심차분과 무작위 방향
남은 두 가지 손질도 같은 벽에 부딪힙니다.
중심차분. 으로 바꾸면 근사의 편향이 에서 로 줄어듭니다. 좋은 손질이지만 고치는 것이 편향뿐입니다. 두 항을 여전히 표본으로 추정하므로 잡음은 꼴로 남고, 으로 나누는 증폭이 그대로입니다. 위 실험에서 지배한 것이 편향이 아니라 잡음이었으니 여기서 얻을 것이 거의 없습니다.
무작위 방향 하나. 파라미터마다 흔드는 대신 무작위 방향 를 하나 뽑아 를 그래디언트의 추정으로 쓰는 방법이 있습니다. 평가 횟수가 파라미터 수와 무관하게 두 번이라 앞의 구조적 문제를 피합니다.
대신 분산이 차원에 비례해 남습니다. 방향 하나로는 그래디언트의 한 성분만 재고 나머지 차원은 잡음으로 들어오기 때문입니다. 같은 정확도를 얻으려면 방향을 개 뽑아야 하므로, 줄인 것이 계산의 모양이고 총량은 그대로입니다. 파라미터가 개면 어느 쪽으로 세든 답이 같습니다.
같은 벽을 만나는 다른 문제들
이산 잠재변수와 하드 어텐션
이 막힘이 강화학습만의 사정이 아니라는 점을 짚어 두면 다음 글의 항등식이 왜 그렇게 넓게 쓰이는지가 보입니다. 같은 자리에서 막히는 문제가 셋 있습니다.
- 이산 잠재변수 모델. 데이터를 몇 개의 이산 코드 가운데 하나로 설명하는 모델에서, 코드 를 뽑는 순간 그 코드는 그냥 번호가 되어 와의 연결이 끊깁니다. 목적식이 이라 형식이 똑같습니다.
- 하드 어텐션. 여러 후보 가운데 하나를 골라 그것만 보는 어텐션은 고르는 행위가 이산 표집이라 미분되지 않습니다. 확률을 전부 섞는 소프트 어텐션이 미분되는 것과 대비됩니다.
- 구조 탐색. 층의 개수나 연산의 종류처럼 이산인 선택을 확률분포로 두고 성능을 점수로 받는 문제도 같은 꼴입니다.
셋을 나란히 적으면 형식이 하나로 겹칩니다.
문제의 이름이 셋이고 남는 식은 하나입니다.
연속에서는 되는데 이산에서만 막히는 이유
같은 형식인데 잠재변수가 연속이면 재매개변수화가 통하고 이산이면 안 통합니다. 갈리는 지점을 한 줄로 적으면 이렇습니다 — 뽑은 값을 와 잡음의 미분 가능한 함수로 적을 수 있는가.
정규분포에서는 으로 적힙니다. 은 와 무관한 잡음이고 는 의 매끄러운 함수라, 미분이 그대로 를 지나 흘러갑니다. 무작위성은 이 다 짊어지고 는 매끄러운 쪽에 남습니다.
이산에서는 그런 함수가 없습니다. 출력이 정수 번호라 를 아주 조금 움직이면 값이 같은 번호로 머물거나 다른 번호로 튀거나 둘 중 하나입니다. 도함수가 거의 모든 곳에서 0이고 튀는 자리에서만 정의되지 않는 함수이므로, 미분이 지나갈 길이 없습니다. 앞에서 「표본을 뽑는 과정에서 확률이 소비되어 사라졌다」고 적은 것과 같은 말입니다.
그래서 남은 길은 하나입니다. 미분을 표본 쪽으로 밀어 넣는 것을 포기하고, 합을 다시 기댓값 꼴로 적는 항등식을 찾는 것입니다. 다음 글의 항등식이 그것이고, 위의 세 문제 모두에 글자 그대로 쓰입니다.
필요한 항등식의 모양
만족해야 할 조건 셋
무엇을 찾고 있는지를 먼저 적어 두면 다음 글에서 항등식이 왜 그 모양인지가 짐작됩니다. 어떤 함수 를 찾아
가 되게 만들면, 답을 뽑아 를 계산해 평균 내는 것만으로 그래디언트를 얻습니다. 그 가 지켜야 할 것이 셋입니다.
- 모든 에 대해 성립해야 한다. 특정 분포 꼴에서만 되는 항등식이면 정책이 신경망일 때 쓸 수 없습니다.
- 표본평균으로 계산될 수 있어야 한다. 곧 가 뽑은 하나만 보고 계산되는 값이어야 합니다. 모든 를 훑어야 하는 값이면 가지를 다 세는 것과 같습니다.
- 뽑은 표본에서 를 미분할 수 있어야 한다. 이산 표집이 끊어 놓은 연결을 어디선가 되살려야 하고, 살릴 수 있는 자리는 자체가 아니라 그 에 매겨진 확률뿐입니다.
세 번째 조건이 답의 모양을 거의 정해 줍니다. 위 식에서 필요한 것은 안에서 하나를 밖으로 끄집어내는 일이고, 그러면 남는 것은 「 로 나눈 」입니다. 그 꼴이 무엇의 미분인지는 로그의 도함수를 아는 사람에게는 이미 보입니다.
조건을 만족하는 것이 사실상 하나다
세 조건을 동시에 만족하는 것은 사실상 하나뿐이고, 다음 글이 그 유도와 성립 조건을 다룹니다. 미리 말해 둘 것은 대가입니다.
얻는 것은 불편 추정량입니다 — 표본을 뽑아 평균 내면 참 그래디언트로 수렴합니다. 그런데 그 추정량의 분산이 큽니다. 이유는 지금까지 본 구조에 이미 들어 있습니다. 답 하나에 점수 하나만 오고, 그 점수를 답 전체의 모든 선택에 똑같이 나눠 주는 방식이라, 좋은 점수를 받은 답 안의 나쁜 선택까지 함께 올라갑니다. 신호 하나가 200개의 결정에 퍼지는 것이므로 한 표본이 알려 주는 것이 적습니다.
그래서 다음 글 뒤에 이어질 이야기의 절반이 분산을 줄이는 방법입니다. 그 첫 손잡이가 무엇인지는 이 글에서 이미 증명해 두었습니다 — 점수에서 상수를 빼도 참값이 안 변한다는 그 자유입니다.
정리
- 정책 는 답 하나에 확률을 주는 함수이고, 언어모델은 이미 정책이다. 그 답 하나를 궤적이라 부른다. 확률이 곱이라 길이에 따라 지수적으로 작아지므로 언제나 로그로 다룬다.
- 가 확률을 주는 대상은 토큰 열이고 사람이 말하는 「답」은 그보다 거친 단위다. 같은 내용을 여러 열로 적을 수 있어, 생성 확률 하나를 그 답의 확률로 읽으면 과소평가다.
- 「좋은 답을 내게 한다」의 목적식은 이고 이것을 최대화한다. 채점이 흔들려도 조건부 기댓값 로 두면 형식은 그대로이고, 바뀌는 것은 표본 하나의 값어치다. 항도 에 대한 기댓값이라 형식을 안 바꾼다.
- 확률의 합이 1이므로 이고, 따라서 점수에 상수를 더해도 가 안 변한다. 베이스라인의 씨앗이며, 빼는 값이 에 의존하지 않아야 한다는 조건이 붙는다.
- 는 에 대해 일차식이라 확률 단체 위에서 등고선이 직선이다. 같은 를 주는 정책이 여럿이고 최댓값은 꼭짓점에 서므로, 만 최대화하면 정책이 답 하나로 무너진다.
- 지도학습과의 차이는 기댓값을 취하는 분포가 에 의존한다는 것 하나다. 합으로 펼쳐 미분하면 가 남는데 가중치가 확률이 아니라 기댓값이 아니고, 뽑아 놓은 표본은 의 함수가 아니라 그 평균을 미분하면 0이다.
- 답이 셋이면 softmax 편미분 로 끝까지 전개되어 이다. 평균보다 나은 답을 올리고 못한 답을 내리며, 크기는 지금 확률에 비례한다.
- 유한차분은 원리상 되지만, 답이 셋뿐인 문제에서도 10% 오차에 파라미터당 표본 10억 개가 든다. 공통 난수로 짝을 맞추면 오차가 120배 줄고, 중심차분은 편향만 고치고 무작위 방향은 분산을 차원만큼 남긴다 — 어느 손질도 파라미터마다 흔들어야 하는 구조를 없애지 못한다.
- 이산 잠재변수 모델, 하드 어텐션, 구조 탐색이 전부 같은 꼴에서 막힌다. 연속에서 되는 재매개변수화가 이산에서 안 되는 이유는 뽑은 값을 의 미분 가능한 함수로 적을 수 없다는 것 하나다.
읽어주셔서 감사합니다. 😊

