추천시스템 개요
추천시스템은 유튜브부터 이커머스 등의 플랫폼까지 우리가 접하는 다양한 콘텐츠, 생활 각각 요소에서 보편적으로 활용되고 있다. 하지만 현재 기업이 추천시스템의 활용하는 목적은 고객을 서비스에 계속 활동할 수 있도록 하는 것이 목적이고 이는 곧 수익창출을 의미한다. 그러므로 현재 추천시스템은 고객에게 다양한 질 좋은 정보를 제공하기보다는 고객이 서비스를 이용하는 데 시간을 소모하도록 하는 것이 목적이기 때문에 사용자 입장에선 자신의 관심사 또는 한 쪽의 편향된 정보만을 주입받아 편향된 생각과 정보에만 노출되는 우려가 있다. 이를 에코챔버(Echo Chamber) 효과라고 한다.
추천시스템의 이로움, 해로움을 떠나 우리는 추천시스템의 많은 영향을 받는 것은 사실이다. 해당 추천시스템에 대해서 좀 더 구체적으로 알아보기 위해 해당 포스트를 게재하게 되었다.
추천시스템 이론
추천시스템은 콘텐츠 기반 필터링과 협업 기반 필터링으로 나뉘며, 여기서 협업 기반 필터링은 최근접 이웃 방식과 잠재 요인 방식으로 나뉜다. 두 방식 모두 사용자-아이템 평점 행렬 데이터에 의해 추천된다.
이번 포스트 목적은 아이템 기반의 협업 필터링과 잠재요인 협업 필터링을 활용하는 것이 주목적이기 때문에 두 가지를 중점으로 설명하겠다. 사용자 기반의 협업 필터링과 아이템 기반의 협업 필터링의 차이는 간단하다.
사용자 기반 협업 필터링이 사용자의 행동양식을 통해, ‘예측 평가’를 수행한다면,
ex) 영화 리뷰를 쓴 사람에게 다른 영화를 추천하는 것
아이템 기반의 협업 필터링은 사용자들의 아이템에 대한 호/불호 평점이 유사한 아이템을 추천하는 기준이 되는 알고리즘이다.
사용자 기반: “사용자 a와 비슷한 사용자 b가 이 아이템을 사용함”
아이템 기반: “이 아이템을 구매한 다른 고객은 저 아이템도 구매함”
아이템 기반 협업 필터링 실습
데이터셋을 통해 아이템 기반 협업 필터링을 진행해보자
데이터셋은 캐글의 데이터셋을 활용했으며 약 271,379 권의 도서에 대해 1,149,780 등급을 제공하는 278,858 명의 사용자를 포함하는 데이터셋이다.
Book-Crossing: User review ratings
Book-Crossing: User review ratings
A collection of book ratings
www.kaggle.com
데이터 불러오기 및 데이터셋 확인
먼저 필요한 라이브러리를 불러오고 데이터셋을 가져온 뒤 간단히 NULL 값을 확인하였다.
데이터셋은 도서정보에 대한 데이터셋인 BX_Books.csv와 유저가 매긴 도서 평점 정보가 담긴 BX_Book_Ratings.csv를 활용하였다.
import csv
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.metrics import mean_squared_error
bxbooks = pd.read_csv('data/kaggle_book/BX_Books.csv', sep=';')
bxbookratings = pd.read_csv('data/kaggle_book/BX_Book_Ratings.csv', sep=';', encoding="cp949")
# 도서 null 체크 1
bxbooks.isnull().sum()
ISBN 0
Book-Title 0
Book-Author 1
Year-Of-Publication 0
Publisher 2
Image-URL-S 0
Image-URL-M 0
Image-URL-L 0
dtype: int64
# 평점 null 체크 2
bxbookratings.isnull().sum()
User-ID 0
ISBN 0
Book-Rating 8
dtype: int64
아래와 같이 도서데이터셋은 ISBN, 책 제목, 저자 등의 도서에 관한 컬럼을 확인할 수 있다.
bxbooks.head()
코사인 유사도를 적용하여 데이터프레임으로 변환한 뒤 추천알고리즘을 적용하였다.
*cosine_similarity(): 행을 기준으로 서로 다른 행을 비교해 유사도를 측정하는 함수
# 변경한 데이터셋을 기반으로 책의 코사인 유사도 구함
from sklearn.metrics.pairwise import cosine_similarity
item_sim = cosine_similarity(ratings_matrix_T, ratings_matrix_T)
# cosine_similarity()로 반환된 Numpy 행렬을 도서명으로 매핑하여 df로 변환
item_sim_df = pd.DataFrame(data=item_sim, index=ratings_matrix.columns,
columns= ratings_matrix.columns)
print(item_sim_df.shape)
item_sim_df.head(3)
# 1. 오만과 편견
item_sim_df['Pride and Prejudice'].sort_values(ascending=False)[:6]
# 2. 로미오와 줄리엣
item_sim_df['Romeo and Juliet'].sort_values(ascending=False)[1:6]
item_sim_df.head(3)
아이템 기반 최근접 이웃 협업 필터링으로 개인화된 도서 추천
아이템 기반 최근접 이웃 협업 필터링으로 개인화된 도서 추천을 진행해보자. 개인화된 도서 추천의 가장 큰 특징은 개인이 아직 읽지 않은 도서를 추천하는 것이 핵심이다. 아직 읽지 않은 도서에 대해 아이템 유사도와 기존 읽은 책 평점 데이터 기반으로 새롭게 모든 책의 예측 평점 계산한 후 높은 예측 평점을 가진 도서를 추천하는 방식이다.
# 아이템 기반 협업필터링에서 개인화된 예측 평점계산식 함수 설계
def predict_rating(ratings_arr, item_sim_arr):
ratings_pred= ratings_arr.dot(item_sim_arr) / np.array([np.abs(item_sim_arr).sum(axis=1)])
return ratings_pred
# 도서간 유사도를 갖는 df인 item_sim_df와 사용자-도서 평점 df인 rating_matrix 변수를 통해 사용자별로 최적화된 평점 스코어 예측
ratings_pred = predict_rating(ratings_matrix.values, item_sim_df.values)
# 예측된 rating_pred에 rating_matrix을 index, item_sim_df을 컬럼으로 하여 df 생성
ratings_pred_matrix = pd.DataFrame(data=ratings_pred, index= ratings_matrix.index, \\
columns = ratings_matrix.columns)
ratings_pred_matrix.head(3)
예측결과가 실제 평점과 얼마나 차이가 나는지 확인하기 위해 사용자가 부여한 도서에 대해서만 예측 성능 평가 MSE를 도출하였다.
def get_mse(pred, actual):
# 평점이 있는 실제 도서만 추출
pred = pred[actual.nonzero()].flatten()
actual = actual[actual.nonzero()].flatten()
return mean_squared_error(pred, actual)
print('MSE: ', get_mse(ratings_pred, ratings_matrix.values))
MSE: 15.572293628480582
MSE이 높게 나왔으므로 개선이 필요하다. 특정 도서와 가장 비슷한 유사도를 갖는 도서에 대해서만 유사도 벡터 적용하는 예측 평점 계산식 함수 생성했다.
def predict_rating_topsim(ratings_arr, item_sim_arr, n=20):
# 사용자-아이템 평점행렬 크기만큼 0을 채운 예측 행렬 초기화
pred = np.zeros(ratings_arr.shape)
# 사용자-아이템 평점 행렬의 열 크기만큼 루프 수행for col in range(ratings_arr.shape[1]):
# 유사도 행렬에서 유사도가 큰 순으로 n개 데이터 행렬의 인덱스 반환
top_n_items = [np.argsort(item_sim_arr[:, col])[:-n-1:-1]]
# 개인화된 예측 평점계산for row in range(ratings_arr.shape[0]):
pred[row, col] = item_sim_arr[col, :][top_n_items].dot(ratings_arr[row,:][top_n_items].T)
pred[row, col] /= np.sum(np.abs(item_sim_arr[col, :][top_n_items]))
return pred
predict_rating_topsim() 함수를 이용해 예측 평점을 계산하고 실제 평점과 MSE 구해보자
계산된 예측 평점 넘파이 행렬은 df로 재생성하였다.
ratings_pred = predict_rating_topsim(ratings_matrix.values, item_sim_df.values, n=20)
print('아이템 기반 최근접 top 20 이웃 mse: ', get_mse(ratings_pred, ratings_matrix.values))
# 계산된 예측 평점 데이터를 df로 변경
ratings_pred_matrix = pd.DataFrame(data=ratings_pred, index=ratings_matrix.index,
columns=ratings_matrix.columns)
Example: 특정 사용자에게 도서 추천
특정 사용자 277928로 도서추천을 수행해보자
먼저 277928 사용자가 높게 평점을 준 도서 확인하였다.
user_rating_id = ratings_matrix.loc[277928, :]
user_rating_id[ user_rating_id > 0 ].sort_values(ascending=False)[:10]
# 사용자가 평점을 주지 않은 책을 리스트객체로 반환하는 함수 생성
def get_unread_books(ratings_matrix, userId):
# userId로 입력받은 사용자의 모든 도서정보를 추출해 Series로 반환 반환된 user_ratings은 도서명(title)을 index로 갖는 Series 객체
user_rating = ratings_matrix.loc[userId, :]
# user_rating이 0보다 크면 기존에 읽은 도서. 대상 index를 추출해 list객체 생성
already_seen = user_rating [ user_rating > 0 ].index.tolist()
# 모든 도서명을 list 객체로 만듦
book_list = ratings_matrix.columns.tolist()
# list comprehension 으로 already_seen에 해당되는 도서는 books_list에서 제외
unread_list = [ book for book in book_list if book not in already_seen ]
return unread_list
사용자가 책의 평점을 주지 않은 추천대상 도서정보와 predict_rating_topsim()에서 추출한 사용자별 아이템 유사도에 기반한 예측 평점 데이터셋을 이용해 최종적으로 사용자에게 책을 추천하는 함수를 생성하였다.
def recomm_book_by_userid(pred_df, userId, unread_list, top_n=10):
# 예측 평점 df에서 사용자 id 인덱스와 unread_list로 들어온 도서명 컬럼을 추출하여 가장 예측 평점이 높은 순으로 정렬
recomm_books = pred_df.loc[userId, unread_list].sort_values(ascending=False)[:top_n]
return recomm_books
# 사용자가 읽지 않은 도서명 추출
unread_list = get_unread_books(ratings_matrix, 277928)
# 아이템 기반의 최근접 이웃 협업 필터링으로 도서 추천
unread_books = recomm_book_by_userid(ratings_pred_matrix, 277928, unread_list, top_n=10)
# 평점 데이터를 df로 생성
recomm_books = pd.DataFrame(data=recomm_books.values, index= recomm_books.index, columns= ['pred_score'])
recomm_books
# 사용자가 좋아할 만한 가장 높은 예측 평점을 가진 도서 리스트가 추천됨
Reference
파이썬 머신러닝 완벽가이드 - 권철민
'Data analysis' 카테고리의 다른 글
텍스트 하이라이트 기능을 통해 XAI 맛보기 (0) | 2023.10.20 |
---|---|
도서 추천시스템 - Surprise 활용 잠재요인 협업 필터링 (0) | 2023.10.15 |