GPT가 하는 일의 본질은 1948년 섀넌(Shannon)이 종이와 연필로 하던 것과 같다 — 지금까지의 글을 보고 다음에 올 것의 확률을 구하는 것. n-gram은 그 가장 단순한 구현이다. 그냥 센다. 이 페이지의 모든 데모는 외부 라이브러리 없이 브라우저에서 직접 실행된다. 코퍼스를 직접 고쳐 가며 만져보자.
"나는 커피를 ___" 다음에 올 단어는? "마셨다"일 확률이 높고 "던졌다"일 확률은 낮으며 "파랗다"일 확률은 거의 0이다. 사람은 이걸 직관으로 안다. 언어 모델(language model)은 이 직관을 확률 분포로 만든 것이다: 지금까지의 단어열이 주어졌을 때 다음 단어의 확률 P(wt | w1, …, wt−1).
문장 전체의 확률은 연쇄 법칙(chain rule)으로 다음 단어 확률들의 곱이 된다. 문제는 조건부의 "지금까지의 모든 단어"가 너무 길다는 것 — 똑같은 20단어 문맥을 두 번 보는 일은 거의 없으므로 확률을 추정할 수 없다. n-gram의 답은 과감한 근사다: 직전 n−1개 단어만 보자 (마르코프 가정).
이때 연속된 n개의 토큰 묶음을 n-gram이라 부른다. 모델을 만들기 전에, 문장이 n-gram으로 어떻게 쪼개지는지부터 눈으로 보자.
문장을 넣고 n을 바꿔 보자. 창(window)이 한 칸씩 미끄러지며 n-gram을 뽑아낸다. 아래 n-gram을 클릭하면 해당 창이 강조된다.
확률은 어디서 오는가? 코퍼스(corpus), 즉 훈련 텍스트에서 그냥 센다. 바이그램이라면 "나는" 뒤에 어떤 단어가 몇 번 왔는지 세고, "나는"이 나온 총 횟수로 나눈다. 이것이 최대 우도 추정(MLE, maximum likelihood estimate)이다.
아래 코퍼스는 직접 수정할 수 있다. 한 줄이 한 문장이다. 문장을 추가하거나 지우면 이 페이지의 모든 데모(생성기, 희소성, 스무딩, 퍼플렉시티)가 즉시 다시 계산된다.
행 = 앞 단어(문맥), 열 = 다음 단어. 셀 색이 진할수록 자주 등장한 조합이다. 행 머리글을 클릭하면 그 문맥의 조건부 확률 분포가 아래에 그려진다.
확률 분포가 있으면 샘플링으로 텍스트를 만들 수 있다. <s>에서 시작해 분포에서 다음 단어를 하나 뽑고, 그 단어를 문맥에 넣어 또 뽑고… </s>가 나올 때까지 반복한다. 섀넌은 1948년 논문에서 이걸 손으로 했다 — 책을 아무 데나 펴서 마지막 단어를 찾고, 그 다음 단어를 받아 적는 식으로. 그렇게 만든 문장이 n이 커질수록 점점 영어처럼 보인다는 것이 논문의 유명한 시연이다.
위(§2)의 코퍼스로 학습된 모델이다. n을 바꿔 가며 생성해 보자. 각 스텝에서 모델이 실제로 본 확률 분포가 오른쪽에 표시된다 — ■ 이 선택된 단어다.
문맥을 길게 볼수록(n↑) 예측은 정확해져야 한다. 그런데 현실에서는 어느 지점부터 오히려 망가진다. 어휘가 V개면 가능한 n-gram 조합은 Vn개 — n이 하나 늘 때마다 경우의 수가 V배씩 지수적으로 폭발하는데, 코퍼스 크기는 그대로이기 때문이다. 대부분의 조합은 코퍼스에 한 번도 등장하지 않고, 카운트가 0이면 MLE 확률도 0이다.
확률 0은 치명적이다. 문장 확률은 곱이므로 0이 하나라도 끼면 문장 전체가 확률 0이 되고, 퍼플렉시티는 무한대가 된다. 멀쩡한 문장인데 훈련 때 그 조합을 못 봤다는 이유만으로.
§2 코퍼스의 문장을 절반은 훈련용, 절반은 테스트용으로 나눴다. 테스트 문장 속 n-gram 중 훈련 쪽에서 한 번도 못 본 비율이다. 코퍼스를 수정하면 다시 계산된다.
해결책은 확률을 조금씩 걷어서 못 본 조합에 나눠주는 것, 스무딩(smoothing)이다. 가장 단순한 방법은 모든 카운트에 k를 더해 주는 애드-k(라플라스) 스무딩:
문맥 하나를 골라 k를 움직여 보자. 관측된 단어(카운트>0)의 확률이 깎이고, 그만큼이 관측 안 된 단어들에 배분된다.
애드-k는 이해하기 쉽지만 실전에서는 확률을 너무 뭉개서 성능이 나쁘다. 실제 시스템들은 더 영리한 방법을 썼다:
어느 모델이 더 좋은가를 어떻게 잴까? 테스트 문장에 높은 확률을 주는 모델이 좋은 모델이다. 이를 문장 길이에 무관하게 정규화한 것이 퍼플렉시티(perplexity, PPL)다.
§2 코퍼스로 학습한 유니그램/바이그램/트라이그램 모델(애드-k 스무딩)이 아래 테스트 문장을 평가한다. 코퍼스에 있는 문장, 새로 조합한 문장, 엉터리 문장을 넣어 비교해 보자.
n-gram의 한계는 셋으로 요약된다. 첫째, 희소성 — n을 키울수록 카운트 표가 빈다(§4). 둘째, 일반화 불가 — "고양이는 물을 마신다"를 아무리 봐도 "강아지는 물을 마신다"의 확률은 1도 오르지 않는다. n-gram에게 단어는 서로 무관한 기호일 뿐, "고양이와 강아지는 비슷하다"는 개념이 없다. 셋째, 짧은 기억 — n−1 단어 밖의 문맥은 원리적으로 볼 수 없다.
2003년 Bengio의 신경망 언어 모델(NPLM)이 두 번째 문제를 정면으로 돌파했다. 단어를 기호가 아니라 연속 벡터(임베딩)로 표현하면, 비슷한 단어는 비슷한 벡터를 갖게 되어 본 적 없는 조합에도 확률이 번져 나간다. RNN(→ RNN 노트)은 세 번째 문제를, Transformer는 그 확장성을 해결했다.
그러나 목표 함수는 한 번도 바뀐 적이 없다. GPT의 사전학습도 정확히 "다음 토큰의 확률을 맞혀라"이고, 성적표도 여전히 퍼플렉시티 계열이다. n-gram을 이해하면 LLM이 무엇을 하도록 훈련되는지를 이해한 것이다.
| n-gram | 신경망 언어 모델 (NPLM → GPT) | |
|---|---|---|
| 목표 | 다음 토큰의 확률 분포 P(wt | 문맥) — 동일 | |
| 확률을 구하는 방법 | 카운트 표에서 조회 | 파라미터화된 함수(신경망)가 계산 |
| 단어의 표현 | 서로 무관한 원자 기호 | 임베딩 벡터 — 유사성이 거리로 표현됨 |
| 못 본 조합 | 확률 0 (스무딩으로 땜질) | 비슷한 조합에서 일반화 |
| 문맥 길이 | n−1 단어, 고정 | RNN: 이론상 무제한 · Transformer: 수십만 토큰 |
| 학습 | 세기 (한 번 훑으면 끝) | 경사 하강법 |
핵심을 7문제로 확인하자. 답을 고르면 즉시 해설이 보인다. — 0 / 7