추천알고리즘 이해를 위한 유사도 기초개념 및 구현실습

2019-01-29

.

그림, 실습코드 등 학습자료 출처 : 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에 가까울 수록 가까운 데이터라고 할 수 있다.
  • 공식 :
\[\ \begin{eqnarray} \| a - b \| &=& \sqrt{\sum_{i=1} (a_i - b_i)^2} \\ \end{eqnarray}\]
# 계산과정
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. 코사인 유사도

  • 벡터사이의 코사인 각으로 유사도를 구함
  • 각이 작을수록 같은 방향성을 가지기 때문에 비슷한 특징을 갖는다.
  • 공식 : 벡터의 내적 / 벡터의 크기

1

내적은 아래의 그림에서 A와 B의 내적은 C가 된다. 세타값이 증가할수록 내적의 크기는 작아진다.

2

# 샘플 데이터
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 값이 큰것은 아니다.

3

아래의 그림은 d 값이 작다고해서 \(\ \theta\)값이 작은건 아니며 \(\ \theta\)값이 크다고해서 d 값이 큰것이 아님을 보여준다. 아래 왼쪽그림은 \(\ \theta\)값이 작지만 d값이 큰경우이고, 오른쪽 그림은 d값이 작지만 \(\ \theta\)값이 큰 그래프를 보여준다.

4

이러한 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