자연어처리를 위한 Language Model

아래 내용은 CS224N 2019 Lecture 6: Language Models and Recurrent Neural Networks을 참조하였습니다.


1. What is Language Model

Language Model은 언어의 확률분포를 추정하는 것을 의미합니다. 주요 Language Model의 종류는 다음과 같습니다.

  • 자동완성
    네이버 또는 구글 등의 포털에서 검색어를 입력할 때 사람들이 검색하는 확률분포에 따라 가능한 검색어를 제시하는 기능
  • 오타
    핸드폰에서 오타를 입력할 경우 언어의 확률분포에 따라 올바른 단어를 제시하는 기능
  • 사람 간의 대화
    어떤 사람의 음성을 들을 경우 불명확한 음성을 앞뒤 맥락을 이용해서 그 사람이 말한 내용을 추론하는 행위
  • 음성인식
    시리, 클로바 등 인공지능 스피커에서 사람의 음성을 인식하여 텍스트로 변환할 때 언어의 확률분포를 이용해서 추론하는 기능


두 문장 '그는 사과를 보자 배고픔을 느꼈다'와 '그는 사과를 보자 외로움을 느꼈다'의 발생확률을 비교해 보면 아래와 같다고 할 수 있습니다.

$$ p(\text{그는 사과를 보자 배고픔을 느꼈다}) > p(\text{그는 사과를 보자 외로움을 느꼈다}) $$

두 문장 중 '그는 사과를 보자 배고픔을 느꼈다'라는 문장이 일상생활에서 더 많이 사용될 만한 문장이기 때문에 발생 확률이 크다고 할 수 있습니다.

그렇지만 실제 언어의 확률분포를 아는 것은 어렵습니다.
그러므로 좋은 확률분포를 근사하는 Language Model을 학습하는 것이 목적입니다.


2. N-gram Language Model

언어의 확률분포는 많은 text로부터 얻을 수 있습니다. 문장의 확률분포의 수식은 아래와 같습니다.

$$ p(s = w^{(1)}, w^{(2)}, ..., w^{(n)}) $$

위 수식과 같이 각 단어들이 순서대로 발생할 확률을 구하면 됩니다. 'the cat slept quietly'라는 문장이 발생할 확률을 예로 들어보겠습니다.

$$ \begin{equation} \begin{split} &p(s = the \; cat \; slept \; quietly) \\ = \;&p(w^{(1)} = the, w^{(2)} = cat, w^{(3)} = slept, w^{(4)} = quietly) \\ = \; &p(quietly|the \; cat \; slept) \cdot p(slept|the \; cat) \cdot p(cat|the) \cdot p(the) \end{split} \end{equation} $$

위 수식과 같이 각 확률의 곱으로 표현할 수 있습니다.

  • 'the'가 발생할 확률
  • 'the'가 발생 후 'cat'이 발생할 확률
  • 'the cat'이 발생 후 'slept'가 발생할 확률
  • 'the cat slept'가 발생 후 'quietly'가 발생할 확률

위 내용을 간단하게 수식을 표현하면 다음과 같습니다.

$$ p(w^{(1)}, w^{(2)}, ..., w^{(n)}) = \prod_{i=1}^n p(w^{(i)}|w^{(1)}, ..., w^{(i-1)}) $$

그런데 이렇게 아주 긴 문장의 확률분포를 계산하는데 어려움이 있습니다. 그래서 다음과 같이 가정을 할 수 있습니다.

'단어의 확률분포는 고정된 몇 개의 이전 단어에 의존한다'

위 가정을 통해서 수식을 다음과 같이 단순화할 수 있습니다.

$$ p(w^{(i)} | w^{(i)}, w^{(2)}, ..., w^{(i - 1)}) \approx p(w^{(i)} | w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i - 1)}) $$

단어의 확률분포를 계산하기 위해 참고하는 단어의 개수에 따라서 아래와 같이 구분할 수 있습니다.

  • trigram: $p(w^{(i)} | w^{(1)}, w^{(2)}, ..., w^{(i - 1)}) \approx p(w^{(i)} | w^{(i-2)}, w^{(i - 1)})$
  • bigram: $p(w^{(i)} | w^{(1)}, w^{(2)}, ..., w^{(i - 1)}) \approx p(w^{(i)} | w^{(i - 1)})$
  • unigram: $p(w^{(i)} | w^{(1)}, w^{(2)}, ..., w^{(i - 1)}) \approx p(w^{(i)})$

즉 n-gram language model은 이전 n - 1 개의 단어를 참고합니다.

이와 같은 확률분포를 많은 text에서 구하는 방법에 대한 수식은 다음과 같습니다.

$$ \begin{equation} \begin{split} p(w^{(i)} | w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i - 1)}) &= {p(w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i-1)}, w^{(i)}) \over p(w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i-1)})} \\ & \approx {count(w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i-1)}, w^{(i)}) \over count(w^{(i-n+1)}, w^{(i-n+2)}, ..., w^{(i-1)})} \end{split} \end{equation} $$

위 수식과 같이 간단하게 발생 빈도수를 계산해서 통계적인 근사치를 구하는 방법입니다. 예를 들어 'The cat slept quietly on the'라는 문장 다음에 'tabel'이 발생할 확률을 4-gram language model에서 다음과 같이 구할 수 있습니다.

$$ p(table \; | \; The \; cat \; slept \; quietly \; on \; the) \approx {count(quietly \; on \; the \; table) \over count(quietly \; on \; the)} $$

4-gram이므로 이전 3개의 단어에만 의존한다고 가정했으므로 위 수식과 같이 'quietly on the' 문장의 발생 빈도와 'quietly on the tabel' 문장의 발생 빈도를 이용해 계산할 수 있습니다.

이와 같은 n-gram language model은 이전의 몇 개의 단어만을 의존하므로 실제 언어의 의미적인 확률분포를 표현한다고 할 수 없습니다.


3. RNN Language Model

RNN Language Model은 언어의 확률분포를 RNN을 이용해서 학습한 language model입니다.

rnn-lm-01.png

위 그림과 같이 '[BOS] The cat slept quietly on the'라는 문장을 입력하고 RNN의 마지막 출력을 이용해서 'tabel'이 발생할 확률을 추론합니다.
'[BOS]'는 begin of sequence를 의미하는 미리 정의된 특수 token 입니다.

3.1. Language Model 학습

rnn-lm-03.png

RNN Language Model을 학습할 때 위 그림과 같이 입력의 처음은 '[BOS]' token이 되도록 정답의 마지막이 '[EOS]' token이 되도록 만듭니다. 이렇게 하면 입력의 위치에서 자신의 다음 단어가 정답이 되는 형식이 됩니다.
'[EOS]'는 end of sequence를 의미하는 미리 정의된 특수 token 입니다.

rnn-lm-02.gif

위 그림과 같이 RNN에 입력을 하고 결과를 이용하여 다음 단어를 예측하는 확률을 최대화하는 방식으로 학습을 합니다. RNN의 수식은 다음과 같습니다.

$$ h_t=tanh(W_h h_{t-1} + W_x x_t + b) $$

RNN은 현재의 단어 $x_t$와 이전 단어들의 정보 $h_{t-1}$로 다음 단어를 예측하도록 학습됩니다.

각 단어에대한 loss $J^{(t)}(\theta)$는 다음과 같습니다.

$$ J^{(t)}(\theta) = -\log \hat{y}_{x_{t+1}}^{(t)} $$

다음단어를 추론할 확률에대한 Negative Log Likelihood입니다.

전체 loss $J(\theta)$는 $J^{(t)}(\theta)$의 평균으로 다음과 같습니다.

$$ J(\theta) = {1 \over T} \sum_{t=1}^T -\log \hat{y}_{x_{t+1}}^{(t)} $$

3.2. Language Model 문장생성

Language Model에서의 문장 생성은 한 단어씩 순서대로 생성해서 문장을 완성합니다.

rnn-lm-04.gif

위 그림과 같이 '[BOS] The cat'이라는 문장을 입력으로 한 단어씩 생성합니다.

  1. '[BOS] The cat'라는 문장을 입력으로 'cat'의 다음 단어를 추론된 확률분포를 기반으로 sampling 합니다. 위 예에서는 'slept'가 sampling 되었습니다.
  2. Sampling된 'slept'를 입력 문장에 추가해서 '[BOS] The cat slept'를 입력으로 다음 단어를 추론하고 sampling 합니다. 위 예에서는 'quietly'가 sampling 되었습니다.
  3. Sampling된 'quietly'를 입력 문장에 추가해서 '[BOS] The cat slept quietly'를 입력으로 다음 단어를 추론하고 sampling 합니다. 위 예에서는 'on'이 sampling 되었습니다.
  4. 이와 같이 순서대로 한 단어씩 생성을 하다가 '[EOS]'가 sampling 되어가 일정한 길이를 넘어가는 경우 문장 생성을 완료합니다.
3.3. Language Model Subcomponent

Language Model은 아래와 같이 다양한 곳에서 subcomponent로 활용됩니다.

  • Predicting Typing
  • Speech recognition
  • Handwriting recognition
  • Spelling/grammar correction
  • Authorship identification
  • Machine Translation
  • Summarization
  • Dialog


4. Perplexity

Perplexity는 Language Model의 성능을 평가하기 위해 사용되는 지표 중 하나입니다. 수식은 아래와 같습니다.

$$ perplexity = \prod_{t=1}^{T} \left({1 \over P_{LM} \left( x^{(t+1)} | x^{(1)}, x^{(2)}, ..., x^{(t)} \right) } \right)^{1 \over T} $$

Perplexity는 입력에 대한 다음 단어를 예측할 확률에 반비례합니다. 확률 값은 [0..1] 사이의 값을 가지므로 확률 값이 1에 가까울수록 작은 값을 가지게 됩니다.

위 수식은 다음과 같이 전개할 수 있습니다.

$$ = \prod_{t=1}^T \left({1 \over \hat{y}_{x_{t+1}}^{(t)}}\right)^{1 \over T} $$

위 수식은 확률 $P_{LM} \left( x^{(t+1)} | x^{(1)}, x^{(2)}, ..., x^{(t)}\right)$을 모델의 추론 확률 $\hat{y}_{x_{t+1}}$으로 변경한 것입니다. 이 두 값은 표현이 다를 뿐 같은 값입니다.

$$ = \exp \left( \log \left( \prod_{t=1}^T \left( {1 \over \hat{y}_{x_{t+1}}^{(t)}} \right) ^{1 \over T} \right) \right) $$

위 수식은 log를 취한 후 exp를 취한 것입니다. log와 exp는 역함수 관계이기 때문에 결괏값이 변하지 않습니다.

$$ = \exp \left( {1 \over T} \sum_{t=1}^{T} -\log \hat{y}_{x_{t+1}}^{(t)} \right) $$

위 수식은 log를 전개한 결과입니다. log의 특성상 곱셈이 덧셈으로 변경되고 지수가 곱하기로 변경되었습니다.

$$ = \exp(J(\theta)) $$

log를 전개한 결과는 loss $J(\theta)$됩니다. $J(\theta)$는 작을수록 좋은 결과를 냅니다. 결국 perplexity도 작은 것이 더 좋다고 볼 수 있습니다.