2 분 소요

19강 LDA 분석과 결과의 해석

01. 패키지와 데이터 불러오기
import pandas as pd

from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
import re

import gensim
from gensim import corpora
# from sklearn.externals import joblib
import joblib
import sklearn
sklearn.externals.joblib = joblib

16,17강에서 불러왔던 동일한 패키지를 불러오고,

여기서 gensim 패키지에서 corpora를 불러오는데 이는 분석 시에 이전과 같은 word형태로 묶은 것이 아닌 corpus 단위로 저장하기 위해서 사용한다.

en_data=pd.read_csv('wos_ai_.csv', encoding='euc-kr')
en_data_abstract = en_data['ABSTRACT']

실습파일을 불러온다. 여기서 ‘ABSTRACT’열에 해당되는 부분만 en_data_abstract 변수에 저장해준다.

02. 전처리 및 corpus 준비
en_doc = []    #문서집
en_word_joined = []   #문장집
en_word = []    #단어집

전처리를 위한 문서집, 문장집, 단어집에 해당되는 변수를 각각 만들어준다

for doc in en_data_abstract:
    if type(doc) != float:   #숫자가 아닌 문서에 해당되는 부분만
        en_doc.append(doc.replace("-", " ")) #"-"을 공백으로 바꿔 저장

en_stopwords = set(stopwords.words("english")) #불용어 사전 저장
en_stemmer = PorterStemmer()  #어간추출을 위한 명령어 저장

#전처리 과정
for doc in en_doc: 
    en_alphabet = re.sub(r"[^a-zA-Z]+", " ", str(doc)) #알파벳만 추출
    en_tokenized = word_tokenize(en_alphabet.lower()) #소문자화, 토큰화
    en_stopped = [w for w in en_tokenized if w not in en_stopwords] #불용어처리
    en_stemmed = [en_stemmer.stem(w) for w in en_stopped] #어간추출
    en_word_joined.append(' '.join(en_stemmed)) #join해서 문장별로 저장
    en_word.append(en_stemmed) #join하지 않고 전처리된 단어를 저장

dtm, tdm자료를 만들때는 TfidfVectorizer() 명령문을 사용해서 백터라이즈 하기 위해 전처리한 자료를 join하였다.

LDA에서는 join하지 않은 형태로 사용하기 때문에 따로 join하지 않았다.

저장한 en_word_joined와 join하지 않은 en_word를 확인해보자.

image-20230523225856456

en_dict = corpora.Dictionary(en_word)
en_corpus = [en_dict.doc2bow(word) for word in en_word]

en_corpus

en_word를 Dictionary 형태로 만들기 위해서 corpora 패키지의 Dictionary명령어를 사용한다.

그리고 BOW(Back of word 단어가방)형태로 만들기 위해서 반복문 구문으 사용한다. 이렇게 만들어진 en_corpus는 (몇번째단어, 단어의빈도)형태로 저장된다.

image-20230523230159265

이렇게 en_corpus를 확인해보면 2542개의 단어의 빈도가 순서대로 저장되어 있는 것을 확인할 수 있다. 2542번째의 단어가 4번 출현한 것을 확인할 수 있다.

03. LDA 모델링
en_lda = lda_ = gensim.models.ldamulticore.LdaMulticore(en_corpus,iterations=12, num_topics=10,id2word=en_dict, passes=1, workers=10)

gensim 패키지의 models 중에 LDA 명령어를 사용한다

만들어진 BOW인 en_corpus 변수를 사용한다. 여기서 중요한 부분은 num_topics 로 주제를 몇개로 하겠냐는 것이다.

num_topics의 수를 조정해가면서 가장 괜찮은 주제의 수를 선정해주는 것이 좋다.

id2word에서 en_dict를 설정해주는 이유는 기준이 되는 단어인 en_dict를 설정해줘야 출력시에 어떤 단어인지 확인이 된다.

image-20230523230926248

LDA 구조를 먼저 확인해보자. 총 2543개이며 주제는 10개인 것을 확인할 수 있다.

이제 LDA를 통한 결과물을 확인해보자.

image-20230523231258926

LDA의 10개 주제로 나누어진 단어들을 확인해볼 수 있다.

num_words는 해당 주제에서 몇개의 단어만 출력해내겠냐는 설정값이다.

여기서 단어 앞에 계수는 단어가 해당 topic에 등장할 확률이다.

lda = en_lda.print_topics(num_topics=30, num_words=30)

lda_df_all = []
for i in range(0,10) :
    lda_df_a=[]
    col = lda[i][1].split("+")
    lda_df = []
    for j in col :
        lda_df.append(j)
    lda_df_a.append(i)
    lda_df_a.append(lda_df)
    lda_df_all.append(lda_df_a)
    
pd.DataFrame.from_dict(dict(lda_df_all)) 

결과물을 lda로 저장하여서 데이터프레임 형태로 알아보기 쉽게 형태를 바꿔보자.

topic을 열, 단어를 행으로 두고 “+”를 기준으로 잘라준 후에 이를 list형태로 저장한 후에 데이터프레임 형태로 바꿔주었다.

image-20230523231735905

  • 0번째 주제의 단어를 보면 [ai, develop, techniqu, power] 등 산업에 관련되어 있고,
  • 1번째 주제의 단어를 보면 [algoithm, prefrom, reserch, featur ] 등을 보면 방법론에 대한 주제일 것 같고,
  • 2번째 주제의 단어를 보면 [dics, time, nerural] 등을 보면 신경망에 관련된 주제일 것이라 보인다.
  • 대부분 20번째까지의 단어들은 모든 topic에서 자주 쓰이기 때문에 단어들을 30개가 아니라 50개 정도 더 많이 확인을 해서 주제의 특성을 잡는 것이 좋다.
04. 시각화를 위한 파일 저장

다음 챕터의 시각화를 위해 파일을 저장해보자.

en_dict.save_as_text('en_lda_dict.txt')

위에서 만들었던 dictionary로 단어를 저장한 en_dict를 텍스트 파일로 저장해주고

corpora.MmCorpus.serialize('en_lda_corpus.mm', en_corpus)

bow형태로 저장한 en_corpus 변수는 corpora에서 제공하는 명령어를 통해 저장해준다.

joblib.dump(en_lda, 'en_lda_model.pkl')

마지막으로 lda모델을 저장해주면 다음 챕터를 위한 준비작업은 끝이난다.

댓글남기기