코사인 유사도는 벡터의 '방향'이라는 특징으로만 벡터간 유사도를 구할 수 있습니다.
유클리드 거리는 방향은 무시한 채, 거리가 얼마나 가까운지에 기반하여 추천 시스템의 엔진이 되었죠.
두 추천 알고리즘 모두 완벽하거나 현재 이상적으로 활발하게 사용되는 추천 시스템은 아닙니다.
하지만 다른 고급(?) 알고리즘의 기초가 되는 만큼 간단하게 이해하고 넘어가는 것이 좋다고 생각합니다.
또한 NLP를 처음 공부한다면, Bag of Words에 기반한 단어 표현 방법인 Document Term Matrix, TF-IDF 등과 같이 단어를 수치화할 수 있는 방법을 알고 있다면, 코사인 유사도는 위 표현식에 아주 적용하기 쉬운 알고리즘입니다.
이를 기반으로 "문서의 유사도"를 구하는 게 가능합니다.
코사인 유사도는 기본적으로 두 벡터간 코사인 각도를 이용하여 구할 수 있는 벡터의 유사도를 말합니다. (자세한 내용은 선형대수학 카테고리에 있는 포스팅을 참고하세요)
그리고 cosine은 -1이상 1이하의 값을 갖는 것이 특징이었습니다.
이를 직관적으로 이해한다면, 두 벡터가 가리키는 방향이 얼마나 유사한가를 의미한다고 볼 수 있습니다.
cosine은 쉽게 말해서 두 벡터의 내적과 norm으로 구할 수 있는데, 간단하게 표현해보자면 아래와 같습니다.
$$ \text{similarity} = \text{cos}(\theta) = \frac{\textbf{a} \cdot \textbf{b}}{|| \textbf{a}|| ||\textbf{b}||} $$
이제는 어떻게 유사도가 어떻게 활용되는지 살펴보시죠.
아래처럼 3개의 문서가 있고, 각각 문서에 대한 단어 행렬(DTM)이 있다고 가정해보죠.
문서1 : 저는 사과 좋아요
문서2 : 저는 바나나 좋아요
문서3 : 저는 바나나 좋아요 저는 바나나 좋아요
이 문서를 DTM에 표현을 하면 아래의 그림처럼 표현할 수 있습니다.
이제 파이썬의 numpy 패키지를 활용하여 구현해봅시다.
# 코사인 유사도를 이용한 유사도 측정
import numpy as np
import pandas as pd
def cosine_sim(x, y):
"""
:param x: numpy array (vector)
:param y: numpy array (vector)
:return: cosine_sim
"""
xy = np.inner(x, y)
x_norm = np.linalg.norm(x)
y_norm = np.linalg.norm(y)
return np.round(xy / (x_norm * y_norm), 3)
# 3개의 도큐먼트 임의로 생성
if __name__ == '__main__':
doc1 = np.array([0, 1, 1, 1])
doc2 = np.array([1, 0, 1, 1])
doc3 = np.array([2, 0, 2, 2])
print('문서 1과 문서 2의 유사도: ', cosine_sim(doc1, doc2))
print('문서 1과 문서 3의 유사도: ', cosine_sim(doc1, doc3))
print('문서 2와 문서 3의 유사도: ', cosine_sim(doc2, doc3))
문서 1과 문서 2의 유사도: 0.667
문서 1과 문서 3의 유사도: 0.667
문서 2와 문서 3의 유사도: 1.0
완벽하게 방향에 의거해서 문서간 유사도를 구한 것을 확인할 수 있습니다.
[문서1과 문서2]의 유사도 & [문서1과 문서3]의 유사도는 왜 같은지,
또 [문서2 & 문서3]의 유사도는 어떻게 완벽하게 나올 수 있었는지 쉽게 알 수 있겠지만, 직접 코사인 유사도를 계산해보면서 이해해보는 것도 좋은 방법이라고 생각합니다.
'추천시스템 > 추천시스템 기초' 카테고리의 다른 글
[python] 유클리드 거리 (Euclidean Distance) - 기초 (0) | 2022.12.21 |
---|