컨텐츠 기반 추천시스템(Content Based)
협업 필터링(CF, Collaborative Filtering)
메모리 기반, 이웃 기반 (Memory Based, Neighbor Based)
모델 기반 (Machine Learning)
Matrix를 이용하는 추천시스템 중 사용자의 평점 혹은 사용여부를 바탕으로 구매 패턴을 파악해 그 메모리를 바탕으로 추천을 진행하는 방법이다.
기본적으로 사용자 또는 아이템의 유사성을 바탕으로 평점이 없는 부분에 대해 모델을 통해 예측을 하는 방식이며, 이는 사용자 관점에서 진행하는 사용자 기반, 아이템 관점에서 진행하는 아이템 기반 협업필터링으로 나눌 수 있다.
K명의 최근접 이웃에 기반해서 찾는 방법으로, 널리 쓰이는 방법이다. 사용자가 준 평점으로 유사한 사람의 아이템을 찾거나, 유사한 아이템을 찾아 추천을 한다. 편향을 제거(전반적으로 평점을 후하게 주거나 적게 주는 경우를 방지)해주기 위해 비교군의 평점을 더해주거나 빼주어 동일하게 해준다.
영화 데이터가 아닌 실제 매트릭스를 생성해서 만들어보도록 한다.
아래는 KNN을 공부했던 TeamEDA 김현우님의 포스팅을 바탕으로 코드를 구현해봤다.
아이템1 | 아이템2 | 아이템3 | 아이템4 | 아이템5 | 아이템6 | |
---|---|---|---|---|---|---|
사용자1 | 7 | 6 | 7 | 4 | 5 | 4 |
사용자2 | 6 | 7 | ? | 4 | 3 | 4 |
사용자3 | ? | 3 | 3 | 1 | 1 | ? |
사용자4 | 1 | 2 | 2 | 3 | 3 | 4 |
사용자5 | 1 | ? | 1 | 2 | 3 | 3 |
import numpy as np
# 위 매트릭스에서 ? 부분은 0으로 치환하여 매트릭스 생성
matrix = np.array([[7,6,7,4,5,4],
[6,7,0,4,3,4],
[0,3,3,1,1,0],
[1,2,2,3,3,4],
[1,0,1,2,3,3]])
여기서 코사인 유사도를 이용해 특정 사용자3과 가장 유사한 사용자를 찾아낼 것이다.
def cosine_simillarity(v1, v2):
"""
두 벡터 v1, v2에 대한 코사인 유사도를 구하는 함수
위 매트릭스에서 사용자 기반 추천을 한다고 할때, 사용자1을 v1, 사용자2를 v2로 놓는다면,
v1 = [7,6,7,4,5]
v2 = [6,7,?,4,3]
으로 두고 함수를 적용하게 된다.
return: similarity of the two vectors
"""
A = np.sqrt(np.sum(np.square(v1)))
B = np.sqrt(np.sum(np.square(v2)))
return np.dot(v1,v2) / (A*B)
사용자3에 대한 다른 사용자들의 유사도를 각각 구해본다.
sim_lst = [] # 빈 리스트 생성
best_score = 0
for idx, vec in enumerate(matrix): # 매트릭스의 각 사용자 별 벡터를 뽑아 vec에 넣기
similarity = cosine_simillarity( vec, matrix[2]) # matrix[2] == 사용자3의 벡터
sim_lst.append((idx,similarity))
if idx != 2 and best_score < similarity: # 현재 계산한 유사도가 기존 최고 유사도보다 높다면 바꿔준다.
best_score = similarity
best_user = idx +1
print(sim_lst, f"\n사용자3과 가장 비슷한 유저: 사용자{best_user} \n유사도:{best_score}")
[output]
[(0, 0.8113480845393759), (1, 0.5969620057957091), (2, 0.9999999999999998), (3, 0.7745966692414833), (4, 0.46188021535170054)]
사용자3과 가장 비슷한 유저: 사용자1
유사도:0.8113480845393759
현재 사용자3과 가장 비슷한 유저는 사용자1(코사인 유사도 0.81)이다.
해당 사용자1의 평균 평점을 '편향'으로 두고, 사용자1의 아이템1의 평점에서 평균점수를 뺀 점수를 이용.
수정된 점수 x 코사인 유사도를 통해 ?의 점수를 예측한다.
수식으로 나타내면 아래와 같다.
best_user_idx = best_user-1 # 가장 비슷한 유저의 매트릭스 내 인덱스
best_mean_score = np.mean(matrix[best_user_idx]) # 가장 비슷한 유저의 평균 평점
for vec in range(len(matrix[2])):
if matrix[2][vec] == 0: # 해당 사용자3의 ? 부분에 위와같은 연산을 진행한다.
matrix[2][vec] = np.mean(matrix[2]) + (((matrix[best_user_idx][vec]-best_mean_score)*best_score)/best_score)
사용자3의 경우, 평균적으로 평점을 낮게 주는 경향이 있다.
그렇기에 편향을 모두 고려하여 이전 단계까지의 연산을 진행했다.
matrix
[output]
array([[7, 6, 7, 4, 5, 4],
[6, 7, 0, 4, 3, 4],
[2, 3, 3, 1, 1, 0],
[1, 2, 2, 3, 3, 4],
[1, 0, 1, 2, 3, 3]])
그 결과로, 아이템1에 대해선 평균(1.6667)보다 높은 점수인 2를 예측했고, 아이템6 에대해선 최하점인 0으로 적용이 되었다.
해당 유저에겐 평균 아이템1의 점수가 평균 이상의 높은 점수에 해당 하므로 아이템1을 추천해줄 수 있게 된다.