본문 바로가기

DATA SCIENCE/NLP

[NLP] 잠재 디레클레 할당 (LDA)

이 포스트는 책 '한국어 임베딩(자연어 처리 모델의 성능을 높이는 핵심 비결 Word2Vec에서 ELMo, BERT까지, 이기창 저)'을 기반으로 작성되었습니다.

토픽 모델링 (Topic Modeling)이라고 불리기도 하는 LDA (Latent Dirichlet Allocation)란, 각 문서에 어떤 주제가 존재하는지 나타내는 확률 모형이다.
LDA는 말뭉치 이면에 존재하는 정보를 추론하는, 잠재 정보를 알아내는 과정이므로 잠재(Latent)라는 단어가 붙으며, 변수 중 디레클레 분포를 따르는 변수가 있기 때문에 디레클레(Dirichlet)라는 단어로 명명되어 있다.
http://www.jmlr.org/papers/volume3/blei03a/blei03a.pdf
http://www.cs.columbia.edu/~blei/papers/Blei2012.pdf

우리는 글쓰기를 할 때 먼저 주제를 정한 후, 어떤 단어를 쓸지 생각하면서 글을 쓰게 된다.
LDA도 비슷한 맥락으로 이어진다. 문서의 말뭉치로부터 얻은 주제 분포로부터 주제를 뽑고, 그 주제에 해당하는 단어를 뽑아 문서가 생성되는 과정을 확률 모형으로 모델링한다. 

LDA는 특정 주제에 특정 단어가 나타날 확률과 문서에 대한 주제 분포 비율을 나타내며, 
각 문서를 주제별로 나타날 확률 분포에 대해 벡터화하기 때문에 문서 임베딩 기법으로 간주할 수 있다.

 

LDA 구조

LDA의 전반적인 구조는 다음과 같다.
LDA는 주제의 단어 분포(Φ)와 문서의 주제 분포(θ)의 결합으로 문서 내 단어들이 생성된다는 가정 하에 만들어진다.
유일하게 관찰할 수 있는 변수는 d번째 문서에 등장하는 n번째 단어인 w이며, w에 영향을 주는 변수는 w의 주제를 나타내는 변수 z와 k번째 주제에 대한 단어 확률 분포를 나타내는 변수 Φ이다. 

d번째 문서의 n번째 단어 주제를 나타내는 변수 z는 d번째 문서에 대한 주제 확률 분포를 나타내는 변수 θ에 영향을 받으며, 이 변수는 디레클레 분포 변수 α에 영향을 받아 디레클레 분포를 따른다.
마찬가지로, k번째 주제에 대한 단어 확률 분포를 나타내는 변수 Φ는 디레클레 분포 변수 β에 영향을 받아 디레클레 분포를 따른다.

디레클레 분포
k차원 벡터 요소 모두 양수이며 모두 더한 값이 1인 경우 확률값이 정의되는 연속확률분포
베이즈 확률에서 사전확률로 많이 사용됨

디레클레 분포

 

깁스 샘플링 기법을 활용한 단어 생성 과정

주제 단어 분포와 문서 주제 분포의 결합확률이 커지도록 해야 한다.
LDA의 단어 생성 과정은 다음과 같은 수식으로 나타낼 수 있다.

여기에서 직접 지정해줘야 하는 hyperparameter인 α, β와 관찰 가능한 변수인 w를 제외하고는 미지수이다.
p(z, Φ, θ, w) = p(z, Φ, θ | w) * p(w) 로 나타낼 수 있기에, p(z, Φ, θ | w)를 최대로 만드는 z, Φ, θ를 찾아야 한다.
이룰 위해 이용하는 것이 깁스 샘플링 기법이다.

깁스 샘플링
하나의 변수만 랜덤변수로 놓고 나머지는 고정시킨 채 표본을 뽑는 기법

이를 이용하여 d번째 문서의 n번째 단어가 실제 j번째 주제가 될 확률을 구하면 다음과 같다.

  • n : d번째 문서에서 k번째 주제에 할당된 단어 빈도
  • v : 전체 말뭉치에서 k번째 주제에 할당된 단어 빈도
  • w : d번째 문서의 n번째 단어
  • α : 문서의 주제 분포 생성을 위한 디레클레 분포 변수
  • β : 주제의 단어 분포 생성을 위한 디레클레 분포 변수
  • K : 주제 개수 (사용자 지정)
  • V : 말뭉치의 전체 단어 수
  • A : d번째 문서와 k번째 주제의 연관 정도 
  • B : 단어 w와 k번째 주제와의 연관 정도

이를 예시를 통해 보다 쉽게 이해해보자.
어떤 문서에 아래 표의 5개 단어가 나오고, 각 단어의 주제가 다음과 같다. 또한 전체 문서에서 해당 단어가 어떤 주제로 나왔는지 그 수를 세어 단어-주제 행렬을 만들 수 있다. 
이 상태에서 2번째 단어의 주제를 모른다고 가정해보자. 그러면 단어-주제 행렬에서 해당 단어의 해당 주제 개수는 1이 감소할 것이다. 이 두 값을 막대로 나타내고 면적을 구하면 위 식에서 의미하던 것을 나타낼 수 있다.
위의 식에서 A는 문서의 단어별 주제 분포 길이를, B는 단어별 주제 분포 길이를 나타낸다. 그리고 두 길이를 곱한 면적이 확률을 나타낸다.
따라서 이런 방식으로 모든 문서 및 단어에 대해 수행해주면 단어마다 주제를 할당할 수 있다.


깁스 샘플링 예시

 

Python 코드

from gensim import corpora
from preprocess import get_tokenizer
from gensim.models import ldamulticore

docs, tokenized_corpus = [], []
tokenizer = get_tokenizer("mecab")

with open('doc.txt', 'r') as f:
    for doc in f:
        tokens = list(set(tokenizer.morphs(doc.strip())))
        docs.append(doc)
        tokenized_corpus.append(tokens)
dictionary = corpora.Dictionary(tokenized_corpus)
corpus = [dictionary.doc2bow(text) for text in tokenized_corpus]

LDA = ldamulticore.LdaMulticore(corpus, id2word=dictionary, num_topics=30, workers=4)
all_topics = LDA.get_document_topics(corpus, minimum_probability=0.5, per_word_topics=False)

for idx, topic in enumerate(all_topics):
    print(idx, topic)

 

반응형

'DATA SCIENCE > NLP' 카테고리의 다른 글

[NLP] Transformer Network  (0) 2020.06.23
[NLP] ELMo (Embeddings from Language Models)  (0) 2020.06.23
[NLP] Doc2Vec  (0) 2020.05.27
[NLP] 가중 임베딩  (0) 2020.05.22
[NLP] Swivel (Submatrix-Wise Vector Embedding Leamer)  (0) 2020.05.18