데이터 분석 - 추천 시스템 (Recommendation System) - Recommendation 기본 알고리즘

2. Recommendation 기본 알고리즘

2.1. Popularity, High Rated Based (가장 단순함)

  • 가장 쉽게 인기도, 즉 높은 평점을 갖는 item을 추천 가능
  • 모두에게 동일한 item이 추천 됨
ratings={
     'Dave':{'달콤한인생':5,'범죄도시':3,'샤인':3},
     'David':{'달콤한인생':5,'범죄도시':1,'샤인':4},
     'Alex':{'달콤한인생':0,'범죄도시':4,'샤인':5},
     'Andy':{'달콤한인생':2,'범죄도시':1,'샤인':5}
}
  • 영화중 가장 평점이 높은 순으로 추천해주면 됨
평점이 가장 높은 두 영화 출력하기
movie_dict = dict()
for rating in ratings:
    for movie in ratings[rating].keys():
        if movie not in movie_dict:
            movie_dict[movie] = ratings[rating][movie]
        else:
            movie_dict[movie] = (movie_dict[movie] + ratings[rating][movie]) 

for movie in ratings[rating].keys():
    movie_dict[movie] = movie_dict[movie] / 4

import operator
sorted_x = sorted(movie_dict.items(), key=operator.itemgetter(1), reverse=True)

print(sorted_x[:2])
[('샤인', 4.25), ('달콤한인생', 3.0)]

2.2. Collaborative Filtering

  1. 데이터 구성 : 사용자가 입력한 선호도(평점)를 사용하여 사용자-항목 선호도(평점) 행렬을 만든다.
  2. 유사도 계산 : 1 단계에서 만들어진 행렬을 사용하여 사용자들 간의 유사도를 계산한다.
  3. 예측 값 계산 및 추천 목록 생성 : 사용자들 간의 유사도를 바탕으로 모든 항목에 대해 예측 값을 계산하고 높은 예측 값을 갖는 상위 N개의 추천 목록을 생성한다.

1. 데이터 구성

ratings={
     'Dave':{'달콤한인생':5,'범죄도시':3,'샤인':3},
     'David':{'달콤한인생':2,'범죄도시':1,'샤인':4},
     'Alex':{'범죄도시':4,'샤인':5},
     'Andy':{'달콤한인생':2,'범죄도시':1,'샤인':5}
}
ratings.get('Dave')
Out[4]:
{'달콤한인생': 5, '범죄도시': 3, '샤인': 3}
ratings.get('Dave').get('샤인')
Out[5]:
3

2. 유사도를 구해보자 (피타고라스 공식을 통한 거리 계산)

import math
def sim(i, j):
    return math.sqrt(pow(i,2)+pow(j,2))
var1 =  ratings['Alex']['범죄도시'] - ratings['Andy']['범죄도시']
var1
Out[8]:
3
var2 =  ratings['Alex']['샤인'] - ratings['Andy']['샤인']
var2
Out[10]:
0
sim(var1,var2)
Out[11]:
3.0

Alex가 평가한 범죄도시, 샤인을 모두 평가한 사용자와 모두 거리 구하기 (유사도 구하기)

for i in ratings:
    if i!='Alex':
        num1 = ratings.get('Alex').get('범죄도시') - ratings.get(i).get('범죄도시')
        num2 = ratings.get('Alex').get('샤인') - ratings.get(i).get('샤인')
        print(i," : ", sim(num1,num2))
Dave  :  2.23606797749979
David  :  3.1622776601683795
Andy  :  3.0

정규화를 통해 유사도 범위를 0과 1사이로 가두고, 1에 가까울 수록 유사도가 높게 변경하기

for i in ratings:
    if i!='Alex':
        num1 = ratings.get('Alex').get('범죄도시') - ratings.get(i).get('범죄도시')
        num2 = ratings.get('Alex').get('샤인') - ratings.get(i).get('샤인')
        print(i," : ", 1 / ( 1 + sim(num1,num2) ) )
Dave  :  0.3090169943749474
David  :  0.2402530733520421
Andy  :  0.25
Dave가 평가한 범죄도시와 샤인 모두 평가한 사용자와의 거리를 구해서, 가장 Dave와 유사한 사용자 구하기
for i in ratings:
    if i!='Dave':
        num1 = ratings.get('Dave').get('범죄도시') - ratings.get(i).get('범죄도시')
        num2 = ratings.get('Dave').get('샤인') - ratings.get(i).get('샤인')
        print(i," : ", 1 / ( 1 + sim(num1,num2) ) )
David  :  0.3090169943749474
Alex  :  0.3090169943749474
Andy  :  0.2612038749637414