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)를 생성할 수 없음
- 아주 긴 주기의 수열을 만들어 유사 난수로 사용
- 간단한 알고리즘: xn+1=(a⋅xn+c)(modm)
- 씨앗값으로부터 일정 항 이후부터 사용
- 보통 씨앗값은 현재 시각으로 결정
- 같은 결과를 재현하려고 할 때는 씨앗값을 고정하여 동일한 유사난수를 생성
스크리 플롯 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)
퀴즈
문서 임베딩 간의 코사인 유사도를 구하는 주된 목적은 무엇인가요?
퀴즈를 풀려면 대화형 기능을 불러와야 합니다.