2 분 소요

23강 doc2vec Modeling 실습

저번에는 word2vec을 진행해보았다. 단어를 딥러닝 방법으로 고차원 시켜서 좌표값으로 표현을 해내었다. 이는 더 자세하고 정교한 분석을 위함이었다.

이번 doc2vec에선 문서간의 유사성을 파악해보는 것이다. 그래서 문서들의 관계를 태그를 붙여서 확인해보고자 한다.

doc2vec의 간단한 개념정리
  • 하나의 문서를 구성하는 단어들의 평균 좌표를 구해서 문서의 대표적인 좌표를 구성하게 된다.
  • 이러한 문서의 대표적인 좌표가 word2vec 기반으로 doc2vec 좌표를 구성하게 되는 것이다. 이때, word2vec와 같이 문서간의 유사성을 살펴볼 수 있게 된다.
01. 패키지 및 데이터 불러오기

word2vec와 유사한 부분은 설명을 생략하고 넘어가자.

import pandas as pd

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

from gensim import models
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
en_data=pd.read_csv('wos_ai_.csv', encoding='euc-kr')
en_data_abstract = en_data['ABSTRACT']
02. 데이터전처
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))
    en_word.append(en_stemmed)

패키지 불러오기와 데이터 전처리를 22강 word2vec와 동일하게 진행하면 된다.

03. 문서 tagging
en_article_tag = []
en_article_tag_count = 0
for item in en_word:
    model = models.doc2vec.TaggedDocument(words=item, tags=['sent_{}'.format(en_article_tag_count)])
    en_article_tag.append(model)
    en_article_tag_count += 1

문서별로 좌표를 정해주기 위해서 일련번호를 주기 위해서 en_article_tag와 en_article_tag_count 변수를 불러온다.

  • models.doc2vec.TaggedDocument 명령문을 통해서 전처리된 en_word의 단어를 단어별로 tag를 달아주게 된다.
  • 그리고 그 결과를 en_article_tag로 달아줌으로써 태그를 달아주는 태깅을 해준다.
04. doc2vec 모델
en_d2v_model = models.Doc2Vec(vector_size=300, window=5, workers=4,
                                    alpha=.025, min_alpha=.025, min_count=1)

word2vec와 비슷하게 옵션값을 Doc2Vec로 부여해 준다.

en_d2v_model.build_vocab(en_article_tag[0::])

build_vocab 명령문을 통해서 단어를 문서별로 넣어주는 작업을 진행한다.

for epoch in range(10):
    en_d2v_model.train(en_article_tag[0::], total_examples=en_d2v_model.corpus_count,
                             total_words=None, epochs=en_d2v_model.epochs)
    en_d2v_model.alpha -= 0.002
    en_d2v_model.min_alpha = en_d2v_model.alpha

이 부분은 옵션 부분으로 모델링을 위해 train 해주기 위해 en_d2v_model.train 명령문을 사용하고 alpha와 min_alpha 값을 지정해준다.

05. 문서차원좌표 저장 및 확인
en_d2v_model.save('en_d2v_model.bin')

이제 bin파일로 저장하는데 그 이유는 나중에 불러와서 좌표화하고 계산하기 이함이다. bin파일이 모델이 돌아간 결과가 된다. 이를 다시 불러와보자.

en_d2v_model = models.Doc2Vec.load('en_d2v_model.bin')

이렇게 한번 저장하고 다시 불러오는 이유는 학습된 데이터를 가지고 분석을 하는 논리이기 때문에 다시 저장하고 분석을 진행해보는 것이다.

#en_d2v_dimension = pd.DataFrame.from_records(en_d2v_model.docvecs.vectors)
#en_d2v_dimension.to_csv('dimension_result.csv', sep=',', header=True, index=False, index_label=None)
en_d2v_dimension = pd.DataFrame.from_records(en_d2v_model.dv.vectors)
en_d2v_dimension.to_csv('dimension_result.csv', sep=',', header=True, index=False, index_label=None)

버전이 바뀌면서 docvecs가 dv로 바뀌었기 때문에 이전 값을 주석처리해주고 dv로 바꾸어 사용하였다.

메모리에 저장된 데이터를 데이터프레임 형태로 불러오기 위해 pd.DataFrame.from_recorods 명령어를 사용하였다.

en_d2v_dimension 출력 결과를 살펴보자.

image-20230525192949245

119개의 문서별로 300차원의 좌표값을 확인해볼 수 있다.

이제 결과값들을 확인해보자. 문서1번과 가장 비슷한 문서가 무엇인지 확인해보자.

image-20230525193150502

1번 문서와 가장 비슷한 문서는 13번 문서임이 확인 되었다.

그렇다면 1번과 9번과의 유사성은 어떻게 될까?

image-20230525193238321

19%로 그렇게 높지 않은 유사성을 보인다.

sent_1 문서의 좌표를 확인해보면 아래와 같은 300차원의 값을 확인해볼 수 있다.

image-20230525193311772

이렇게 구해진 값을 ‘dimension_result.csv’ 파일로 저장을 하고 시각화해보자.

en_d2v_dimension.to_csv('dimension_result.csv', sep=',', header=True, index=False, index_label=None)
06. 문서 TSNE 시각화
def d2v_tsne_plot(dimension):

    tsne = TSNE(learning_rate=100).fit_transform(dimension)

    x = []
    y = []
    for value in tsne:
        x.append(value[0])
        y.append(value[1])

    plt.figure(figsize=(16, 16))
    for i in range(len(x)):
        plt.scatter(x[i], y[i])
        plt.annotate(i,
                     xy=(x[i], y[i]),
                     xytext=(5, 2),
                     textcoords='offset points',
                     ha='right',
                     va='bottom')
    plt.show()

word2vec와 비슷한 설정값을 부여해주고, 반복문을 통해서 value[0]은 문서에 대한 값을 x축으로 value[1] 좌표값을 y축으로 해서 append 해준다.

이제 결과물을 확인해보자.

d2v_tsne_plot(en_d2v_dimension)

image-20230525193751753

300차원을 2차원으로 축소했기에 손실되는 정보가 있지만 유사하게 가까운 좌표값을 가지는 몇몇 값을 확인할 수 있다. 이렇게 word2vec를 통해서 전체 문서가 유사한게 무엇인지 찾아낼 수 있게 된다.

댓글남기기