2019.06.12
본 글은 https://wikidocs.net/book/2155을 참고하여 작성되었음을 밝힙니다.
핵심키워드
- LDA(Latent Dirichlet Allocation)
잠재 디리클레 할당(Latent Dirichlet Allocation) 실습
LSA 챕터에서는 사이킷런(sklearn)을 사용하였지만, 이번에는 gensim을 사용하므로 앞서 챕터와 실습 과정이 확연히 다르다.
1) 정수 인코딩과 단어 집합 만들기
바로 이전 챕터 LSA 챕터에서 사용하였던 Twenty Newsgroups이라고 불리는 20개의 다른 주제를 가진 뉴스 데이터를 다시 사용한다. 데이터에 대한 소개나 전처리 과정은 이전 챕터와 중복되므로 생략한다. 동일한 전처리 과정을 거친 후에 tokenized_doc로 저장한 상태라고 하자.
+ 전처리과정
import pandas as pd
from sklearn.datasets import fetch_20newsgroupsdataset = fetch_20newsgroups(shuffle = True, random_state = 1, remove=('headers', 'footers', 'quotes'))document = dataset.data
news_df = pd.DataFrame({'document':document})# 데이터 전처리 과정
news_df['clean_doc'] = news_df['document'].str.replace("[^a-zA-Z#]", " ")
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: ' '.join([w for w in x.split() if len(w) > 3]))
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: x.lower())# 불용어 처리 및 토큰화
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
tokenized_doc = news_df['clean_doc'].apply(lambda x : x.split())
tokenized_doc = tokenized_doc.apply(lambda x: [item for item in x if item not in stop_words])
이제 각 단어에 정수 인코딩을 하는 동시에, 각 문서에서의 단ㄷ어의 빈도수를 기록해본다. 여기서는 각 단어를( word_id, word_frequency)의 형태로 바꾸고자 한다. word_id는 단어가 정수 인코딩된 값이고, word_frequency는 해당 문서에서의 해당 단어의 빈도수를 의미한다. 이는 gensim의 corpora.Dictionary()를 사용하여 수행 가능하다. 전체 문서에 대해서 정수 인코딩을 수행하고, 두번째 문서를 출력해보자.
from gensim import corpora
dictionary = corpora.Dictionary(tokenized_doc)corpus = [dictionary.doc2bow(text) for text in tokenized_doc]
corpus[1] # 수행된 결과에서 두번째 문서 출력, 첫번째 문서의 인덱스는 0
[(52, 1), (55, 1), (56, 1), (57, 1), (58, 1), (59, 1), (60, 1),
(61, 1), (62, 1), (63, 1), (64, 1), (65, 1), (66, 2), (67, 1),
(68, 1), (69, 1), (70, 1), (71, 2), (72, 1), (73, 1), (74, 1),
(75, 1), (76, 1), (77, 1), (78, 2), (79, 1), (80, 1), (81, 1),
(82, 1), (83, 1), (84, 1), (85, 2), (86, 1), (87, 1), (88, 1),
(89, 1)]
두 번째 문서의 출력 결과를 보면 (66, 2)는 정수 인코딩이 66으로 할당도니 단어가 두 번째 문서에서는 두 번 등장하였음을 알 수 있다. 66이라는 값을 가지는 단어가 정수 인코딩이 되기 전에는 어떤 단어였는지 확인할 수 있다.
dictionary[66]
'faith'
기존 단어 ‘faith’ 였음을 알 수 있다. 총 학습된 단어의 개수는 dictionary의 길이를 보면 된다.
len(dictionary)
65284
총 65,284개의 단어가 학습되었다. 이제 LDA 모델을 훈련시켜보자.
2) LDA 모델 훈련시키기
기존의 뉴스 데이터가 총 20개의 카테고리를 가지고 있었으므로 토픽의 개수를 20으로 하여 LDA 모델을 학습시켜보자
import gensim
NUM_TOPICS = 20ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics = NUM_TOPICS, id2word=dictionary, passes=15)topics = ldamodel.print_topics(num_words=4)for topic in topics:
print(topic)(0, '0.013*"book" + 0.008*"books" + 0.006*"reference" + 0.006*"picture"')
(1, '0.044*"scsi" + 0.017*"disks" + 0.009*"swap" + 0.006*"sequences"')
(2, '0.022*"printf" + 0.021*"char" + 0.020*"year" + 0.020*"null"')
(3, '0.067*"space" + 0.025*"nasa" + 0.014*"launch" + 0.013*"earth"')
(4, '0.028*"armenian" + 0.024*"armenians" + 0.020*"turkish" + 0.012*"turkey"')
(5, '0.008*"post" + 0.008*"list" + 0.008*"article" + 0.007*"posting"')
(6, '0.022*"file" + 0.013*"program" + 0.011*"files" + 0.010*"available"')
(7, '0.015*"disease" + 0.015*"pain" + 0.014*"food" + 0.013*"patients"')
(8, '0.012*"thanks" + 0.011*"would" + 0.010*"drive" + 0.010*"know"')
(9, '0.013*"encryption" + 0.012*"chip" + 0.011*"keys" + 0.010*"clipper"')
(10, '0.010*"like" + 0.010*"would" + 0.010*"good" + 0.007*"much"')
(11, '0.020*"would" + 0.016*"people" + 0.013*"think" + 0.009*"like"')
(12, '0.021*"jesus" + 0.012*"christian" + 0.012*"bible" + 0.011*"church"')
(13, '0.013*"government" + 0.009*"people" + 0.008*"state" + 0.008*"israel"')
(14, '0.012*"said" + 0.010*"know" + 0.010*"people" + 0.009*"time"')
(15, '0.010*"african" + 0.007*"cells" + 0.006*"tigers" + 0.006*"nords"')
(16, '0.022*"game" + 0.021*"team" + 0.015*"games" + 0.014*"play"')
(17, '0.030*"wire" + 0.029*"ground" + 0.020*"neutral" + 0.016*"panel"')
(18, '0.017*"runs" + 0.015*"filename" + 0.011*"pitching" + 0.010*"lost"')
(19, '0.009*"information" + 0.007*"university" + 0.007*"research" + 0.006*"april"')
각 단어 앞에 붙ㅇ느 수치는 단어의 해당 토픽에 대한 기여도를 보여준다. 또한 맨 앞에 있는 토픽 번호는 0부터 시작하므로 총 20개의 토픽은 0부터 19까지의 번호가 할당되어져 있다. 여기서는 num_words=4로 총 4개의 단어만 출력하도록 했다.
3) LDA 시각화 하기
LDA 시각활르 위해서는 pyLDAvis의 설치가 필요하다. 설치를 한 후, LDA 시각화를 하자.
import pyLDAvis.gensim
pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim.prepare(ldamodel, corpus, dictionary)
pyLDAvis.display(vis)
좌측의 원은 각각의 20개의 토픽을 나타낸다. 위의 그림에서는 4번 토픽을 클릭하였고, 이에 따라 우측에는 4번 토픽에 대한 정보가 나타난다. 한 가지 중의할 점은 LDA 모델의 출력 결과에서는 토픽 번호가 0부터 할당되어 0~19의 숫자가 사용된 것과는 달리 위의 LDA 시각화에서는 토픽의 번호가 1부터 시작하므로 토픽 번호를 헷갈리지 않게 주의하자.