단어 임베딩 : 단어를 낮은 차원의 벡터로 나타내는 것
단어 임베딩 만드는 방법
Word2Vec
FastText
Word2Vec은 등록된 어휘의 임베딩만 만들 수 있음
FastTest는 새로운 어휘의 임베딩도 만들 수 있게 한 방법
한 단어를 n-gram으로 분해
(예) Orange → or, ora, ran, ang, nge, ge_
각 n-gram의 임베딩을 더하면 단어의 임베딩이 되도록 학습
import re
def find_hangul(text):
return re.findall(r'[ㄱ-ㅎ가-힣]+', text)
data = nsmc['document'].map(find_hangul)
from gensim.models.fasttext import FastText
ft = FastText(vector_size=16) # 단어 하나당 16개 vector를 활용해서 표현
# 어휘를 파악
ft.build_vocab(corpus_iterable=data)
# 학습
ft.train(
corpus_iterable=data,
epochs=5,
total_examples=ft.corpus_count,
total_words=ft.corpus_total_words
)
# 임베딩 보기
ft.wv['히어로'] # 16개..
ft.wv.similarity('슈퍼히어로', '히어로')
ft.wv.most_similar('송강호')
문서 임베딩
FastTest를 이용한 감성 분석
import numpy as np
x = np.zeros((1000, 16)) #1000개만
doc = nsmc['document'].iloc[:1000]
y = nsmc['label'].values[:1000]
for i, d in enumerate(doc):
vs = [ft.wv[word] for word in find_hangul(d)]
if vs:
x[i,] = np.mean(vs, axis=0) # 모든 단어들의 임베딩을 평균 낸 것
# 분할
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test, idx_train, idx_test = train_test_split(
x, y, doc.index, test_size=0.2, random_state=42)
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(x_train, y_train)
model.score(x_test, y_test)
코사인 유사도(단어 임베딩에 주로 쓰는 유사도)
*|a||b| : 값 크기 보정
임베딩을 이용한 검색: 느리다
import numpy as np
from sklearn.metrics.pairwise import cosine_distances, cosine_similarity
%%time
i = 1
d = cosine_distances([x_test[i]], x_train)
ids = np.argsort(d)[0, :3]
# ms는 굉장히 긴 시간임
dist = np.sort(d)[0, :3]
for j, d in zip(ids, dist):
idx = idx_train[j]
print(f'{d:.02f}', idx, nsmc.loc[idx, 'document'], nsmc.loc[idx, 'label'])
ANN(Aproximate Nearest Neighbor Search)
트리를 이용한 문서 검색
해서(hasher)를 이용한 문서 검색
위계적 탐색 가능한 작은 세상 네트워크(Hierarchical Navigable Small World network)