티스토리 뷰
1. 점별 상호 정보량 (PMI)
PMI의 식은 다음과 같습니다.
P(x), P(y)는 x,y가 일어날 확률, P(x,y)는 x,y가 동시에 일어날 확률입니다.
이를 동시발생행렬에 적용해봅시다.
N은 말뭉치에 포함된 단어의 수, C(x), C(y)는 x,y의 등장 횟수, C(x,y)는 x,y의 동시 발생 횟수입니다.
이를 이용해 N=10,000, "the"=1,000, "car"=20, "drive"=10, "the, car"=10, "car, drive"=5 라고 한다면
PMI("the","car") ≒ 2.32, PMI("car", "drive") ≒ 7.97 입니다.
이를 이용하면, the라는 것이 많이 나왔지만, car와 drive의 연관성이 더 큰 값을 나타내는 것을 알 수 있습니다.
PMI의 경우 동시 발생횟수가 0인 경우 log(0) = -inf 이므로 PPMI를 이용합니다.
import numpy as np
def ppmi(C, verbose=False, eps=1e-8):
M = np.zeros_like(C, dtype=np.float32)
N = np.sum(C)
S = np.sum(C, axis=0)
total = C.shape[0] * C.shape[1]
cnt = 0
for i in range(C.shape[0]):
for j in range(C.shape[1]):
pmi = np.log2(C[i,j]*N / (S[j]*S[i]) + eps)
M[i,j] = max(0, pmi)
if verbose:
cnt += 1
if(cnt % (total//100) == 0):
print("%.1f%% 완료" %(100*cnt/total))
return M
2. 차원 감소
위 ppmi를 이용해 M을 구하면 0이 많은 것을 알 수 있습니다. 그렇기 때문에 시간과 메모리를 줄이면서 중요한 정보를 유지하고자 하는것이 차원 감소입니다.
- 특이값 분해 (SVD)
SVD는 임의의 행렬을 세 행렬의 곱으로 분해하며 식은 다음과 같습니다.
여기서 U, V는 직교행렬 (orthogonal matrix)이고, S는 대각행렬 (diagonal matrix)입니다.
U는 단어 공간으로 취급할 수 있고, S는 특이값(singular value)이 내림차순으로 나열되어 있습니다.
이를 이용해 X에 있는 단어 id에 해당하는 단어 벡터의 일부를 U, S, V를 활용하여 중요도가 낮은 원소는 제거할 수 있스니다.
import sys
sys.path.append('..')
import numpy as np
import matplotlib.pyplot as plt
from common.util import preprocess, create_co_matrix, ppmi
text = "You say goodbye and I say hello."
corpus, word_to_id, id_to_word = preprocess(text)
vocab_size = len(id_to_word)
C = create_co_matrix(corpus, vocab_size)
W = ppmi(C)
U, S, V = np.linalg.svd(W)
for word, word_id in word_to_id.items():
plt.annotate(word, (U[word_id,0], U[word_id,1]))
plt.scatter(U[:,0], U[:,1], alpha=0.5)
plt.show()
보다시피 hello와 goodbye가 상관관계가 높고, you와 i의 상관관계가 높음을 알 수 있습니다. (goodbye랑 i랑 겹침)
3. PTB 데이터셋에 적용
PTB (펜 트리뱅크)의 내용을 하나의 큰 문장으로 처리한 데이터가 여기에 존재합니다.
github.com/WegraLee/deep-learning-from-scratch-2
데이터 이용 방법은 책을 참고하면 됩니다.
이를 sklearn을 이용해 PTB데이터셋에 적용해 봅시다.
import sys
sys.path.append('..')
import numpy as np
from common.util import most_similar, create_co_matrix, ppmi
from dataset import ptb
window_size = 2
wordvec_size = 100
corpus, word_to_id, id_to_word = ptb.load_data('train')
vocab_size = len(word_to_id)
C = create_co_matrix(corpus, vocab_size, window_size)
W = ppmi(C, verbose=True)
print("SVD계산")
try:
from sklearn.utils.extmath import randomized_svd
U,S,V = randomized_svd(W, n_components=wordvec_size, n_iter=5, random_state=None)
except ImportError:
print("sklearn 모듈 불러오기 실패")
U,S,V = np.linalg(W)
word_vecs = U[:, :wordvec_size]
querys = ['you', 'year', 'car', 'toyota']
for query in querys:
most_similar(query, word_to_id, id_to_word, word_vecs, top=5)
결과 (random값을 활용하여 실행마다 결과는 조금 다릅니다.)
[query] you
i: 0.6775782108306885
we: 0.6531620025634766
do: 0.5528689026832581
've: 0.5055562257766724
anybody: 0.5042886734008789
[query] year
month: 0.7258844375610352
quarter: 0.6563577055931091
earlier: 0.636909544467926
last: 0.601109504699707
fiscal: 0.5889010429382324
[query] car
luxury: 0.6932957768440247
auto: 0.6356461644172668
cars: 0.5667458176612854
vehicle: 0.5311421751976013
domestic: 0.5154250860214233
[query] toyota
motors: 0.6816779375076294
motor: 0.6634222865104675
nissan: 0.6418960690498352
honda: 0.6062759160995483
lexus: 0.5848075747489929
해당 쿼리마다 연관된 것으로 알 수 있는 단어들이 출력되었습니다.
'딥러닝' 카테고리의 다른 글
네거티브 샘플링 (0) | 2021.01.27 |
---|---|
CBOW 1 (0) | 2021.01.26 |
통계 기반 기법 1 (0) | 2021.01.23 |
스파이럴 데이터셋을 이용한 신경망 학습 (0) | 2021.01.22 |
밑바닥부터 시작하는 딥러닝 1권 후기 (0) | 2021.01.20 |