문서 유사도(Document Similarity)

개요

일반적으로 사람은 문서들 간에 동일한 단어 또는 비슷한 단어가 얼마나 공통적으로 많이 사용되었는지에 의존하여 문사의 유사도를 측정한다. 머신 또한 해당 정보를 바탕으로 각 문서의 단어들을 여러 방법으로 수치화한 후, 각 벡터 간의 유사도를 측정함으로써 계산이 가능해진다.

코사인 유사도(Cosine Similarity)

코사인 유사도는 두 벡터 간의 코사인 각도를 이용하여 구할 수 있는 두 벡터의 유사도를 의미한다. 두 벡터의 방향이 완전히 동일한 경우에는 1, 완전히 반대 방향의 성격을 가질 경우 -1을 반환하게 되며, 무조건 해당 값 사이로 유사도 정보를 반환한다.

두 벡터 A, B에 대해서 코사인 유사도는 식으로 표현하면 다음과 같다.

예를 들어 다음과 같은 행렬을 벡터로 취급하여 코사인 유사도를 계산해보면 다음과 같이 결과가 나온다.

from numpy import dot
from numpy.linalg import norm
import numpy as np
def cos_sim(A, B):
       return dot(A, B)/(norm(A)*norm(B))
       
doc1=np.array([0,1,1,1])
doc2=np.array([1,0,1,1])
doc3=np.array([2,0,2,2])
print(cos_sim(doc1, doc2)) 
print(cos_sim(doc1, doc3)) 
print(cos_sim(doc2, doc3))
# 0.67
# 0.67
# 1.00

유클리드 거리(Euclidean distance)

유클리드 거리(euclidean distance)는 다차원 공간에서 점과 점 사이의 거리를 구하는 비교적 매우 직관적인 공식이다. 두 개의 점 p와 q가 각각 p=(p1,p2,p3,...,pn)q=(q1,q2,q3,...,qn)의 좌표를 가질 때 두 점 사이의 거리를 계산하는 유클리드 거리 공식은 다음과 같다.

import numpy as np
def dist(x,y):   
    return np.sqrt(np.sum((x-y)**2))

doc1 = np.array((2,3,0,1))
doc2 = np.array((1,2,3,1))
doc3 = np.array((2,1,2,2))
docQ = np.array((1,1,0,1))

print(dist(doc1,docQ))
print(dist(doc2,docQ))
print(dist(doc3,docQ))
# 2.23606797749979
# 3.1622776601683795
# 2.449489742783178

자카드 유사도(Jaccard similarity)

자카드 유사도는 벡터가 아닌 단어의 빈도수를 집합 개념으로 보고, 교집합을 통해 유사도를 측정하는 방법이다. 자카드 유사도를 구하는 함수를 J라고 하였을 때, 자카드 유사도 함수 J는 아래와 같다.

doc1 = "apple banana everyone like likey watch card holder"
doc2 = "apple banana coupon passport love you"

# 토큰화를 수행합니다.
tokenized_doc1 = doc1.split()
tokenized_doc2 = doc2.split()

# 토큰화 결과 출력
print(tokenized_doc1)
print(tokenized_doc2)
# ['apple', 'banana', 'everyone', 'like', 'likey', 'watch', 'card', 'holder']
# ['apple', 'banana', 'coupon', 'passport', 'love', 'you']

union = set(tokenized_doc1).union(set(tokenized_doc2))
intersection = set(tokenized_doc1).intersection(set(tokenized_doc2))
print(len(intersection)/len(union))
# 0.16666666666666666

Last updated