import numpy as np
def preprocess(text):
= text.lower()
text = text.replace(".", " .")
text = text.split(' ')
words
= {}
word_to_id = {}
id_to_word
for word in words:
if word not in word_to_id:
= len(word_to_id)
new_id = new_id
word_to_id[word] = word
id_to_word[new_id] = np.array([word_to_id[w] for w in words])
corpus return corpus, word_to_id, id_to_word
자연어와 단어의 분산 표현
deep learning
자연어 처리(NLP)
- 우리 말을 컴퓨터에게 이해시키기 위한 기술
- 기계 번역, 검색, 등
시소러스
- 사람이 직접 레이블링 한 유의어 사전
- 대표적으로 WordNet이 있다.
한계
- 시대 변화에 따라 단어의 의미가 바뀌는 경우가 있다.
- 사람 쓰는 비용이 크다.
- 단어의 미묘한 차이를 표현할 수 없다.
통계 기반 기법
- 말뭉치: 언어의 실제 사용 예시를 모은 텍스트 데이터
- 위키백과, 뉴스 기사, 블로그 글 등
= "The quick brown fox jumps over the lazy dog."
text = preprocess(text) corpus, word_to_id, id_to_word
단어의 분산 표현
- 단어의 의미를 벡터로 표현하는 방법
- 분포 가설: 단어의 의미는 그 단어의 주변 단어들(맥락)에 의해 결정된다.
def create_co_matrix(corpus, vocab_size, window_size=1):
= np.zeros((vocab_size, vocab_size), dtype=np.int32)
co_matrix = len(corpus)
corpus_size
for idx, word_id in enumerate(corpus):
= max(0, idx - window_size)
left = min(corpus_size, idx + window_size + 1)
right for i in range(left, right):
if i == idx:
continue
+= 1
co_matrix[word_id, corpus[i]] return co_matrix
def cos_similarity(x, y, eps=1e-8):
= x / (np.sqrt(np.sum(x**2)) + eps)
nx = y / (np.sqrt(np.sum(y**2)) + eps)
ny return np.dot(nx, ny)
= len(word_to_id)
vocab_size = create_co_matrix(corpus, vocab_size, window_size=1)
C
= C[word_to_id['the']]
C0 = C[word_to_id['dog']]
C1 = cos_similarity(C0, C1)
similarity similarity
0.4082482852200891
유사 단어 랭킹
def most_similar(query, word_to_id, id_to_word, C, top=5):
if query not in word_to_id:
print(f"{query}는 사전에 없습니다.")
return None
= word_to_id[query]
query_id = C[query_id]
query_vec
= C.shape[0]
vocab_size = np.zeros(vocab_size)
similarity
for i in range(vocab_size):
= cos_similarity(query_vec, C[i])
similarity[i]
# 유사도 순으로 정렬
= 0
count for i in (-1 * similarity).argsort():
if id_to_word[i] == query:
continue
print(f"{id_to_word[i]}: {similarity[i]:.4f}")
+= 1
count if count >= top:
return
통계 기반 기법 개선
이전 방법의 한계
- 단어의 의미를 벡터로 표현하는 방법이 단순히 주변 단어의 빈도수에 의존한다.
- 점별 상호정보량(PMI)
def ppmi(C, eps=1e-8):
= np.zeros_like(C, dtype=np.float32)
M = np.sum(C)
N = np.sum(C, axis=0)
S
for i in range(C.shape[0]):
for j in range(C.shape[1]):
= np.log2((C[i, j] * N) / (S[i] * S[j]) + eps)
pmi = max(0, pmi)
M[i, j] return M