지난 글에서는 가장 단순한 통계적 언어 모델인 **유니그램(Unigram)**과 **바이그램(Bigram)**에 대해 살펴보았습니다.
이번에는 **2개의 문자를 참조하여 다음 문자를 예측하는 트라이그램(Trigram)**에 대해 학습하겠습니다.
또한, 문맥이 길어질수록 예측이 어떻게 달라지는지 살펴보고, N-gram 모델이 가진 근본적인 한계까지 이해해 나갈 것입니다.
지난 글에서 확인했던 유니그램과 바이그램의 차이는 단순했습니다.
유니그램은 1개의 문자 출현 빈도만을 이용하고, 바이그램은 직전 문자에 따라 다음 문자의 확률을 다른 방식으로 계산했습니다.
그렇다면 직전 1문자가 아니라 2문자를 기억한다면 어떨까요?
**트라이그램(Trigram)**은 N-gram에서 N = 3인 경우입니다. 연속된 3개의 문자를 하나의 조합으로 취급합니다.
지난 글의 내용을 정리하면 다음과 같습니다:
| 이름 | N | 다음 문자를 예측할 때 참조하는 문맥 |
|---|
| 유니그램 (Unigram) | 1 | 이전 문자를 참조하지 않음 |
| ... | | |
트라이그램을 언어 모델로 활용하는 방법은 바이그램과 크게 다르지 않습니다.
학습 데이터로부터 연속된 3개의 문자 출현 횟수를 세고, 앞의 2문자가 주어졌을 때 3번째 문자가 나타날 조건부 확률을 계산하면 됩니다.
예를 들어, MAM이라는 트라이그램이 있다면, 앞의 2문자 MA가 나타났을 때 다음 문자로 M이 나왔다는 것을 의미합니다.
그럼 실제 데이터를 사용해서 살펴보겠습니다.
이번에도 지난 글에서 사용했던 세 단어를 학습 데이터로 사용하겠습니다.
먼저, MAMMAL에 **3문자 크기의 창(window)**을 두고 오른쪽으로 1글자씩 이동시킵니다.
Step 1 [MAM]MAL
Step 2 M[AMM]AL
Step 3 MA[MMA]L
...
바이그램에서 사용했던 슬라이딩 윈도우와 같은 방식입니다. 다만, 이번에는 창의 크기가 2문자에서 3문자로 늘어났습니다.
나머지 두 단어에도 동일한 처리를 적용하면 다음과 같습니다:
| 학습 단어 | 추출된 트라이그램 |
|---|
MAMA | MAM, AMA |
MAMMAL | MAM, AMM, MMA, MAL |
MAMMOTH | MAM, AMM, MMO, MOT, OTH |
길이가 k인 단어에서 3문자씩 추출하면, k - 2개의 트라이그램을 얻게 됩니다.
따라서 이번 학습 데이터에서 추출되는 트라이그램의 수는 다음과 같습니다.
MAMA: 4 - 2 = 2개 -
MAMMAL: 6 - 2 = 4개 -
MAMMOTH: 7 - 2 = 5개
총 11개의 트라이그램이 추출됩니다.
그럼, 중복되는 트라이그램도 빠짐없이 세어보겠습니다.
| 트라이그램 | 출현 횟수 |
|---|
MAM | 3 |
AMA | 1 |
AMM | 2 |
MMA | 1 |
MAL | 1 |
MMO | 1 |
MOT | 1 |
OTH | 1 |
| 합계 | 11 |
여기서 MAM은 세 단어 모두에 나타났으므로 3번, AMM은 MAMMAL과 MAMMOTH에 나타났으므로 2번입니다.
나머지 트라이그램은 각각 1번씩 나타났습니다.
여기까지의 과정은 유니그램이나 바이그램과 크게 다르지 않습니다.
이번에는 모델이 MA라는 2문자를 출력한 상태라고 가정해 봅시다.
트라이그램은 직전 2문자를 참조하므로, 학습 데이터에서 MA로 시작하는 트라이그램을 찾으면 됩니다.
| 조합 | 출현 횟수 | MA 다음 문자로 선택될 확률 |
|---|---|
MAM | 3 | 3/4 = 75% |
MAL | 1 | 1/4 = 25% |
| 합계 | 4 | 100% |
도식으로 표현하면 다음과 같습니다.
┌── M 75% (3회)
Current Context MA ────┤
└── L 25% (1회)
이 모델에서는, MA 다음에 M이 올 확률은 75%, L이 올 확률은 25%입니다.
여기서, 하나의 의문이 생길 수도 있습니다.
지난 기사에서는 MA라는 바이그램이 총 5번 나타났음에도 불구하고, 왜 이번에는 4번만 계산했는지 궁금하실 겁니다.
그 이유는 MAMA의 마지막 두 글자인 MA 뒤에는 더 이상 문자가 없기 때문입니다.
이번 예시에서는 단어의 시작과 끝을 나타내는 경계 기호(boundary marker)를 사용하지 않았기 때문에, 실제로 다음 문자가 존재하는 경우에만 계산합니다.
즉, MA 다음에 올 문자를 예측할 때 사용하는 관측 횟수의 합은 4번입니다.
이번에는 AM과 MM이라는 두 가지 문맥을 비교해 보겠습니다.
두 문맥 모두 마지막 글자가 M이라는 공통점이 있습니다. 하지만 바이그램 모델은 바로 직전의 문자(M)만 참조하기 때문에, 이 둘을 구별할 수 없습니다.
하지만 트라이그램은 앞의 두 문자를 참조하므로, 각각 다른 확률 분포를 사용할 수 있습니다.
먼저, AM 다음에 올 문자를 살펴보겠습니다.
| 조합 | 출현 횟수 | 선택 확률 |
|---|
AMA | 1 | 1/3 ≈ 33.3% |
AMM | 2 | 2/3 ≈ 66.7% |
반면, MM 다음에 올 문자의 확률은 다음과 같습니다.
| 조합 | 출현 횟수 | 선택 확률 |
|---|
MMA | 1 | 1/2 = 50% |
MMO | 1 | 1/2 = 50% |
요약하면 다음과 같습니다.
현재 문맥 AM
├── A 33.3%
└── M 66.7%
...
AM과 MM은 둘 다 M으로 끝나지만, 다음에 올 문자의 확률은 다릅니다.
바이그램이 직전의 한 문자를 기억했다면, 트라이그램은 직전의 두 문자를 기억함으로써 더 구체적인 문맥을 반영할 수 있습니다.
그럼 학습한 트라이그램을 사용해서 실제로 문자열을 생성해 보겠습니다.
시작 시점의 문맥은 MA라고 가정합니다. 첫 번째 예측에서는 MA 다음에 올 문자를 선택해야 합니다.
확률에 따라 M이 선택되었다고 가정하면, 생성된 문자열은 다음과 같습니다.
그럼 다음 문자를 생성할 때는 어떻게 해야 할까요?
트라이그램은 항상 가장 최근의 두 문자를 참조합니다. 따라서 MAM 전체를 사용하는 것이 아니라, 마지막 두 문자(AM)를 사용합니다.
생성 결과: MAM
현재 문맥: AM
A: 33.3%
...
이번에도 M이 선택되었다고 가정하면 다음과 같습니다.
여기서 가장 최근의 두 문자는 MM입니다.
생성 결과: MAMM
현재 문맥: MM
A: 50%
...
여기서 O가 선택되면, 결과는 다음과 같습니다.
이 과정을 반복하면 다음과 같은 문자열을 만들 수 있습니다.
시작 MA
Step 1 MAM
Step 2 MAMM
...
학습 데이터로 사용된 MAMMOTH가 생성되었습니다. 물론, 이것은 모델이 MAMMOTH라는 단어의 의미를 이해했다는 뜻은 아닙니다.
단지 학습 데이터에서 관측된 3글자의 연결에 따라 문자를 생성했을 뿐입니다.
트라이그램이 반드시 학습한 단어만을 생성하는 것은 아닙니다. 예를 들어, 다음과 같은 문자열도 생성할 수 있습니다.
이 문자열은 원래의 학습 데이터에는 없었습니다. 하지만, 이 문자열을 3글자씩 끊으면 다음과 같습니다.
위 트라이그램들은 모두 학습 데이터에 1회 이상 나타난 조합입니다.
즉, 트라이그램 모델은 학습한 3글자의 조합을 연결하여, 학습 데이터에는 없던 문자열을 생성할 수 있습니다.
유니그램(Unigram)으로 우연히 새로운 문자 조합이 만들어진 것과 유사하지만, 중요한 차이가 있습니다.
유니그램은 각 문자를 독립적으로 선택하는 반면, 트라이그램은 직전의 두 문자에 연결되는 문자만 선택합니다. 따라서 이전보다 학습 데이터의 문자 배열을 더 잘 반영한 문자열을 생성할 수 있습니다.
다만, 이것만으로 자연스러운 단어나 문장이 만들어진다고는 할 수 없습니다.
지금까지 살펴본 트라이그램은 바이그램보다 많은 문맥을 참조할 수 있었습니다. 그럼, N
이 크기를 계속 키운다면, 언젠가 완벽한 언어 모델을 만들 수 있을까요?
안타깝게도, 그렇게 간단하지는 않습니다.
N-gram은 문맥(context)이 길어질수록 새로운 문제에 직면합니다.
트라이그램(Trigram)은 다음 글자를 예측할 때 직전의 2글자만 사용합니다.
예를 들어, 다음 두 문자열을 생각해 봅시다.
두 문자열의 길이는 다르지만, 마지막 2글자는 둘 다 MM입니다.
따라서 트라이그램 모델은 두 경우 모두 완전히 동일한 확률 분포를 사용합니다.
MAMM → 다음 글자 예측
MM → A 50%, O 50%
MAMMAMM → 다음 글자 예측
...
모델은 MM 앞에 어떤 글자가 있었는지를 고려하지 않습니다.
즉, 이전에 얼마나 많은 글자가 나타났든 상관없이, 마지막 2글자가 같다면 동일한 예측을 수행하는 것입니다.
이러한 특성은 N-gram 언어 모델의 **제한된 문맥 길이(limited context length)**라고 생각할 수 있습니다.
바이그램에서는 1글자, 트라이그램에서는 2글자, 그리고 N-gram에서는 최대 N - 1개의 직전 글자를 사용합니다.
물론, N을 크게 하면 더 많은 문맥을 참조할 수 있습니다.
하지만 그 과정에서 또 다른 문제가 발생합니다.
이번에 사용한 학습 데이터에서 추출한 N-gram의 개수를 비교해 봅시다.
| 모델 | N | 추출된 조합의 총수 |
|---|
| 유니그램 | 1 | 17 |
| ... | | |
| 여기서, 조합의 총수란 중복을 포함하여 추출된 모든 조합의 수입니다. | | |
창(window)의 크기가 커질수록, 하나의 단어에서 추출할 수 있는 조합의 개수는 줄어듭니다.
더 중요한 것은, 가능한 조합의 종류는 오히려 급격하게 늘어난다는 점입니다.
예를 들어, 알파벳을 26글자 사용한다고 가정해 봅시다.
| N | 가능한 글자의 조합 수 |
|---|
| 1 | 26 |
| ... | |
| 가능한 조합의 수는 다음과 같이 계산할 수 있습니다. | |
[$ ext{26}^N$]
이것은 26글자를 사용하여 만들 수 있는 길이 N의 모든 조합을 계산한 것입니다.
물론, 실제 영어에서 모든 조합이 사용되는 것은 아닙니다.
하지만, N이 커질수록 학습 데이터에서 관찰해야 할 조합의 종류가 늘어난다는 점은 변하지 않습니다.
예를 들어, N = 5인 경우, 가능한 조합은 약 1,188만 개입니다.
학습 데이터가 충분하지 않으면, 그중 상당수는 한 번도 나타나지 않을 수 있습니다.
이처럼, 문맥이 길어질수록 각 조합에 대한 관측 데이터가 부족해지는 문제를 **데이터의 희소성(Data sparsity)**이라고 부릅니다.
이 문제를 좀 더 구체적으로 살펴보겠습니다.
학습된 트라이그램은 다음과 같았습니다.
MAM, AMA, AMM, MMA,
MAL, MMO, MOT, OTH
그런데 모델에 LA라는 문맥이 주어졌다고 가정해 봅시다. 학습 데이터에는 LA로 시작하는 트라이그램이 한 번도 나타나지 않았습니다.
현재 문맥: LA
LA? → 관찰된 조합 없음
따라서 이 단순한 카운트 기반 모델로는 다음 글자의 확률 분포를 계산할 수 없습니다.
그렇다고 해서 해결 방법이 전혀 없는 것은 아닙니다.
예를 들어, 트라이그램에서 필요한 통계가 발견되지 않으면 바이그램을 사용하거나, 관찰되지 않은 조합에도 작은 확률을 부여하는 방법이 있습니다.
이러한 방법들은 각각 **백오프(Backoff)**와 **스무딩(Smoothing)**이라고 불립니다.
다만, 여기서는 자세한 계산 방법까지는 다루지 않겠습니다.
중요한 것은, 문맥을 길게 기억하는 것만으로는 처음 보는 문맥을 처리하는 문제는 해결되지 않는다는 점입니다.
마지막으로, 좀 더 근본적인 문제가 있습니다.
앞서 생성했던 문자열을 다시 한번 봅시다.
이 문자열은 학습 데이터에는 존재하지 않았지만, 모든 트라이그램이 관찰된 조합이었기 때문에 생성할 수 있었습니다.
하지만 실제 영어 단어로서 자연스러운지는 별개의 문제입니다.
트라이그램 모델이 아는 것은 다음과 같은 통계뿐입니다.
MA 다음에는 M이 자주 나타난다. -
AM 다음에는 M이 자주 나타난다. -
MM 다음에는 A 또는 O가 나타난다.
이 모델은 문자가 함께 나타난 빈도만 알고 있을 뿐, 그 문자열이 실제 단어인지, 어떤 의미를 가지는지 직접 판단할 수는 없습니다.
이것은 트라이그램만의 문제는 아닙니다.
N-gram의 크기를 키우더라도, 기본적인 카운트 기반 접근 방식에서는 학습 데이터에 등장한 문자 조합의 빈도를 이용한다는 점은 같습니다.
긴 문맥에서 발생하는 통계를 더 많이 기억할 수는 있지만, 처음 보는 표현이나 복잡한 의미 관계를 일반화하는 데는 한계가 있습니다.
지금까지 유니그램부터 바이그램, 그리고 트라이그램까지 살펴보았습니다.
세 가지 모델을 비교하면 다음과 같습니다.
| 구분 | 유니그램 | 바이그램 | 트라이그램 |
|---|
| 참조하는 문맥 | 없음 | 이전 1글자 | 이전 2글자 |
| ... | | | |
지금까지 확인한 것은 다음과 같습니다.
- 문맥의 확장: 트라이그램은 이전 2글자를 참조하여 다음 글자의 확률을 계산합니다. -
- 텍스트 생성: 학습된 트라이그램을 연결하여 새로운 문자열을 생성할 수 있습니다. -
- 문맥 길이의 한계: N-gram은 최대
N - 1 개의 직전 글자만 참조합니다. -
- 데이터 희소성(Data Sparsity): 문맥이 길어질수록 관측되지 않은 조합이 늘어나 확률 계산이 어려워집니다. -
- 일반화의 한계: 단순히 출현 횟수를 기억하는 방식으로는 처음 보는 문맥이나 복잡한 의미 관계를 처리하기 어렵습니다.
여기서 중요한 의문점이 하나 남습니다.
모든 문자 조합의 출현 횟수를 직접 기억하지 않아도, 다음 문자의 확률을 예측할 수 없을까요?
예를 들어, 각 문자나 문맥을 숫자로 표현하고, 학습 데이터를 통해 다음 문자를 예측하는 규칙 자체를 학습한다면 어떨까요?
이것이 바로 앞으로 배울 신경망 언어 모델(Neural Language Model) 을 이해하기 위한 출발점입니다.