Cosine Similarity의 Bound 조정하기 + 코드

이용준·2024년 10월 26일

Coding

목록 보기
3/5

Introduction

Cosine Similarity (코사인 유사도) 는 아주아주 유명한 개념이다. 두 벡터 간 내적을 각 벡터의 거리 (Norm) 의 곱으로 나누어 주면 두 벡터 간 cosine 각도가 나온다는 것이고, 이는 사실 고등학교 삼각함수에도 나오는 내용이다.

cos(θ)=ABABcos(\theta) = \frac{A\cdot B}{|A||B|}

딥러닝에서 Cosine Similarity의 활용도는 정말 무궁무진한데 대표적인 것이 Transformer의 Attention에서 Dot Product를 하는 경우다. Cosine Similarity는 계산 과정에서 (1) Dot Product와 (2) Norm의 곱으로 나누어주는 과정, 두 가지가 필요한데 이중 (2)는 많은 딥러닝 Application에서 생략될 수 있는 것이 일반적으로 Feature를 L2-Normalization을 거치게 해 연산 과정을 생략시킬 수 있기 때문이다.

이외에도 개념적인 부분을 짚기에는 너무도 많은 글들이 Cosine Similarity에 대해 잘 설명하고 있어서 굳이 그럴 필요는 없겠다 싶다. 이 글은 -1~1의 치역을 가지는 Cosine Similarity 함수의 Bounds를 0~1로 바꾸는 방식을 소개하고, 이를 코딩으로 구현한다. Bounds를 0에서 1로 바꾸는 것은 다양한 상황에서 이용될 수 있는데, angle 기준으로 먼 벡터에 대해서 더 낮은 값을 (0에 가깝게) 부여하고 angle 기준으로 가까운 벡터에 더 높은 값을 (1에 가깝게) 부여하고자 하는 것이다.

-1~1 Cosine Similarity

일반적인 Cosine Similarity에서는 cos(0)=1cos(0^\circ) =1 이므로 같은 방향에 있는 벡터는 1로 표현된다. cos(90)=0cos(90^\circ) =0 이므로 Orthogonal, 즉 관계가 없는 벡터들의 유사도는 0으로 표현된다. 마지막으로 cos(180)=1cos(180^\circ) =-1 이므로 정 반대에 있는 벡터들의 유사도는 -1로 표현된다.

0~1 Cosine Similarity

cos(θ)=ABABθ=cos1(ABAB)Dθ=θπ=arccos(ABAB)πSθ=1Dθcos(\theta) = \frac{A\cdot B}{|A||B|} \\ \theta = cos^{-1}(\frac{A\cdot B}{|A||B|}) \\ D_{\theta}=\frac{\theta}{\pi} = \frac{arccos(\frac{A\cdot B}{|A||B|})}{\pi}\\ S_{\theta} = 1 - D_{\theta}

arccos 함수는 -1~1의 정의역에 대해 0~pi 까지의 치역을 가지는 함수이므로 이를 pi로 나누어 normalize를 해 주면 angular distance를 구할 수 있게 된다. distance의 반대가 similarity이므로 우리는 1에서 Distance를 빼주어서 Similarity인 SθS_{\theta}를 구해낼 수 있다.

def compute_cosine_similarity(matrix_a, matrix_b):

    # matrix_a.shape, matrix_b.shape = [n_features, sequence_length]
    
    cos_sim = cosine_similarity(matrix_a, matrix_b)[0][0]
    cos_sim = np.clip(cos_sim, -1 + 1e-6, 1 - 1e-6) 
    # To mitigate numerical instability
    angular_dis = np.arccos(cos_sim) / np.pi
    
    return 1 - angular_dis

가운데 clip 메소드를 이용한 것은 -1과 1에 정의역이 가까울 때 arccos 함수의 계산 과정에서 numerical instability가 자주 발생하기 때문이다. 매우 작은 값을 이용해 clipping 해주어서 계산 과정을 stabilize한다.

Conclusion

벡터 간 angular distance가 멀수록 (π\pi에 가까울수록) 0에 가깝게 유사도를 맵핑하는 Angular similarity를 구현한다.

profile
Ad libitum

0개의 댓글