문서들 간에 유사도를 구하기 위해서는 문서마다 동일한 단어나 비슷한 단어가 얼마나 사용되었는지를 파악할 수 있다. BoW, DTM, TF-IDF, Word2Vec 등의 방법으로 단어를 수치화 했다면, 유사도 기법을 사용하여 문서의 유사도를 구하는 게 가능하다.


  1. 코사인 유사도(Cosine similarity) 는 두 벡터의 방향에 따라 1~ -1 의 값을 가지며 1에 가까울수록 유사하다.
  2. 유클리드 거리(Euclidean distance) 는 두 점 사이의 직선 거리를 구하여 거리의 값이 작을수록 유사하다.
  3. 자카드 유사도(Jaccard similarity) 는 두개의 집합이 있을 때 합집합에서 교집합의 비율을 구하며, 1에 가까울 수록 유사하다.


문서1 : 저는 사과 좋아요

문서2 : 저는 바나나 좋아요

문서3 : 저는 바나나 좋아요 저는 바나나 좋아요


위 문서간의 유사도 구하기


from sklearn.feature_extraction.text import CountVectorizer
from numpy import dot
from numpy.linalg import norm
import numpy as np
 
corpus = [
    "저는 사과 좋아요",
    "저는 바나나 좋아요",
    "저는 바나나 좋아요 저는 바나나 좋아요",
]
vector = CountVectorizer()
dtm = vector.fit_transform(corpus).toarray()
print(dtm)
# [[0 1 1 1]
#  [1 0 1 1]
#  [2 0 2 2]]
 
def cos_sim(A, B):
    return dot(A, B) / (norm(A)*norm(B))
 
print(cos_sim(dtm[0], dtm[1])) #문서1과 문서2의 코사인 유사도 0.6666666666666667
print(cos_sim(dtm[0], dtm[2])) #문서1과 문서3의 코사인 유사도 0.6666666666666667
print(cos_sim(dtm[1], dtm[2])) #문서2과 문서3의 코사인 유사도 1.0000000000000002
 
def dist(A, B):
    return np.sqrt(np.sum((A-B)**2))
 
print(dist(dtm[0], dtm[1])) #문서1과 문서2의 유클리드 거리 1.4142135623730951
print(dist(dtm[0], dtm[2])) #문서1과 문서3의 유클리드 거리 2.6457513110645907
print(dist(dtm[1], dtm[2])) #문서2과 문서3의 유클리드 거리 1.7320508075688772
 
corp1 = corpus[0].split()
corp2 = corpus[1].split()
corp3 = corpus[2].split()
 
def jaccard(A, B):
    union = set(A).union(set(B))  # 합집합
    intersection = set(A).intersection(set(B))  # 교집합
    return len(intersection) / len(union)
 
print(jaccard(dtm[0], dtm[1])) #문서1과 문서2의 자카드 유사도 1.0
print(jaccard(dtm[0], dtm[2])) #문서1과 문서3의 자카드 유사도 0.3333333333333333
print(jaccard(dtm[1], dtm[2])) #문서2과 문서3의 자카드 유사도 0.3333333333333333
cs


위 코드에서 처럼 문서의 유사도의 성능은 각 문서의 단어들의 수치화 방법, 유사도 방법에 따라 다르다는 것을 알 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,