OkBublewrap

토픽 모델링 - 20 뉴스 그룹 본문

Python/학습용

토픽 모델링 - 20 뉴스 그룹

옥뽁뽁 2023. 4. 4. 04:23

문서 집합에 숨어 있는 주제를 찾아내는 것 자주 사용하는 기법은 LSA(Latent Semantic Analysis)와 LDA(Latent Dirichlet Allocation)이다. 

 

LDA(Latent Dirichlet Allocation)

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

# category
cats = ['rec.motorcycles', 'rec.sport.baseball', 'comp.graphics', 'comp.windows.x',
		'talk.politics.mideast', 'soc.religion.christian', 'sci.eletronics', 'sci.med']

# 위 카테고리 추출
news_df = fetch_20newsgroup(subset='all', remove=('headers', 'footers', 'quotes'),
							categories=cats, random_state=0)
                            

# LDA는 Count기반의 Vectorizer만 적용
count_vect = CountVectorizer(max_df = 0.95, max_features=100, min_df=2, stop_words='english', ngram_range=(1,2))
# max_df : 문서에서 등장 빈도가 0.95 이상인 단어를 제거(0.0~1.0)
# max_features : 추출한 최대 단어수 100
# stop_words : 불용어
# ngram_range : 1단어, 2단어 

feat_vect = count_vect.fit_transform(news_df.data)
print('CountVectorizer Shape:', feat_vect.shape)
# CountVectorizer Shape: (7862, 1000)

LatentDirchletAllocation은 비지도학습으로 여덟개의 분류로 학습을 시킨다.

 

lda = LatentDirichletAllocation(n_components=8, random_state=0)
lda.fit(feat_vect)

print(lda.components_.shape)
lda.components_
# (8, 1000)
# array([[3.60992018e+01, 1.35626798e+02, 2.15751867e+01, ...,
#         3.02911688e+01, 8.66830093e+01, 6.79285199e+01],
#        [1.25199920e-01, 1.44401815e+01, 1.25045596e-01, ...,
#         1.81506995e+02, 1.25097844e-01, 9.39593286e+01],
#        [3.34762663e+02, 1.25176265e-01, 1.46743299e+02, ...,
#         1.25105772e-01, 3.63689741e+01, 1.25025218e-01],
#        ...,
#        [3.60204965e+01, 2.08640688e+01, 4.29606813e+00, ...,
#         1.45056650e+01, 8.33854413e+00, 1.55690009e+01],
#        [1.25128711e-01, 1.25247756e-01, 1.25005143e-01, ...,
#         9.17278769e+01, 1.25177668e-01, 3.74575887e+01],
#        [5.49258690e+01, 4.47009532e+00, 9.88524814e+00, ...,
#         4.87048440e+01, 1.25034678e-01, 1.25074632e-01]])

lda.componets_.shape는 8, 1000으로 8개의 주제에 각각 1000개의 다너를 가지고 있다.

lda.components_는 각 주제에 있는 단어의 가중치를 나타낸 것이다. 이것을 보기 위해서는

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

        # components_ array에서 가장 값이 큰 순으로 정렬했을 때, 그 값의 array index를 반환. 
        topic_word_indexes = topic.argsort()[::-1]
        top_indexes=topic_word_indexes[:no_top_words]
        
        # top_indexes대상인 index별로 feature_names에 해당하는 word feature 추출 후 join으로 concat
        feature_concat = ' '.join([feature_names[i] for i in top_indexes])                
        print(feature_concat)

for topic_index, topic in enumerate(model.components_):

topic_index : 0~7

topic 안에는 각각의 리스트가 들어간다.

 

topic_word_idexes는 topic의 가중치 값들을 내림차순으로 정렬을 한뒤 argsort() 인덱스 번호를 가져오는 함수이다.

no_top_words에 숫자를 넣어 표현해 줄 값을 넣는다.

'  '.join : 단어 사이에 빈칸으로 넣고, ([feature_names[i] for i in top_indexes]) 가중치가 높은 인덱스(top_indexes)에서 순서대로 나온 단어를 합쳐서 출력

Topic # 0
year 10 game medical health team 12 20 disease cancer 1993 games years patients good
Topic # 1
don just like know people said think time ve didn right going say ll way
Topic # 2
image file jpeg program gif images output format files color entry 00 use bit 03
Topic # 3
like know don think use does just good time book read information people used post
Topic # 4
armenian israel armenians jews turkish people israeli jewish government war dos dos turkey arab armenia 000
Topic # 5
edu com available graphics ftp data pub motif mail widget software mit information version sun
Topic # 6
god people jesus church believe christ does christian say think christians bible faith sin life
Topic # 7
use dos thanks windows using window does display help like problem server need know run

클러스터링에서 군집화와 비슷한 느낌을 받았다. 다른것이 있다면 단어의 가중치값이고 클러스터링은 k-means에서 보면 k개의 중심점을 지정을 하여서 데이터와 가까운 값을 해 나누는 기법이다. 처음에 시작할 때 20뉴스그룹을 8개로 해서 추출을 했다. 주제는 모토사이클, 야구, 그래픽스, 윈도우즈, 중동, 기독교, 의학, 우주이다.

1번째 Topic을 보면 medicial, health, disease, cancser, patients을 보니 의학적 주제를 가지고 있는 것 같다.

2번째 Topic는 의미를 알 수 없는 단어를 포함하고 있어서 유추하기가 어렵다.

3번째 Topic은 명확하게 image file, jpeg program, gif images, 그래픽스에 대한 토픽이 나왔다.

4번째 Topic은 book, read, information, post을 봐서 책이나 정보, 포스터에 대한 단어인 것 같다. (주제와 상관없는 단어)

5번째 Topic은 armenain israel turkish을 보니 중동에 대한 단어가 나왔다.

6번째 Topic은 edu, ftip data, mail, software, version으로 윈도우즈에 대한 단어들인 것 같다. 

7번째 Topic은 god, jesus, church, believe, christian, bible, faith으로 기독교에 대한 토픽이 나왔다. 8번째는 window, display, server등 윈도우즈에 대한 토픽이다. 이중에서 야구, 모토사이클에 대한 토픽을 찾을 수가 없었는데 이 부분에 대해서 단어들을 더 출력을 해서 보기로 했다. 2,4번째만 

 

# Topic 2
# lda.components_[1]
topic_2 = lda.components_[1].argsort()[::-1]
topic_2_idx = topic_2[:30]
topic_2_word = ' '.join([feature_names[i] for i in topic_2_idx])

topic2번째 단어를 30개를 더 넣어서 보기로 했다.

'don just like know people said think time ve didn right going say ll way did good bike really got want went left thing came let told little don know started'

bike란 단어가 나오고 그 외에는 의미있는 단어가 있지는 않았다. 

 

# Topic 4
# lda.components_[3]
topic_4 = lda.components_[3].argsort()[::-1]
topic_4_idx = topic_4[:30]
topic_4_word = ' '.join([feature_names[i] for i in topic_4_idx]) 
topic_4_word
'like know don think use does just good time book read information people used post question group point list interested need make want case work sure way new non current'

가중치가 높은 단어들로 봤어도 이 단어에 대한 주제는 유추를 하기 힘든 것 같다.

'Python > 학습용' 카테고리의 다른 글

문서유사도  (0) 2023.04.05
문서 군집화  (0) 2023.04.05
감성분석 chat gpt  (0) 2023.03.31
감성분석  (0) 2023.03.30
20 뉴스그룹 분류  (0) 2023.03.28