logo

LSA 실습

colab 한글 글꼴 설정

  • colab에 글꼴 설치
!apt install fonts-nanum
!fc-cache -fv
!rm ~/.cache/matplotlib -rf
  • 글꼴 설치 후 메뉴에서 런타임 → 세션 다시 시작

colab 한글 글꼴 설정

# 글꼴 이름 찾기
from matplotlib import font_manager
for font in font_manager.fontManager.ttflist:
    if 'Nanum' in font.name:
        print(font.name, font.fname)

# 글꼴 설정
import matplotlib.pyplot as plt
plt.rc('font', family='NanumGothic')

전처리 (지난 주와 같음)

!pip install kiwipiepy
import kiwipiepy
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer

kiwi = kiwipiepy.Kiwi()
def extract_nouns(text):
    for token in kiwi.tokenize(text):
        if token.tag in {'NNG', 'NNP'}:
            yield token.form

df = pd.read_excel('patents.xlsx')
cv = CountVectorizer(tokenizer=extract_nouns, min_df=10)
dtm = cv.fit_transform(df.abstract)

SVD 적용

  • 문서 단어 행렬에 SVD 적용, 100차원으로 축소
from sklearn.decomposition import TruncatedSVD
svd = TruncatedSVD(n_components=100, random_state=1234)
doc_emb = svd.fit_transform(dtm)

문서 임베딩의 코사인 유사도

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

sim = cosine_similarity(doc_emb[[0]], doc_emb) # 문서 임베딩의 코사인 유사도
rank = np.argsort(sim[0]) # 유사도 순으로 정렬
rank = rank[::-1] # 내림차순으로 바꿈
df.iloc[rank].head() # 가장 비슷한 문서 5개

유사 난수 pseudorandom number

  • 대부분의 컴퓨터는 결정론적(deterministic)으로 작동하여 난수(random number)를 생성할 수 없음
  • 아주 긴 주기의 수열을 만들어 유사 난수로 사용
  • 간단한 알고리즘:
  • 씨앗값으로부터 일정 항 이후부터 사용
  • 보통 씨앗값은 현재 시각으로 결정
  • 같은 결과를 재현하려고 할 때는 씨앗값을 고정하여 동일한 유사난수를 생성

스크리 플롯 scree plot

  • TruncatedSVD에서 "설명된 분산"의 시각화
  • PCA와 다르게 완전히 정렬되어 있지 않음
  • 절벽 밑의 비탈(scree) 모양
import matplotlib.pyplot as plt
plt.plot(svd.explained_variance_)
for i, txt in enumerate(svd.explained_variance_):
    plt.text(i, txt, str(i))
  • 완만한 경사가 시작하는 부분(대략 15번)이 적정한 컴포넌트의 수 → 15차원으로 줄임
from sklearn.decomposition import TruncatedSVD
svd = TruncatedSVD(n_components=15, random_state=1234)
doc_emb = svd.fit_transform(dtm)

단어 임베딩

word_emb = svd.components_.T
  • 단어 text의 번호
words = cv.get_feature_names_out().tolist()
i = words.index('모발')
  • 단어와 각 토픽의 관련도를 시각화
plt.plot(word_emb[i])

단어임베딩의 코사인 유사도

  • 코사인 유사도 구하기
from sklearn.metrics.pairwise import cosine_similarity
sim = cosine_similarity(word_emb)
  • 유사도 높은 단어 10개 보기
import numpy as np
rank = np.argsort(sim[i]) # i번째 단어와 유사도 순으로 정렬
rank = rank[::-1]         # 역순

[words[j] for j in rank[:10]]

두 임베딩을 시각적으로 비교

j = words.index('손상')
fig, ax1 = plt.subplots()
ax1.plot(word_emb[j])
ax2 = ax1.twinx() # ax1을 복제하여 새로운 y축을 가진 ax2를 생성
ax2.plot(word_emb[i], color='r', label=words[i])

모든 임베딩을 시각화

  • tSNE 기법을 이용해서 가까운 임베딩은 가깝게, 먼 임베딩은 멀게 시각화
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2, random_state=1234, init='pca', learning_rate='auto')
word_emb_2d = tsne.fit_transform(word_emb)

plt.figure(figsize=(10, 10))
plt.scatter(word_emb_2d[:, 0], word_emb_2d[:, 1], alpha=0.5)

words = cv.get_feature_names_out().tolist()
for i, word in enumerate(words):
    plt.annotate(word, (word_emb_2d[i, 0], word_emb_2d[i, 1]), fontsize=9, alpha=0.8)
Previous
잠재 의미 분석(LSA)