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