언어 모델(Language Model)은 연속된 단어(token)의 시퀀스에 확률을 할당(assign)하는 모델이다. 언어 모델은 크게 통계적 모델과 인공 신경망 모델로 구분할 수 있는데, 최근에는 본 포스트에서 언급한 희소 문제를 해결하며 훨씬 좋은 성능을 보여주는 인공 신경망 모델이 주로 사용된다. 본 포스트에서는 통계적 언어 모델(Statistical Language Model, SLM)에 대하여 알아보고, nltk를 이용하여 이를 구현한다.
조건부 확률은 어떤 사건이 일어나는 경우에 다른 사건이 일어날 확률을 말하며, 사건 와 사건 에 대해 다음과 같이 표현된다.
위의 식에서 다음과 같은 식을 도출할 수 있다.
이를 개의 사건에 대해 일반화해 보자. 사건 에 대해 다음이 성립한다는 것을 귀납적으로 쉽게 추론할 수 있다.
이렇게 일반화된 결과를 조건부확률의 연쇄법칙(Chain Rule for Conditional Probability)라고 한다.
조건부확률을 이용하여 문장에 대한 확률을 나타내 보자. 단어 으로 이루어진 문장 에 대한 확률을 다음과 같이 나타낼 수 있다.
예를 들어, 문장 'A little boy smiles'의 확률을 식으로 표현하면 다음과 같다.
즉, 문장의 확률은 각 단어에 대한 예측 확률을 곱하여 나타낼 수 있다.
SLM의 가장 기본적인 접근 방식은 이전 단어로부터 다음 단어에 대한 확률을 구할 때 카운트(코퍼스에서 해당 시퀀스가 등장한 횟수)에 기반하여 확률을 계산한다. 예를 들어, 'A little boy'라는 시퀀스가 주어졌을 때, 'smiles'가 나올 확률인 을 다음과 같이 계산한다.
언어 모델의 목표는 기계에게 많은 코퍼스를 학습시켜 실제 자연어에서의 확률 분표를 근사하는 것이다. 그러나, 카운트 기반으로 접근하려면 기계가 훈련하는 데이터의 양에 한계가 있다. 위에서 제시한 예시 문장을 다시 보자. 를 구하는 경우에, 기계가 훈련한 코퍼스에 'A little boy smiles'라는 단어 시퀀스가 없었다면, 해당 확률은 0이 된다. 또 'A little boy'라는 시퀀스가 없었다면 분모가 0이 되어 확률이 정의되지 않는다. 언어의 창조성에 의해, 자연어에서 발생할 수 있는 단어 시퀀스는 무한하다. 카운트 기반의 접근 방식을 취할 경우, 코퍼스의 크기가 유한하기 때문에 한 언어의 모든 상황에 대해 학습시킬 수 없고, 이에 따라 언어를 정확히 모델링할 수 없다. 이와 같이 충분한 데이터를 관측하지 못하여 언어를 정확히 모델링할 수 없는 문제를 희소 문제(Sparsity Problem)이라고 한다. 해당 문제를 해결하기 위하여 n-gram 모델이 제안되었다.
Markov Chain 또는 Markov Process는 Marcov Property를 지니는 이산확률과정이다. Markov Property의 핵심은 과거 상태들과 현재 상태가 주어졌을 때, 미래 상태는 과거 상태와는 독립적으로 현재 상태에 의해서만 결정된다는 것을 의미한다. 이를 식으로 나타내면 다음과 같다.
Markov Property를 가진 이산확률과정에서, 알고 있는 자료로 미래의 변화를 예측하는 데에는 다음과 같은 식을 사용할 수 있다.
이때 는 각 열의 합이 1인 확률행렬이고, 는 시간이 일 때의 상태를 나타내는 행렬이다.
n-gram 언어 모델은 여전히 카운트에 기반한 통계적 접근을 사용하고 있으나, 문장이 Markov Property를 가진다고 가정하여 이전에 등장한 모든 단어를 고려하지 않고 일부 단어만을 고려하는 접근 방식을 사용한다. 예를 들어, 'A little boy'라는 시퀀스가 주어졌을 때, 와 같이 근사하는 것이다. 이렇게 하면 코퍼스에서 해당 단어의 시퀀스를 카운트할 확률이 높아진다.
n-gram은 개의 연속적인 단어 나열을 의미하며, n-gram Language Model에서는 코퍼스에서 개의 단어 시퀀스를 하나의 토큰으로 간주한다. 이때 인 경우 unigram, 일 경우 bigram, 일 경우 trigram으로 명명한다. 인 경우 gram 앞에 숫자를 그대로 붙여 명명한다.
nltk에서 제공하는 Brown 코퍼스를 이용하여 모델을 학습시키고, bigram을 이용하여 문장의 확률을 계산하도록 하였다. 코퍼스 내에 bigram이 없다면 unigram을 이용하도록 하였다.
import nltk
from nltk.corpus import brown
from collections import Counter
def ngram(tokens, n):
return list(zip(*[tokens[i:] for i in range(n)]))
corpus = brown.sents()
tokens = [token.lower() for sent in corpus for token in sent]
unigram_counts = Counter(ngram(tokens, 1))
bigram_counts = Counter(ngram(tokens, 2))
total_count = len(tokens)
unigram_probs = {unigram: count/total_count for unigram, count in unigram_counts.items()}
bigram_probs = {bigram: count/unigram_counts[bigram[:1]] for bigram, count in bigram_counts.items()}
def sentence_prob(sentence):
tokens = nltk.word_tokenize(sentence.lower())
bigrams = ngram(tokens, 2)
prob = 1
for bigram in bigrams:
if bigram in bigram_probs:
prob *= bigram_probs[bigram]
else:
prob *= unigram_probs[(bigram[1],)]
return prob
'An adorable little boy is spreading smiles'라는 문장을 생각해 보자. 'An adorable little boy is spreading'이 주어져 있고, 그 다음 단어를 예측하려고 한다. 4-gram을 이용하면, spreading 다음에 올 단어 는 다음 확률을 이용하여 예측할 수 있다.
학습시킨 코퍼스에서 'boy is spreading'이라는 시퀀스가 1000번 등장했다고 가정하자. 그리고 'boy is spreading insults'와 'boy is spreading smiles'가 각각 500번, 200번 등장했다고 가정하자. 이 경우 가 insults일 확률은 50%이고, smiles일 확률은 20%가 된다. 확률적 선택에 따라, 모델은 라고 판단할 것이다.
해당 선택은 문장 전체를 보고 판단하는 우리 인간으로 하여금 의문이 들게 한다. 이 언어 모델은 'boy is spreading'의 앞에 있던 'an adorable little'이라는 시퀀스를 제거하고 반영하지 않았다. 그러나 해당 수식어를 반영하여 판단하는 우리에게 '작고 사랑스러운 소년이' 하는 행동이 '웃음 지었다' 대신 '모욕을 퍼트렸다'가 선택된 것은 이상하게 보인다. 요점은, n-gram 모델에서는 매우 제한적인 단어 시퀀스만이 예측에 반영되기 때문에 한 문장 안에서도 위의 예시와 같이 문맥이 전혀 맞지 않는 문장이 생성될 수가 있다. 즉, 전체 문장을 고려한 언어 모델보다 훨씬 정확도가 떨어진다.
물론, 의 크기를 늘릴 경우 문맥을 더 잘 반영하여 더 높은 정확도로 문장을 예측할 수 있다. 자료 [1]의 9페이지에 제시된 표에 따르면, 이 커질수록 perplexity가 낮아지는 것을 확인할 수 있다. 다만, 이 커지면 모델 사이즈가 커지고 희소 문제가 심각해진다. 즉, n을 선택하는 것은 trade-off 문제이다. 희소 문제를 해결하기 위해 자료 [1]의 3-5절에서 설명하는 것과 같은 Smoothing 기법을 사용할 수 있으나, 근본적인 해결책은 아니다.
SLM은 그 방식이 매우 간단하지만, 희소 문제와 같은 치명적인 취약점을 가진다. 따라서 최근에는 대부분의 경우에 더 나은 성능을 보이는 인공 신경망을 이용한 언어 모델이 주로 사용된다.
[1] D. Jurafsky and J. H. Martin, "Chapter 3: N-gram Language Models" in Speech and Language Processing. Pearson.
[2] 유원준 & 안상준, "Chapter 3: 언어 모델" in 딥 러닝을 이용한 자연어 처리 입문. Wikidocs.
[3] 김창일 외, "VII-2: 마르코프 체인 문제" in 고급 수학 II. 전라북도교육청.