본문 바로가기

NPL with ML

토픽 모델링 [Topic Modeling] - LDA기법 소스포함

반응형

토픽 모델링(Topic Modeling)이란 문서 집합에 숨어 있는 주제를 찾아내는 것입니다. 많은 양의 문서가 있을 때 사람이 이 문서를 다 읽고 핵심 주제를 찾는 것은 매우 많은 시간이 소모됩니다. 

 

이 경우에 머신러닝 기반의 토픽 모델링을 적용해 숨어 있는 중요 주제를 효과적으로 찾아낼 수 있습니다. 사람이 수행하는 토픽 모델링은 더 함축적인 의미로 문장을 요약하는 것에 반해, 머신러닝 기반의 토픽 모델은 중심 단어를 통해 함축적으로 추출합니다. 

 

머신러닝 기반의 토픽 모델링의 대표는 LSA(Latent Semantic Analysis)와 LDA(Latent Dirichlet Allocation)이 있습니다. LDA기법에 대한 예시를 보겠습니다.  LDA는 Count기반의 벡터화만 적용이 됩니다.

 

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation

#모토사이클, 야구, 그래픽스, 윈도우즈, 중동, 기독교, 전자공학, 의학 8개 주제를 추출
cats = ['rec.motorcycles', 'rec.sport.baseball', 'comp.graphics', 'comp.windows.x', 'talk.politics.mideast', 'soc.religion.christian', 'sci.electronics', 'sci.med']

#위에서 cats변수로 기재된 카테고리만 추출, fetch_20newsgrouops()의 categories에 cats입력
news_df = fetch_20newsgroups(subset='all', remove=('headers', 'footers', 'quotes'), categories=cats, random_state=0)

#LDA는 Count기반의 벡터화만 적용합니다.
count_vect = CountVectorizer(max_df=0.95, max_features=1000, min_df=2, stop_words='english', ngram_range=(1,2))
fect_vect = count_vect.fit_transform(news_df.data)
print(fect_vect)
print(fect_vect.shape)

 

상기와 같이 CountVectorizer를 적용한 데이터 세트를 기반으로 LDA토픽 모델링을 구현하면 됩니다. n_components은 추출하고자 하는 토픽의 수를 지정하면 됩니다.  결과로 components_는 개별 토픽별로 각 word피처가 얼마나 많이 해당 토픽에 할당됐는지에 대한 수치를 가지고 있습니다. 높은 값일수록 해당 word피처는 그 토픽의 중심 word가 됩니다.

lda = LatentDirichletAllocation(n_components=8, random_state=0)
lda.fit(fect_vect)
print(lda.components_)
print(lda.components_.shape)

하기 결과를 보면 (8,1000)으로 8가지 토픽별로 1000개의 word피처가 해당 토픽별로 연관도 값을 가지고 있습니다.

[[2.46251560e+02 1.18842248e+02 1.51715288e+02 ... 1.00147234e+02
  7.63673375e+01 1.17028758e+02]
 [1.25033020e-01 1.25052288e-01 1.25003012e-01 ... 1.10644583e+02
  1.51405141e-01 5.09788954e+01]
 [1.25103419e-01 1.25075224e-01 1.25082214e-01 ... 6.72008817e+01
  1.25138615e-01 2.48516614e+00]
 ...
 [1.05055615e+02 4.94858011e-01 2.52075927e+01 ... 1.80695744e+01
  1.25115936e-01 8.33321314e+00]
 [1.25147502e-01 2.27058083e+02 5.45176328e+00 ... 1.41751120e+00
  7.67217701e+01 4.49861794e+01]
 [1.25096012e-01 4.05666840e+00 1.25049904e-01 ... 1.63821915e+02
  1.25049991e-01 1.49550227e-01]]
  
  
(8, 1000)

 

각 Topic별 대표언어를 출력해 봅니다.

def display_topics(model, feature_names, no_top_words):
    for topic_index, topic in enumerate(model.components_):
        print('Topic #', topic_index)

        #components_ array에서 가장 값이 큰 순으로 정렬했을 때, 그 값의 array인덱스를 반환.
        topic_word_indexes = topic.argsort()[::-1]
        topic_index=topic_word_indexes[:no_top_words]

        #top_indexes대상인 인덱스별로 feature_names에 해당하는 word feature 추출 후 join concat
        feature_concat = ' '.join([feature_names[i] for i in topic_index])
        print(feature_concat)
        

#CountVectorizer객체 내의 전체 word의 명칭을 get_feature_names()을 통해 추출
feature_names = count_vect.get_feature_names()

#토픽별 가장 연관도가 높은 word를 15개만 추출
display_topics(lda, feature_names, 15)

 

하기와 같이 8개의 Topic별 대표 단어를 추출해봅니다.  #1번, #3번에 대한 주제가 얼추 가능하네요.! 끝. 

Topic # 0
year said don didn know game just time went people think did like say home
Topic # 1
god people jesus church think believe christ say does don christian know christians bible faith
Topic # 2
know does thanks like question information help time post advance book just looking group read
Topic # 3
edu com graphics mail ftp information available data pub list computer send software ca 3d
Topic # 4
israel jews jewish israeli dos dos arab turkish people war turkey dos state government greek history
Topic # 5
file image use program window jpeg windows display version color server files using available motif
Topic # 6
armenian armenians people health medical armenia disease turkish patients cancer russian 10 azerbaijan children 92
Topic # 7
like just don ve use good think time know way make used bike want need

 

토픽모델링 소스 레퍼런스 확인

반응형