[Python]Top2Vec 각 Document 별 Topic 찾기

배경

  • Top2Vec으로 토픽 모델링 이후 각 Document 별 해당되는 토픽을 알고자 할 때

해결책

  • Top2Vec의 Github 코드를 확인해보니, Single Underscore Function으로 있는 _calculate_documents_topic의 Return Value로 doc_top, doc_dist를 갖는데, doc_top은 각각 Document 별 Topic에 대한 List이다. 그리고 doc_dist는 Topic Vector와의 Distance 값이다.
  • "model.search_documents_by_topic(0, num_docs=1)" 형태로 Topic 0에 해당하는 Document 1개를 가지고 오라고 할 때 doc_top,doc_dist를 통해 가지고 온다.
  • 아직 모델이 개발중이라서 그런 것인지, 해당 변수에 대해서 model.doc_top, model.doc_list 형태로 바로 접근이 가능하다.
import numpy as np
import pandas as pd
from top2vec import Top2Vec
from sklearn.datasets import fetch_20newsgroups

np.random.seed(0)

# Data Loading
newsgroups = fetch_20newsgroups(subset='all', remove=('headers', 'footers', 'quotes'))

# Modeling 
model = Top2Vec(newsgroups.data, workers=4, embedding_model='universal-sentence-encoder')

model.search_documents_by_topic(0, num_docs=1)

위에까지 실행하고 나면 아래와 같은 결과를 볼 수 있다.

#(array(['Well, the Patrick Division got a little more interesting last night. ...dtype=object), array([0.7826741], dtype=float32), array([17864]))

위 내용은 17864번 인덱스 Document가 Topic Vector로부터 가장 가까이 있고 거리 값은 0.7826741이라는 것이다. 위 Document는  model.doc_top[17684], model.doc_list[17684]에서 확인할 수 있다.

Topic Vector은 다음과 같이 동일한 Cluster를 가지고 있는 Document Vector의 평균 값을 이용해서 생성하는 듯하다.(자세히 보지는 않았음)

self.topic_vectors = self._l2_normalize(
            np.vstack([self.document_vectors[np.where(cluster_labels == label)[0]]
                      .mean(axis=0) for label in unique_labels]))