언어모델이 한 번의 순전파에서 내놓는 것은 다음 토큰 하나의 확률분포입니다. 어휘 5만 개짜리 벡터 하나, 그게 전부입니다. 그런데 우리는 태연히 «이 문장의 확률»이라고 말하고, 두 답변 중 어느 쪽이 더 그럴듯한지 점수로 비교하고, 로그가능도를 손실로 씁니다.
토큰 하나짜리 분포에서 문장 하나의 확률로 어떻게 건너가는가 — 이 글이 답할 것입니다. 지난 글에서 라는 곱을 모양만 빌려 썼는데, 그 곱이 어디서 오는지가 여기 있습니다. 그리고 답은 새로운 가정이 아니라 조건부 확률의 정의를 여러 번 쓴 것뿐입니다.
시작점 — 확률이 지켜야 하는 세 가지
확률은 «일어날 수 있는 모든 결과의 집합» 위에서 정의됩니다. 이 집합을 표본공간이라 하고 로 적습니다. 다음 토큰 자리라면 어휘 전체가 입니다. 그 부분집합 하나하나가 사건이고, 확률은 사건에 수를 붙이는 함수 입니다.
가 확률이라고 불리려면 세 가지만 지키면 됩니다.
- 음수가 없다. 모든 사건 에 대해
- 전체는 1이다.
- 겹치지 않으면 더한다. 이면
이것을 확률의 공리라고 합니다. 이 글에 나오는 모든 규칙이 여기서 나오고, softmax의 출력이 확률로 취급되는 것도 그 벡터가 이 셋을 만족하기 때문입니다 — 성분이 전부 양수이고, 합이 1이며, 서로 다른 토큰은 겹치지 않는 사건이라 합이 곧 합집합의 확률입니다.
결합·주변·조건부 — 표 하나로
두 자리를 동시에 보면 세 종류의 확률이 한꺼번에 생깁니다. 작은 예로 확인합니다. 앞 토큰이 the인지 a인지, 다음 토큰이 cat·dog·car 중 무엇인지를 재는 표입니다.
cat |
dog |
car |
행 합 | |
|---|---|---|---|---|
the |
0.30 | 0.20 | 0.10 | 0.60 |
a |
0.12 | 0.08 | 0.20 | 0.40 |
| 열 합 | 0.42 | 0.28 | 0.30 | 1.00 |
칸 하나하나가 결합확률입니다 — 두 사건이 함께 일어날 확률이고 처럼 적습니다. 여섯 칸의 합이 1인 것이 공리 2입니다.
가장자리의 합이 주변확률입니다. 한쪽 변수를 «신경 쓰지 않고» 지워 버린 확률이고, 지우는 방법은 그 변수의 모든 값에 대해 더하는 것입니다.
이 조작을 주변화라고 부릅니다. 이름이 «주변»인 이유가 그림 그대로입니다 — 표의 가장자리(margin)에 적히는 값이라서입니다. 표에서 이고, 이 값이 다음 토큰이 무엇이든 상관없이 앞 토큰이 the일 확률입니다.
조건부확률은 «앞 토큰이 the라고 이미 알고 있을 때» 다음 토큰의 확률입니다.
분모가 하는 일이 핵심입니다. the인 행만 남기면 세 값의 합이 0.60이라 더는 확률이 아닙니다 — 공리 2가 깨집니다. 그래서 0.60으로 나누어 다시 1로 맞춥니다.
조건을 건다는 것은 표본공간을 잘라 낸 뒤 남은 것을 다시 1로 정규화하는 일입니다. 언어모델이 문맥을 받아 분포를 내놓는 장면이 정확히 이것입니다 — 문맥이 표본공간을 자르고, softmax가 정규화를 맡습니다.
정의의 분모를 넘기면 곱셈 규칙이 나옵니다. 이 글의 나머지가 전부 이 한 줄에서 나옵니다.
주변화에 이 곱셈 규칙을 넣으면 주변확률을 조건부만으로 적을 수 있습니다.
이것을 전확률 법칙이라고 합니다. « 가 나올 전체 확률은 각 경우에서 나올 확률을 그 경우의 확률로 가중평균한 것»이라는 뜻입니다. 표에서 로 열 합과 같습니다.
조건부는 대칭이 아닙니다. 인데 입니다. 같은 칸 0.30을 서로 다른 것으로 나누었으니 당연한 일인데, 이 둘을 섞어 읽는 실수가 흔합니다 — «the 다음에 cat이 올 확률»과 «cat 앞에 the가 있었을 확률»은 다른 질문입니다. 두 값을 잇는 다리가 다음 절입니다.
독립 — 조건이 아무것도 바꾸지 않을 때
이면, 즉 를 알아도 의 분포가 그대로이면 두 사건이 독립이라고 합니다. 곱셈 규칙에 넣으면 익숙한 모양이 됩니다.
독립은 양쪽에서 동시에 성립합니다. 이면 곱셈 규칙을 거꾸로 써서 도 따라 나오기 때문입니다. « 가 를 알려 주지 않는다»와 « 가 를 알려 주지 않는다»는 같은 말입니다.
위 표는 독립이 아닙니다. 인데 이니 조건이 값을 바꿉니다. 자연어가 독립이 아니라는 것이 언어모델이 존재하는 이유입니다 — 토큰이 서로 독립이었다면 문맥을 볼 필요가 없고, 어휘의 빈도표 하나로 끝났을 것입니다.
베이즈 규칙 — 방향을 뒤집기
곱셈 규칙은 두 방향으로 쓸 수 있습니다. 는 어느 쪽을 먼저 조건으로 두든 같은 값이므로
이고, 양변을 로 나누면 베이즈 규칙입니다.
네 자리에 각각 이름이 있습니다.
| 자리 | 이름 | 뜻 |
|---|---|---|
| 사전확률 | 관측 전에 에 대해 알던 것 | |
| 가능도 | 가 참이라면 가 나올 법한 정도 | |
| 사후확률 | 를 보고 난 뒤의 | |
| 증거 | 관측이 나올 전체 확률. 정규화 상수 |
표로 확인합니다. cat이 나왔다는 것만 알 때 앞 토큰이 the였을 확률은 얼마일까요.
사전확률 0.60이 관측 하나로 0.714까지 올라갔습니다. cat은 the 쪽에서 더 잘 나오는 토큰이라 증거가 그 방향으로 밀어 준 것입니다.
분모는 사실 계산할 필요가 없을 때가 많습니다. 는 분자를 모든 에 대해 더한 값과 같기 때문입니다 — 로 실제로 그렇습니다. 그래서 사후확률을 여러 후보에 대해 비교만 할 때는 분자만 계산하고 마지막에 합으로 나누면 됩니다. 이 «비례식 + 정규화» 패턴은 확산 모델의 역과정처럼 사후분포를 다루는 자리마다 반복해서 나옵니다.
연쇄법칙 — 곱셈 규칙을 계속 쓰기
이제 자리를 셋으로 늘립니다. 곱셈 규칙을 한 번 쓰면
이고, 남은 에 한 번 더 쓰면
입니다. 자리가 개여도 똑같이 번 반복하면 되고, 결과가 확률의 연쇄법칙입니다.
는 번째보다 앞에 있는 토큰 전부를 뜻하고, 일 때는 조건이 비어 있어 그냥 입니다.
여기에는 가정이 하나도 들어가지 않았습니다. 독립도 마르코프 성질도 쓰지 않았고, 조건부의 정의를 반복했을 뿐입니다. 그래서 이 등식은 어떤 결합분포에서도 참이고, 자리를 어떤 순서로 늘어놓아도 참입니다 — 뒤에서 앞으로 분해해도 등식은 성립합니다.
가정이 들어가는 것은 그다음 단계입니다. 조건 를 최근 개로 잘라
로 두면 -그램 모델이 되고, 이 자르기를 마르코프 가정이라고 합니다. 여기서 등호가 근사로 바뀝니다 — 연쇄법칙은 등식이고, 근사는 조건을 자를 때 들어옵니다. 트랜스포머가 하는 일은 이 자르기를 되돌려 조건을 문맥 전체로 되돌려놓는 것입니다.
자기회귀 모델이 하는 일이 이 분해다
이제 처음 질문에 답할 수 있습니다. 언어모델은 연쇄법칙의 오른쪽 항 하나를 근사하는 함수입니다.
그리고 문장 전체의 확률은 그 항들을 곱한 것 — 연쇄법칙이 그렇게 하라고 말해 주었습니다. 지난 글의 결론을 여기에 붙이면 곱은 합이 됩니다.
이 합이 로그가능도이고, 부호를 뒤집어 토큰 수로 나눈 것이 언어모델의 학습 손실입니다. 모델이 토큰 하나짜리 분포만 내놓아도 문장 확률을 말할 수 있는 근거가 전부 여기에 있습니다.
세 토큰으로 한 번 세어 봅시다. 모델이 순전파 세 번에서 이런 값을 내놓았다고 하면
문장의 확률은 입니다. 세 번의 순전파에서 각각 한 항씩 받아 곱한 것이고, 그 이상은 아무것도 하지 않았습니다.
여기서 한 가지가 눈에 띕니다. 항이 전부 1 이하라 문장이 길어질수록 확률은 반드시 작아집니다. 긴 문장이 짧은 문장보다 «덜 그럴듯한» 것이 아니라, 자리가 많으면 그만큼 곱이 늘어나기 때문입니다. 그래서 길이가 다른 후보를 비교할 때는 로그가능도를 토큰 수로 나눈 «토큰당 평균»을 씁니다. 빔서치의 길이 정규화가 그것이고, 이 평균값을 다루는 지표는 「중급 26번 · 엔트로피와 퍼플렉서티」가 맡습니다.
두 가지가 따라옵니다.
하나, 인과 마스크는 선택이 아니라 필수입니다. 번째 항은 만 조건으로 받아야 합니다. 어텐션이 뒤쪽 토큰을 보게 두면 가 아니라 다른 값을 계산하는 것이고, 곱해 봐야 문장의 확률이 되지 않습니다. 트랜스포머 디코더의 삼각 마스크는 연쇄법칙의 조건 부분을 코드로 옮긴 것입니다.
둘, 생성은 이 분해를 왼쪽부터 채우는 일입니다. 을 뽑고, 그것을 조건에 넣어 를 뽑고, 반복합니다. 매 단계에서 뽑는 대상이 정확히 연쇄법칙의 한 항입니다. 학습과 생성이 같은 식의 양쪽 방향인 셈입니다.
import numpy as np
# 문장 하나의 로그가능도 — 연쇄법칙의 항을 그대로 더한다
logprobs = np.array([-0.11, -2.31, -0.02, -1.20, -3.50])
print(logprobs.sum()) # -7.14
print(np.exp(logprobs.sum())) # 0.000793
정리
- 확률의 공리는 셋뿐이다 — 음수 없음, 전체가 1, 배반이면 덧셈. 나머지는 전부 여기서 나온다.
- 조건을 건다는 것은 표본공간을 자른 뒤 다시 1로 정규화하는 일이다. 분모 가 그 정규화를 맡는다.
- 주변화는 신경 쓰지 않는 변수를 더해서 지우는 것이다. 표의 가장자리 합이 그 값이다.
- 베이즈 규칙은 곱셈 규칙을 두 방향으로 쓴 것이다. 사전·가능도·증거·사후가 각각의 자리를 차지하고, 증거는 분자를 전부 더한 값이라 비교만 할 때는 미뤄 둘 수 있다.
- 연쇄법칙에는 가정이 없다. 조건부의 정의를 번 반복한 항등식이라 어떤 분포에서도 성립한다.
- 자기회귀 분해가 그 연쇄법칙 자체다. 모델은 항 하나를 근사하고, 인과 마스크가 조건 부분을 지키고, 로그를 씌우면 합이 되어 손실이 된다.
문장 하나짜리 분포에서 시작해 문장 전체의 확률까지 왔습니다. 그런데 아직 «확률이 붙은 결과»만 다루었을 뿐, 그 결과에 수를 붙여 평균을 내는 일은 하지 않았습니다. 다음 글은 확률변수와 기댓값을 세워 «손실은 데이터 분포 위의 기댓값»이라는 문장을 실제로 계산할 수 있게 만듭니다.
읽어주셔서 감사합니다. 😊

