코사인 유사도 cosine similarity

정의

  • 두 벡터 사이의 유사도를 판단하기 위해 사용하는 계산 방법, 혹은 유사도 값
  • 두 벡터의 방향이 동일하면 1의 값을 가지고, 직교하면 0을 가지게 된다.
  • 방향이 동일하면 유사성이 높은 것이고, 직교한다면 유사성이 없는 것이다.
  • 자연어처리에서는 단어 또는 문서 벡터 사이의 유사도를 비교하기 위해 사용될 수 있다.

계산법

\[\text{similarity} = \cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|} = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}}\]
  • 코사인 유사도는 두 벡터의 내적을 두 벡터의 크기(길이) 곱으로 나눈 것이다.
  • 쉽게 말해 두 벡터가 크기(길이)에 상관 없이 방향이 얼마나 유사한가를 측정하는 것이다.
  • 분자 : 두 벡터의 내적
  • 분모 : 두 벡터 크기의 곱

보통 코사인 유사도를 계산할 때에는 unit length로 만든 뒤 계산한다.
unit length 란, 벡터의 길이가 1이란 뜻이다. (||a|| = ||b|| = 1)
그 이유는, unit length 로 만들 경우 분모 계산 필요 없이 두 벡터의 점곱만으로 간단하게 연산할 수 있기 때문이다.

코드

직접 계산해보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import numpy as np

vector_a = (1, 10)
vector_b = (3, 2)

# cosine similarity (직접 구축)
def cosine_similarity(vector_a, vector_b):
    
    # type check
    arr_a = vector_a if isinstance(vector_a, np.ndarray) else np.array(vector_a)
    arr_b = vector_b if isinstance(vector_b, np.ndarray) else np.array(vector_b)
    
    # dimension check
    if arr_a.shape != arr_b.shape:
        raise ValueError("dimension dismatched")
    
    # cosine similarity
    length_sum_a = 0
    length_sum_b = 0
    point_mul_sum = 0
    for point_a, point_b in zip(arr_a, arr_b):
        length_sum_a += point_a**2
        length_sum_b += point_b**2
        point_mul_sum += point_a * point_b
    
    cosine_similarity = point_mul_sum / ((length_sum_a**0.5) * (length_sum_b**0.5))

    return cosine_similarity

print(cosine_similarity(vector_a, vector_b))
>> np.float64(0.6347394233600139)

numpy 라이브러리를 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
# cosine similarity (numpy)
import numpy as np
from numpy import dot
from numpy.linalg import norm

vector_a = (1, 10)
vector_b = (3, 2)

arr_a = np.array(vector_a)
arr_b = np.array(vector_b)

print(dot(arr_a, arr_b) / (norm(arr_a)*norm(arr_b)))
>> np.float64(0.6347394233600139)

gensim 라이브러리를 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# cosine similarity (gensim)
from gensim.matutils import cossim

vector_a = (1, 10)
vector_b = (3, 2)

arr_a = np.array(vector_a)
arr_b = np.array(vector_b)

# 희소행렬로 변환
# gensim 의 경우 계산 대상인 vector를 generator 방식으로 작동하도록 해야함  
sparse_vector_a = enumerate(arr_a)
sparse_vector_b = enumerate(arr_b)

# 코사인 유사도
sim = cossim(sparse_vector_a, sparse_vector_b)

print(sim)
>> 0.6347394233600139

코사인 유사도의 사용

  • 임베딩 모델을 통해 만들어진 단어 벡터 또는 문서 벡터 사이의 유사성 비교
  • 이를 통해 문서 검색, 챗봇, 표절 검사 등에 사용된다.
  • 벡터간 유사성 비교이므로 텍스트 뿐만 아니라 추천 시스템, 분류 문제 등에서도 사용할 수 있다.

실습

<추후 시간="" 나면="" 실습="" 코드="" 리뷰=""> ## Reference 방송통신대학교 - 자연언어처리 수업 (유찬우 교수)

Comments