추천알고리즘 이해를 위한 유사도 기초개념 및 구현실습
.
그림, 실습코드 등 학습자료 출처 : https://gitlab.com/radajin
[협업필터링 추천알고리즘]
- 사용자 기반 협업 필터링
- 주로 사용자기반으로 추천 알고리즘을 구현
- 아이템 기반 협업 필터링
- 사용자가 가지고 있는 아이템에 대한 정보가 많이 없을때 아이템을 기준으로 추천알고리즘을 구현
- 인터넷 쇼핑물이 대표적인 예시
[추천알고리즘 구성 기본개념 정리 : 유사도]
-
종류 : 유클리디안, 코사인, 멘하튼, 자카드 등
-
멘하튼 : 뉴욕 멘하튼 도시를 연상시키는 개념으로 블럭간의 x축과 y축의 거리를 산출해서 계산한다.
-
자카드 : 집합데이터에 대한 유사도를 구하는 개념이다. 0과 1사이의 값으로 두집합이 동일하면 1로 표기한다.
import numpy as np
import pandas as pd
from scipy import spatial
# 샘플 데이터 초기화
vector_1 = np.array([1,2,3,4,5])
vector_2 = np.array([5,4,3,2,1])
vector_3 = np.array([2,3,4,5,6])
1. 유클리디안 유사도
- 벡터 사이의 거리
- 거리값이 작으면 가까운 위치에 있기 때문에 비슷한 특징을 데이터가 서로 갖는다.
- 거리값이 0에 가까울 수록 가까운 데이터라고 할 수 있다.
- 공식 :
# 계산과정
print((vector_1 - vector_2))
print((vector_1 - vector_2) ** 2)
print(sum((vector_1 - vector_2) ** 2))
print(np.sqrt(sum((vector_1 - vector_2) ** 2)))
[-4 -2 0 2 4]
[16 4 0 4 16]
40
6.324555320336759
# numpy 함수 사용
np.linalg.norm(vector_1 - vector_2), np.linalg.norm(vector_1 - vector_3), np.linalg.norm(vector_2 - vector_3)
# 각각의 유클리디안 유사도를 구해보면 벡터1-벡터2보다 벡터1-벡터3이 더 가까운 것으로 확인된다.
(6.324555320336759, 2.23606797749979, 6.708203932499369)
# 유클리디안 유사도 함수화
def Euclidean_Distance_Similarity(vector_1, vector_2):
return np.linalg.norm(vector_1 - vector_2)
Euclidean_Distance_Similarity(vector_1, vector_2)
6.324555320336759
2. 코사인 유사도
- 벡터사이의 코사인 각으로 유사도를 구함
- 각이 작을수록 같은 방향성을 가지기 때문에 비슷한 특징을 갖는다.
- 공식 : 벡터의 내적 / 벡터의 크기
내적은 아래의 그림에서 A와 B의 내적은 C가 된다. 세타값이 증가할수록 내적의 크기는 작아진다.
# 샘플 데이터
vector_1 = np.array([1,2,3,4,5])
vector_2 = np.array([5,4,3,2,1])
vector_3 = np.array([11,19,28,32,47])
# 분자 - 벡터의 내적
print(sum(vector_1 * vector_2))
# 내적 numpy 함수
print(np.dot(vector_1, vector_2))
35
35
# 분모 - 벡터의 크기
# 계산과정
print(vector_1 * vector_1, vector_2 * vector_2)
print(sum(vector_1 * vector_1), sum(vector_2 * vector_2))
print(np.sqrt(sum(vector_1 * vector_1)), np.sqrt(sum(vector_2 * vector_2)))
[ 1 4 9 16 25] [25 16 9 4 1]
55 55
7.416198487095663 7.416198487095663
# numpy 함수 사용 계산
print(np.sqrt(np.dot(vector_1, vector_1)) * np.sqrt(np.dot(vector_2, vector_2)))
55.0
# 벡터의 내적 / 벡터의 크기
print(np.dot(vector_1, vector_2) / (np.sqrt(np.dot(vector_1, vector_1)) * np.sqrt(np.dot(vector_2,
vector_2))) )
0.6363636363636364
# scipy 함수 사용
1 - spatial.distance.cosine(vector_1, vector_2), 1 - spatial.distance.cosine(vector_1, vector_3)
(0.6363636363636364, 0.9971083087048903)
# 코싸인 유사도 함수화
def Cosine_Similarity(vector_1, vector_2):
return 1 - spatial.distance.cosine(vector_1, vector_2)
3. 유클리디안 유사도와 코사인 유사도의 차이점
d는 Euclidean Distance를 의미하며, \(\ \theta\)는 \(\ \cos\theta\) 의미한다. 두개의 유사도는 하나는 거리를 하나는 각도를 의미하는 수치를 나타낸다. 그러므로 d 값이 작다고해서 \(\ \theta\)값이 작은건 아니며 \(\ \theta\)값이 크다고해서 d 값이 큰것은 아니다.
아래의 그림은 d 값이 작다고해서 \(\ \theta\)값이 작은건 아니며 \(\ \theta\)값이 크다고해서 d 값이 큰것이 아님을 보여준다. 아래 왼쪽그림은 \(\ \theta\)값이 작지만 d값이 큰경우이고, 오른쪽 그림은 d값이 작지만 \(\ \theta\)값이 큰 그래프를 보여준다.
이러한 Euclidean Distance와 Cosine Similarity의 특성으로 인해 추천 알고리즘에는 Cosine Similarity가 사용된다.
예를들어 뉴스 컨텐츠를 소비하는데 A 사용자는 서비스에 대한 소비량이 적고 B 사용자는 서비스에 대한 소비량이 많지만 소비하는 컨텐츠는 비슷한 경우 왼쪽 그림과 같은 현상이 나타난다. A와 C 사용자 모두 컨텐츠 소비는 비슷하게 하는데 서로 다른 컨텐츠를 소비하는 경우에는 우측과 같은 모양의 그림이 나온다.
이러한 경우 A에게 컨텐츠를 추천해주기 위해서 어떤 사용자의 데이터를 활용하는게 옳을까?
-> B 사용자의 데이터를 활용하여 A에게 컨텐츠를 추천해주는것이 더욱 정확하다고 할 수 있다.
# 샘플 데이터
vector_1 = np.array([1,2])
vector_2 = np.array([10,10])
vector_3 = np.array([2,1])
# Euclidean Distance Similarity
Euclidean_Distance_Similarity(vector_1, vector_2)
12.041594578792296
Euclidean_Distance_Similarity(vector_1, vector_3)
1.4142135623730951
# Cosine Similarity
Cosine_Similarity(vector_1, vector_2)
0.9486832980505138
Cosine_Similarity(vector_1, vector_3)
0.8