아래 step 2 까지 성공적으로 수행했다면 자신이 분석하고 싶은 텍스트 뭉터기의 json 파일이 있을 것이다.
이제 본격적으로 토픽모델링을 돌려보자.
-
데이터 업로드
jupyter notebook 을 실행시킨 후, Upload 버튼을 눌러 토픽모델링을 할 데이터를 jupyter 폴더 내에 올린다.
-
새로운 작업 공간 만들고 사용법 익히기
우측 상단의 New → Python 3 을 눌러 새로운 작업 공간을 만든다.
-
Mallet 설치
아래 링크에서 Mallet 을 다운로드 받고 설치한다.
http://mallet.cs.umass.edu/dist/mallet-2.0.8.zip
-
nltk stopwords, spacy model 다운로드
2-1) NLTK 설치를 하려면 먼저 numpy 를 설치해야 한다.
아래의 사이트에 접속해 numpy 파일을 다운로드 받는다.
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy
본인이 설치한 파이썬 버전을 확인하고 해당하는 파일을 다운 받으면 된다.
그 후 명령프롬프트 창을 열어 아래 pip 명령어를 통해 설치한다.
python -m pip install [numpy 파일이 다운로드된 경로/numpy-1.11.2+mkl-cp35-cp35m-win32.whl]
2-2) numpy 설치가 완료되었다면 NLTK 를 pip로 설치하자.
명령프롬프트 창에 pip install nltk 입력. 아래 이미지의 경우 이미 설치가 된 상태여서 세줄만 출력되었지만 첫 설치라면 텍스트가 많이 출력될 수 있다.
그 후 Python Shell 에 들어가서 아래와 같이 두 줄을 입력해보자. shell은 윈도우 검색창 (전체 화면 아래 검색창)에 idle 이라고 입력한 후 Python IDLE 을 실행하면 나온다.
아래와 같은 창이 뜨면 All packages 를 다운로드 하면 된다.
다음, 아까와 같이 Python console 에 들어가서 우선 데이터 전처리에 필요한 nltk 를 import 하자.
‘#’으로 시작하는 문장은 설명이므로 무시한다.
그 후 명령 프롬프트 창에 들어가 아래 두번째와 명령과 같이 입력한다.
# Run in python console
import nltk; nltk.download('stopwords')
# Run in terminal or command prompt
python3 -m spacy download en
-
패키지 다운로드
이 매뉴얼에서는 그 외에도 re, gensim, spacy, pyLDAvis, matplotlib, numpy, pandas pip패키지를 모두 사용할 것이므로 명령 프롬프트 창에서 모두 pip 로 설치하면 된다. 아래의 이미지는 gensim 을 설치할 때의 모습이다.
> pip install {패키지 이름}
-
패키지와 데이터 import
그 후 아래의 코드를 jupyter 에 붙여넣어보자. 붙여 넣을 때 ‘Test_file.json’ 자리에는 데이터 파일의 이름을 넣도록 한다.
Mallet 을 다운로드한 위치를 Mallet 경로설정 부분으로 수정한다.
import re
import numpy as np
import pandas as pd
from pprint import pprint
import json
import codecs
# Gensim
import gensim
import gensim.corpora as corpora
from gensim.utils import simple_preprocess
from gensim.models import CoherenceModel
import os
from gensim.models.wrappers import LdaMallet
os.environ['MALLET_HOME'] = 'C:/Users/user/Desktop/mallet-2.0.8'
# spacy for lemmatization
import spacy
# Plotting tools
import pyLDAvis
import pyLDAvis.gensim # don't skip this
import matplotlib.pyplot as plt
# %matplotlib inline
# Enable logging for gensim - optional
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.ERROR)
import warnings
warnings.filterwarnings("ignore",category=DeprecationWarning)
# NLTK Stop words
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['from', 're', 'edu'])
# Import data
with codecs.open('Test_file.json', 'r', 'utf-8-sig') as json_file:
df= pd.DataFrame(json.load(json_file))
df.head()
# Convert to list
data = df.values.tolist()
pprint(data[:1])
-
Stopword 설정
Stopword list 란, 데이터 전처리 과정에서 제거하려는 단어의 목록이다. NLTK 패키지에서 제공하는 Stopword list 가 기본적인 단어들은 제거해주지만, 사용자가 추가로 그 리스트를 extend 할 수 있다. 위 코드에서 ‘from’ ‘re’ ‘edu’ 는 이 매뉴얼에서 추가로 설정한 것으로, 만약 disaster 라는 단어를 추가로 제거하고 싶다면 ‘edu’ 뒤에 ‘disaster’ 를 추가로 넣어주면 된다.
Run 버튼 눌러 실행시키면 아래와 같이 따옴표로 분리된 문서를 볼 수 있다. 코드 마지막 줄에 pprint(data[:1]) 은 list 형태로 바뀐 데이터 중 1번째 항목을 보여주는 것으로, 업로드한 파일에서 첫번째 논문의 초록이라고 볼 수 있다.
-
Tokenizing
다음, 아래 코드를 새 박스 안에 붙여넣어보자. Tokenizing은 문장들을 단어로 쪼개는 과정이다.
# Tokenize words
def sent_to_words(sentences):
for sentence in sentences:
yield(gensim.utils.simple_preprocess(str(sentence), deacc=True)) # deacc=True removes punctuations
data_words = list(sent_to_words(data))
print(data_words[:1])
Run 버튼을 눌러 실행하면 아래와 같은 출력 결과를 볼 수 있다.
print 는 단지 과정을 보기 위한 용도로, 나중에 모두 확인이 되면 지워도 된다.
-
Bigram, Trigram 모델 사용하기
계속 해서 다음 블록을 붙여넣고 실행한다. Bigram 은 문서에서 자주 붙여 쓰는 두개의 단어들, Trigram 은 문서에서 자주 붙여쓰는 세개의 단어들을 말한다.
threshold 가 높을수록 단어들이 붙기 어려워진다. 이 매뉴얼에서는 디폴트 값 100으로 진행해보겠다.
# Build the bigram and trigram models
bigram = gensim.models.Phrases(data_words, min_count=5, threshold=100) # higher threshold fewer phrases.
trigram = gensim.models.Phrases(bigram[data_words], threshold=100)
# Faster way to get a sentence clubbed as a trigram/bigram
bigram_mod = gensim.models.phrases.Phraser(bigram)
trigram_mod = gensim.models.phrases.Phraser(trigram)
# See trigram example
print(trigram_mod[bigram_mod[data_words[0]]])
-
Stopword 없애고 Lemmatize 하기
쓸데없는 단어들을 지우고, 품사에 따라 나누는 작업을 하기 위해 아래 코드를 붙여넣어 실행한다.
# Define functions for stopwords, bigrams, trigrams and lemmatization
def remove_stopwords(texts):
return [[word for word in simple_preprocess(str(doc)) if word not in stop_words] for doc in texts]
def make_bigrams(texts):
return [bigram_mod[doc] for doc in texts]
def make_trigrams(texts):
return [trigram_mod[bigram_mod[doc]] for doc in texts]
def lemmatization(texts, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
"""https://spacy.io/api/annotation"""
texts_out = []
for sent in texts:
doc = nlp(" ".join(sent))
texts_out.append([token.lemma_ for token in doc if token.pos_ in allowed_postags])
return texts_out
# Remove Stop Words
data_words_nostops = remove_stopwords(data_words)
# Form Bigrams
data_words_bigrams = make_bigrams(data_words_nostops)
# Initialize spacy 'en' model, keeping only tagger component (for efficiency)
# python3 -m spacy download en
nlp = spacy.load('en', disable=['parser', 'ner'])
# Do lemmatization keeping only noun, adj, vb, adv
data_lemmatized = lemmatization(data_words_bigrams, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV'])
print(data_lemmatized[:1])
-
Dictionary 와 Corpus 만들기
토픽 모델에 사용될 dictionary(id2word)와 corpus 를 만들기 위해 아래 코드를 붙여넣고 실행한다.
# Create Dictionary
id2word = corpora.Dictionary(data_lemmatized)
# Create Corpus
texts = data_lemmatized
# Term Document Frequency
corpus = [id2word.doc2bow(text) for text in texts]
# View
print(corpus[:1])
아래와 같이 숫자쌍이 출력될텐데, 이는 문서에서 나오는 단어마다 id를 달고 frequency를 체크한 것이다.
+) 궁금하다면 id2word[0] 를 출력해서 아이디에 해당하는 단어가 무엇인지 알 수 있다. (0 자리에 아이디 바꿔가면서 체크할 수 있음)
-
LDA 모델을 통해 생성된 주제 출력하고 해석해보기
아래 코드를 붙여넣고, Mallet 을 다운로드 한 경로를 ‘’ 안에 넣어준다. 토픽의 갯수는 우선 20으로 정해두고 이후에 최적화 시켜보겠다.
mallet_path = 'C:/Users/user/Desktop/mallet-2.0.8/bin/mallet'
ldamallet = gensim.models.wrappers.LdaMallet(mallet_path, corpus=corpus, num_topics=20, id2word=id2word)
# Show Topics
pprint(ldamallet.show_topics(formatted=False))
실행버튼을 누르면 아래와 같이 명령프롬프트 창에 바쁘게 모델이 돌아가는 모습을 볼 수 있다.
실행이 끝나면 Jupyter 에 20개의 토픽이 출력된 것을 볼 수 있다.
앞에 나오는 숫자는 토픽의 id, 그 뒤의 단어와 숫자는 각각 그 토픽을 대표하는 keyword와 그 토픽에서의 비중이다.
-
모델 Coherence Score 출력해보기
아래 코드를 실행시키면 모델의 Coherence Score 가 나온다. 이 지수는 높을수록 좋다.
이 매뉴얼에서의 예시는 Coherence 가 아직 낮지만, 위에서 숫자를 조정하면서 높여보거나 Mallet 가 아닌 Gensim 의 내장 LDA 모델을 이용해 결과를 비교하면서 높일 수 있다.
# Compute Coherence Score
coherence_model_ldamallet = CoherenceModel(model=ldamallet, texts=data_lemmatized, dictionary=id2word, coherence='c_v')
coherence_ldamallet = coherence_model_ldamallet.get_coherence()
print('\nCoherence Score: ', coherence_ldamallet)
-
토픽 데이터 시각화 하기
이제 pyLDAvis 를 이용해 모델링 결과를 시각화해보겠다.
아래 코드를 돌리면 몇가지 warning 이 발생하지만 무시해도 괜찮다.
model = gensim.models.wrappers.ldamallet.malletmodel2ldamodel(ldamallet)
pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim.prepare(model, corpus, id2word)
vis
pyLDAvis.save_html(vis, 'LDAMallet_Optimal_disaster.html')
실행 후 jupyter notebook 작업공간이 모두 보이는 Home 에 가보면 내가 설정한 이름의 html 파일이 생긴 것을 볼 수 있다. 이를 열어보자.
아래와 같이 시각화된 데이터를 볼 수 있다. 좌측 상단에 토픽의 id 를 넣거나 마우스로 동그라미 위를 hover 하면 우측의 단어 비중 그래프가 바뀌는 것을 볼 수 있다.
다음 스텝으로 토픽 갯수를 최적화하고 시각화하는 방법을 더 알아보겟슘당
* Reference
https://www.machinelearningplus.com/nlp/topic-modeling-gensim-python/
'컴퓨터 COMPUTER > Urban Data Analytics 데이터분석' 카테고리의 다른 글
(Windows10) ArcPy 를 Jupyter Notebook 과 연결하기 (0) | 2020.07.09 |
---|---|
내 Conda Environment를 Jupyter Notebook 에서 사용하기 (0) | 2020.07.07 |
Windows 10 - Anaconda, Geopandas 8.0 설치 중 HTTP 000 connection 문제, Failed with initial frozen solve 문제 (0) | 2020.07.07 |
[파이썬을 이용한 토픽모델링] : step2. 웹크롤링 툴 (Octoparse) 을 이용해 데이터 수집하기 (1) | 2020.01.29 |
[파이썬을 이용한 토픽모델링] step 1. Python, Jupyter Notebook 설치 (0) | 2020.01.29 |
댓글