추천 시스템은 컨텐츠 기반, 협업 필터링 방식으로 나뉨
협업필터링에서는 최근접 이웃, 잠재 요인 으로 나뉨
ex) 나와 비슷한 취향을 가진 사람에게 다른 영화 정보를 묻는 방법
최근접 이웃 협업 필터링은 사용자, 아이템 으로 나뉨
https://grouplens.org/datasets/movielens/latest/
import pandas as pd
import numpy as np
movies = pd.read_csv('movies.csv')
ratings = pd.read_csv('ratings.csv')
ratings_movie = pd.merge(ratings, movies, on='movieId')
ratings_matrix = ratings_movie.pivot_table('rating', 'userId', 'title')
# pivot_table(value, index, columns)
# 사용자별 영화 평점
ratings_matrix.fillna(0, inplace=True)
#NaN = 0 으로 채우기
ratings_matrix_T = ratings_matrix.T
# 영화별 사용자 평점
# index <-> columns 위치를 바꾸기
# 아이템기반 협업 필터링을 하기위해 사용자-아이템 행렬을 아이템-사용자 행렬을 사용
ratings_matrix.head(3)
ratings_matrix.T.head(3)
from sklearn.metrics.pairwise import cosine_similarity
sklearn_cosine = cosine_similarity(ratings_matrix_T, ratings_matrix_T)
item_similarity = pd.DataFrame(sklearn_cosine, index=ratings_matrix_T.index, columns = ratings_matrix_T.index)
item_similarity.head(3)
item_similarity[movies['title'][300]].sort_values(ascending=False)[:5]
#movies['title'][300] = Muriel's Wedding (1994)
# 평가 점수와 유사한 영화를 추천
def predict_rating(ratings_array, item_similarity):
sum_sr = ratings_array @ item_similarity
# u x i , item_similarity = ixi
# @ 연산자는 np.matmul, np.dot 행렬 곱을 해줌
sum_abs = np.array([np.abs(item_similarity).sum(axis=1)])
ratings_pred = sum_sr / sum_abs
return ratings_pred
rating_pred = predict_rating(ratings_matrix.values, item_similarity.values)
rating_pred_matrix = pd.DataFrame(data=rating_pred, index=ratings_matrix.index, columns = ratings_matrix.columns)
rating_pred_matrix.head()
def no_watch(ratings_matrix, user):
user_rating = ratings_matrix.loc[user,:]
#user_id 별로 평점 정보
no_watching = user_rating[user_rating==0].index.tolist()
# 보지않은 영화 리스트
movie_list = ratings_matrix.columns.tolist()
# 모든 영화를 리스트 만들기
no_list = [movie for movie in movie_list if movie in no_watching]
# 안 본 영화 리스트
return no_list
def recommend_movie_by_userid(pred_df, userId, no_list, top_n=10):
# 안 본 영화리스트 중 예측 점수가 가장 높은 순서 .series
recommend_movie = pred_df.loc[userId, no_list].sort_values(ascending=False)[:top_n]
return recommend_movie
user_id = 15
no_watch = no_watch(ratings_matrix, user_id)
recommend_movie = recommend_movie_by_userid(rating_pred_matrix, user_id, no_watch, top_n=10)
recom_movies = pd.DataFrame(data=recommend_movie.values, index=recommend_movie.index, columns=['pred_score'])
recom_movies