Dev.log

문서간 유사도: Jaccard Similarity & Cosine Similarity 본문

자연어처리

문서간 유사도: Jaccard Similarity & Cosine Similarity

포켓몬빵 2022. 4. 29. 20:03

자연어처리분야에서의 유사도(similarity)란 비슷한 정도를 나타내는 지표를 의미합니다. 하지만 유사도는 주관적인 지표로 작용될 수 있는데, 이를 정량화 하기위해 유클리디안 거리, 맨하튼 거리, 피어슨 상관 계수, 코사인 유사도, 자카드 유사도과 같은 수치로 표현하였습니다. 이러한 유사도 방법중 본 포스팅에서는자카드 유사도(Jaccard Simiarity)와 코사인 유사도(Cosine Similarity)에 대해 진행해 보도록하겠습니다.

 

Jaccard 유사도

Jaccard 유사도는 두 집합간의 유사도를 측정하는 방법으로써, 두 집합을 문서로 적용시키면, 두 문서간의 교집합의 크기를  합집합 크기로 나눈 값을 의미합니다. 즉, 0에서 1까지의 범위의 두 데이터 세트에 대한 유사도 측정값으로써 1에 가까울 수록 두 모집단이 더 유사하다고 판단 할 수 있습니다. 자카드 유사도는 아래의 수식으로 표현 할 수있습니다.

예를 들어, A = {0,1,2,5,6}와 B = {0,2,3,4,5,7,9} 두가지 집합이 존재한다고 했을때, J(A,B)는 |A∩B| / |A∪B| 이므로, |{0,2,5}| / |{0,1,2,3,4,5,6,7,9}|로 표현할 수 있습니다. 이는 3/9으로 0.33의 유사성을 지닌다고 할 수 있습니다. 하지만 자카드 유사도는 작은 샘플 크기에 극도로 민감하고 특히 매우 작은 샘플이나 누락된 관찰이 있는 데이터 세트의 경우 잘못된 결과를 제공할 수 있습니다. 이러한 자카드 유사도는 아래의 코드와 같이 나타낼 수 있습니다.

def jaccard(list1, list2):
    s1 = set(list1)
    s2 = set(list2)
    return float(len(s1.intersection(s2)) / len(s1.union(s2)))

이를 통해 두 문장이 주어졌을 때 자카드 유사도를 확인해 보겠습니다.

list1 = ['dog', 'cat', 'cat', 'rat']
list2 = ['dog', 'cat', 'mouse']
jaccard(list1, list2)

>> 0.5

 

Cosine 유사도

코사인 유사도는 문서를 벡터화 시켜서 두 벡터 간의 코사인 각도를 이용하여 구할 수 있는 유사도를 의미합니다. 두 벡터의 방향이 완전히 동일한 경우에는 1의 값을 가지며, 90°의 각을 이루면 0, 180°로 반대의 방향을 가지면 -1의 값을 갖게 됩니다. 즉 코사인 유사도는 값이 1에 가까울수록 두 문서간의 유사도가 높다고 판단할 수 있습니다.

위의 수식은 아래의 코드와 같이 표현 할 수 있습니다.

from numpy import dot
from numpy.linalg import norm

def cos_sim(A, B):
  return dot(A, B)/(norm(A)*norm(B))

이제 간단한 두 문장간간의 코사인 유사도를 확인해 보겠습니다. 이번에는 별도의 전처리나 토큰화 과정을 거치지 않고 TF-IDF를 통해 백터화 시킨 이후, 코사인 유사도를 구해보겠습니다.

li = ['스타트업기업의 창업성공률 제고를 위한 창업금융의 효율적 운영 방안 연구' ,
      '4차 산업혁명시대에 민관의 청년창업활성화를 위한 효율적인 협조금융체계의 개편방안 연구']

tfidf_vect_simple = TfidfVectorizer()
feature_vect_simple = tfidf_vect_simple.fit_transform(li)

# Dense Matrix 형태로 변환. 
feature_vect_dense = feature_vect_simple.todense()

#리스트 내 첫번째 문장과 두번째 문장의 feature vector 추출
vect1 = np.array(feature_vect_dense[0]).reshape(-1,)
vect2 = np.array(feature_vect_dense[1]).reshape(-1,)

#Cosine 유사도 추출
similarity_simple = cos_sim(vect1, vect2)
print('문장 1과 문장 2의 코사인 유사도 : {0:.3f}'.format(similarity_simple))


>>>  문장 1과 문장 2의 코사인 유사도 : 0.126

'자연어처리' 카테고리의 다른 글

Sentence BERT  (0) 2022.05.11
Bag of Words  (0) 2022.05.10
How to write a spelling corrector  (0) 2022.04.29
SentiwordNet  (0) 2022.04.23
Semantic Network Analysis  (0) 2022.04.23
Comments