Books/한국어 임베딩

[Books] 확률 기반 언어모델 (NPLM, Word2Vec, FastText)

언킴 2022. 3. 24. 14:53
반응형

Contents

     

     

    단어수준 임베딩이란 추후 나올 문장수준 임베딩이 나오기 이전에 나온 방법론으로, 단어들을 임베딩해 모델을 구축하는 것을 의미한다. 단어수준 임베딩은 예측기반 모델(rediction based model)과 행렬 분해기반 모델(Matrix Factorization based model)이 존재한다. 

     

    • Prediction based model
      • NPLM, Word2Vec, FastText

     

     

    • Matrix Factorization based model 
      • LSA, GloVe, Swivel

    이번 글에서는 NPLM, Word2Vec, FastText 등의 확률 기반 언어모델에 대해서 다룰 것이고, 행렬 분해 기반 언어모델은 다음에 다루어볼 것이다. 

     

    Prediction Based Model


    NPLM (Neural Probabilistic Language Model)

    기존 n-gram의 경우 학습 데이터에 존재하지 않는 문장이 나타날 경우 확률값을 0으로 처리한다는 단점이 존재해 back-off나 smoothing 방법을 사용하여 일부 개선이 가능하지만 완전히 개선하지 못했다. 또한, n이 커질수록 그 등장 확률이 거의 0인 단어 시퀀스가 기하급수적으로 늘어나기 때문에 장기 의존성(long-term dependency)을 포착하기 어렵다는 단점이 존재한다. NLPM은 이와같은 문제를 극복한 모델이며 다음과 같은 구조를 가지고 있다. [논문]

     

    NPLM (Bengio et al., 2003)

    NPLM은 다음 수식을 최대화 하는 것을 목적으로 한다. $w_t$는 t번째 단어를 의미하고, $n$은 단어의 총 개수를 의미한다. 위 구조를 뜯어서 한 번 살펴보자. 우리는 $w_t$를 예측하기 위해서 $w_{t-1}$부터 $w_{t-n+1}$까지의 총 n-1개를 고려해 다음 단어를 예측하는 방식으로 학습한다. 각각의 단어에 대한 행렬 $\boldsymbol{C}$을 $\tanh$로 보내고, $\tanh$에 전달된 값을 최종 Layer에 보내면서 원래 각 단어들의 벡터를 참조(Lookup)하는 것을 볼 수 있다. 

    \[ \text{P}(w_t|w_{t-1}, ..., w_{t-n+1}) = \frac{\exp(y_{w_t})}{\sum_i \exp(y_i)}\] 

    참조라는 말을 어렵게 생각할 필요 없이 $\boldsymbol{C}$에 원-핫 벡터를 내적해주면 쉽게 도출할 수 있다. 이 과정을 수식으로 표현하면 다음과 같다. 

     

    $ \boldsymbol{C}(w_t) = \begin{bmatrix} 0 & 0 & 0 & 1 & 0 \end{bmatrix} \times \begin{bmatrix} 11 & 18 & 25 \\ 10 & 12 & 19 \\ 4 & 6 & 13 \\ 23 & 5 & 7 \\ 17 & 24 & 1 \end{bmatrix} $

    $ = \begin{bmatrix} 23 & 5 & 7 \end{bmatrix} $

     

    위에서 언급한 방식을 수식으로 간단히 표현하면 다음과 같다. 

    \[ \boldsymbol{y_{w_t}} = \boldsymbol{b} + \boldsymbol{Wx} + \boldsymbol{U}\tanh(\boldsymbol{d} + \boldsymbol{Hx}) \] 

    $\boldsymbol{W} \in \mathbb{R}^{|V| \times (n-1)m}, \ \boldsymbol{U} \in \mathbb{R}^{|V| \times h}, \ \boldsymbol{H} \in \mathbb{R}^{h \times (n-1)m}$는 가중치 벡터임을 확인할 수 있으며, 역전파 알고리즘을 수행하여 학습하는 방식으로 이루어진다. 

     

     

    Word2Vec

    Word2Vec은 2013년 구글에서 발표한 기법이며 지금까지도 많이 활용되고 있는 방법 중 하나이다. 개별 토큰들을 독립적이라고 봐서 문맥을 고려하지 않기에 문장을 전부 고려해야되는 태스크에서는 사용을 하고 있진 않지만, 특정 토큰을 독립적으로 대변할 수 있는 부분에서는 응용 부분으로 아직 많이 사용된다. Mikolov et al. (2013a)에서 처음 제안하였고, Mikolov et al. (2013b)에서 이 기법을 사용하되 네거티브 샘플링(Negative Sampling)등 학습 최적화 기법을 제안하였다. 네거티브 샘플리은 현재 추천 시스템에서도 많이 활용되고 있는 방법이다. 

    CBOW의 경우 주변 단어를 기반으로 특정 단어를 예측하는 방식이기에 1번의 학습이 진행되지만, Skip-gram의 경우 특정 단어를 가지고 주변 단어를 예측하기에 위 그림의 경우 4번의 학습을 수행하게 된다. 보다 많은 학습을 수행하기에 일반적으로 CBOW보다 Skip-gram의 임베딩 성능이 조금 더 좋은 것으로 알려져있다. 

     

    타깃 단어 $w(t)$를 학습할 때 주변 단어들인 $w(t-2), w(t-1), w(t+1), w(t+2)$와 같은 단어들은 포지티브 샘플(positive sample)이라고 표현하고, 그외 학습에 관여하지 않는 단어들은 네거티브 샘플(negative sample)이라고 표현한다. 위 그림에서는 윈도우(window)를 2로 설정하였기에 양 옆 2개씩 단어를 고려해 분석을 진행하였다. 만약 윈도우 크기를 3으로 설정한다면 주변 각각 3개씩의 단어를 고려하는 방식이 될 것이다. 

     

    Word2Vec 논문에서는 단어 하나당 2*윈도우 크기 만큼의 학습 데이터를 만들어 해당 단어가 나올 확률을 계산하기에 사전에 있는 단어의 수가 많으면 많아질수록, 윈도우 크기가 커지면 커질수록 연산량이 너무 많아진다. 우리가 정답 문맥 단어(Context word)가 나올 확률은 높이고 정답이 아닌 문맥 단어가 나올 확률은 낮춰야하기에 엄청난 연산을 수행하기 때문이다. 그렇기에 네거티브 샘플링이라는 기법을 도입하여 타깃 단어와 문맥 단어 쌍이 주어졌을 때 해당 쌍이 positive인지 negative인지 이진 분류하는 과정으로 변환하였다. 

     

    네거티브 샘플링을 사용하게 되면 1개의 포지티브 샘플과 k개의 네거티브 샘플만을 계산해 positive인지 negative인지를 계산하지만, 기존 방식의 경우 매번 모든 단어들에 대해서 소프트맥스를 계산하기에 전자보다 계산량이 많다는 것을 이해할 수 있다. 이때 네거티브 샘플은 데이터의 수가 작을 경우 5~20, 데이터의 수가 많을 경우 2~5로 설정하는 것이 가장 성능이 좋았다고 한다. 

     

    하지만 네거티브 샘플링은 랜덤하게 샘플링을 하는 방식이기에 이 방법이 최적의 해를 가지고 온다고는 할 수 없다. 그렇기 때문에 말뭉치에 자주 등장하지 않는 희귀한 단어가 네거티브 샘플로 조금 더 잘뽑힐 수 있도록 설계하였다. 추가적으로 자주 등장하는 단어는 학습에서 제외하는 서브샘플링(sub sampling)기법도 적용했다. 

     

    그렇다면 Word2Vec는 어떻게 학습하는 것일까? Word2Vec에서 성능이 좋다고 알려진 Skip-gram의 학습 방법에 대해서 알아보자. Skip-gram 모델은 단어 쌍이 주어졌을 때 positive인지를 예측하는 과정에서 학습된다. 만약 단어 쌍이 positive라면 다음의 수식은 최대가 되어야 한다. 

    \[ \text{P}(+|t,c) = \frac{1}{1+ \exp(-\boldsymbol{U}_t \boldsymbol{v}_c)} \] 

    $\boldsymbol{U}, \ \boldsymbol{V} \in \mathbb{R}^{|V| \times N}$으로 차원이 동일하며 $N$은 임베딩 차원의 수를 의미한다. 이와 같이 타깃 단어와 문맥 단어간 유사도를 내적(inner product)을 수행하여 내적이 커지는 방향으로 학습을 진행한다. 이때의 내적은 코사인 유사도(cosine similarity)와 비례한다. 

     

    positive의 경우 위의 수식이 최대화하는 방향으로 학습하였으나 negative를 예측하는 경우 위 수식을 최대화하는 방법으로 접근하는 것이 아니라 위 수식을 최소화하는 방향으로 접근해야 한다. 즉, 아래의 수식을 최대화하는 방식으로 접근할 수 있다. 

    \[ \text{P}(-|t,c) = 1 - \text{P}(t,c) = \frac{\exp(-\boldsymbol{u}_t \boldsymbol{v}_c)}{1 + \exp(-\boldsymbol{u}_t \boldsymbol{v}_c)}\]

    분자를 최대화하기 위해서는 각 단어 간 내적 값을 최소화하는 방향으로 접근해야한다. 이때 우리는 목적 함수를 MLE(Maximul Likelihood Estimate)를 사용할 수 있다. MLE의 자세한 수식은 여기를 참고하면 된다. Skip-gram의 경우 최대화를 해야하는 수식이 두개이기에 목적 함수를 다음과 같이 정의할 수 있다. 

    \[ \mathcal{L}(\theta) = \log\text{P}(+|t,c) + \sum^k_{i=1}\log\text{P}(-|t_{n_i}, c_{n_i})\]

    네거티브 샘플의 경우 여러개를 추출하기에 $\Sigma$를 통해 합산해준 것이다. 

     

    Word2Vec는 gensim 패키지에서 지원해주기에 매우 간단하게 구현이 가능하다. gensim 에서는 latent vector의 기본값을 100으로 설정하였으며, 차원을 변경하고 싶을땐 조절하면 된다. 코드의 구현은 매우 간단하며 여기를 참고하면 된다. 결과값을 확인할 때 전혀 정반대의 단어들이 유사하다고 도출될 수도 있다. 이 때 우리는 '유사하다'라는 것의 의미를 제대로 이해하여야 한다. 예를 들어 '춥다'와 '덥다'가 유사하다고 나왔을 때 전혀 상반되는 단어인데 왜 유사하다고 도출되었는지 생각해보면 두 단어는 모두 '날씨'라는 속성을 매개로 강한 관련을 맺고 있다. 단순히 단어 간 유사도를 측정하는 것으로 이해하는 것이 아니라 관련성(relevance)이 높은 단어를 출력한다는 것으로 이해하는 것이 매끄럽다. 

     

    FastText

    FastText는 페이스북에서 개발해 공개한 단어 임베딩 기법이다[논문]. Word2Vec와 구조는 동일하지만 단어 단위로 n-gram을 구성하는 것이 아니라, 단어를 문자(character) 단위로 n-gram을 구성한 것이 가장 큰 차이점이다. 예를 들어 '고등학교'라는 단어를 문자 단위 n-gram(n=3)을 수행한다고 가정하면, <고등, 고등학, 등학교, 학교>, <고등학교>가 된다. '<'와 '>'는 FastText 모델이 사용하는 특수한 기호이다. 

    \[ \boldsymbol{u}_{\text{고등학교}} = \boldsymbol{z}_\text{<고등} + \boldsymbol{z}_\text{고등학} + \boldsymbol{z}_\text{등학교} + \boldsymbol{z}_\text{학교>} + \boldsymbol{z}_\text{<고등학교>} \] 

    \[ \boldsymbol{u}_t = \sum_{g \in G_t} \boldsymbol{z}_g \]

    $G_t$는 타깃 단어 t에 속한 문자 단위 n-gram 집합을 의미한다. FastText 역시 Word2Vec과 동일하게 네거티브 샘플링 기법을 사용하지만, FastText는 타깃 단어에 속한 문자 단위 n-gram vector를 모두 업데이트하기 때문에 최대화하는 수식이 Word2Vec과는 조금 상이하며, 포지티브 샘플과 네거티브 샘플에 대한 수식은 다음과 같다. 

    \[ \text{P}(+|t,c) = \frac{1}{1 + \exp(-\boldsymbol{u}_t \boldsymbol{v}_c)} = \frac{1}{1+\exp(-\sum_{g \in G_t} \boldsymbol{z}^T_g \boldsymbol{v}_c)} \] 

    \[ \text{P}(-|t, c) = 1 - \text{P}(+|t,c) = \frac{\exp(-\boldsymbol{u}_t \boldsymbol{v}_c)}{1+\exp(-\boldsymbol{u}_t \boldsymbol{v}_c)} = \frac{\exp(-\sum_{g \in G_t} \boldsymbol{z}^T_g \boldsymbol{v}_c)}{1+\exp(-\sum_{g \in G_t} \boldsymbol{z}^T_g \boldsymbol{v}_c)} \] 

    Fasttext 모델은 조사나 어미가 발달한 한국어에서 Word2Vec보다 좋은 성능을 보인다고 한다. 동사, 형용사의 활용이나 그와 관계된 어미들이 벡터 공간상에 가깝게 임베딩된다. 또한 오타나 Unknown word에 대해서도 robust하다. 단어 단위로 임베딩을 하는 것이 아니라 문자 단위로 하기에 오타가 발생하더라도 어느정도 같은 n-gram을 구성하고 있기 때문이다. 

     

    Word2Vec과 FastText 등 확률 기반 언어모델의 코드는 여기를 참고하면 된다.