(프로젝트)머신러닝_Netflix 영화 데이터셋을 이용한 '협업 필터링' + '콘텐츠 기반 필터링' 영화 추천_1) 협업 필터링_KNN
목차
Overview
Kaggle에 있는 넷플릭스 영화 순위 데이터셋 및 넷플릭스 영화 데이터셋으로 협업 필터링, 콘텐츠 기반 필터링 영화 추천 시스템을 구현하고자 한다. 사용자가 자신이 좋아하는 영화를 입력하면 협업 필터링으로 추천한 영화와 콘텐츠 기반 필터링으로 추천한 영화를 모두 추천해주어 더욱 다양한 영화를 사용자에게 추천하는 것을 목표로 한다.
https://www.kaggle.com/datasets/rishitjavia/netflix-movie-rating-dataset
Netflix Movie Rating Dataset
Dataset from Netflix's 'Netflix Prize' competition
www.kaggle.com
1. Netflix Movie Recommendation System: Collaborative Filtering_KNN
- Collaborative Filtering(협업 필터링) 이란?
협업 필터링은 쿼리와 항목 간 유사성을 동시에 사용하여 권장사항을 제공하는 것을 말하는 데, 예를 들어 사용자 A가 사용자 B와 비슷하고 사용자 B가 영화 1을 좋아하면 사용자 A가 영화 1과 유사한 영화를 보지 못했더라도 시스템에서 사용자 1에게 영화 1을 추천하는 것을 뜻한다.
이번 프로젝트에서는 협업 필터링의 초기 알고리즘인 Memory-based Collaborative Filtering의 아이템 기반의 근접 이웃 방법(Neighborhood Method)를 사용하여 특정 사용자가 준 점수 간의 유사한 아이템을 찾아서 추천 리스트를 생성하고자 한다.
https://developers.google.com/machine-learning/recommendation/overview/candidate-generation?hl=ko
후보 생성 개요 | Machine Learning | Google for Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 후보 생성 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 후보 생성은
developers.google.com
01) Business Understanding
아이템(영화)을 기준으로 사용자들이 비슷한 평점을 내린 유사한 아이템(영화)을 추천
02) Data Understanding
2-1. Data Load
import pandas as pd
movie_df = pd.read_csv('data/Netflix_Dataset_Movie.csv')
rating_df = pd.read_csv('data/Netflix_Dataset_Rating.csv')
2-2. EDA
# Merge
df = movie_df.merge(rating_df, how='inner', on='Movie_ID')
# Null 값 확인
df.isnull().sum() # Null 값 없음
# rating 확인
df['Rating'].value_counts() # 1~5점으로 형성되어 있음
# 영화별 리뷰 수 확인
import matplotlib.pyplot as plt
plt.title("Popularity Ranking of Movies") # 하나의 영화에 많은 리뷰가 있음
df.Movie_ID.value_counts().plot(kind = "bar")
plt.xticks(ticks = [])
# 협업 필터링 용 df를 csv로 저장
df.to_csv('data/cf_df.csv', index=False)
2-3. Data Preparation
# 영화 별 유저들의 평점 테이블 생성
movie_pivot = df.pivot_table(index='Movie_ID', columns='User_ID', values='Rating')
movie_pivot.fillna(0, inplace=True) # NaN 값을 0으로 변환
movie_pivot = movie_pivot.astype('int8') # 데이터 크기를 줄이기 위해 int8로 변환
# shape 확인
movie_pivot.shape # (1350, 143458)
# 테이블 출력
movie_pivot.head()
03) Modeling
# 모델 생성
from sklearn.neighbors import NearestNeighbors
n_neighbors = 11
KNN = NearestNeighbors(metric='cosine', n_neighbors=n_neighbors, n_jobs=-1)
KNN.fit(movie_pivot)
distances, indices = KNN.kneighbors(movie_pivot)
# 모델 저장
import pickle
with open('data/distances.pickle','wb') as fw:
pickle.dump(distances, fw)
with open('data/indices.pickle','wb') as fw:
pickle.dump(indices, fw)
with open('data/movie_pivot.pickle','wb') as fw:
pickle.dump(movie_pivot, fw)
# 모델 버전 확인
import numpy
import sklearn
print(f'numpy version: {numpy.__version__}')
print(f'sklearn version: {sklearn.__version__}')
print('python version: 3.10.9')
# numpy version: 1.23.5
# sklearn version: 1.2.1
# python version: 3.10.9
04) Deployment
# 영화 제목 검색 함수 생성
def search_movie(name):
search_movie_id = df.loc[df['Name'] == name, 'Movie_ID'].unique()[0]
index = np.where(movie_pivot.index == search_movie_id)[0][0]
return index
# CF 함수 생성
def collaborative_filtering(index, n):
for i in range(n):
movie_name = movie_df.loc[movie_df['Movie_ID'] == movie_pivot.index[indices[index][i]], 'Name'].values[0]
distance = '{:.3f}'.format(distances[index][i])
print(movie_name, 'distance: ', distance)
# Top 3 영화 추천
index = search_movie('Pirates of the Caribbean: The Curse of the Black Pearl')
n = 4 # Top 3
collaborative_filtering(index, n)
# Pirates of the Caribbean: The Curse of the Black Pearl distance: 0.000
# Lord of the Rings: The Fellowship of the Ring distance: 0.180
# Finding Nemo (Widescreen) distance: 0.210
# Bruce Almighty distance: 0.217
05) Evaluation
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 케리비안 해적 영화와 유사한 영화
indices[587]
# array([ 587, 746, 1199, 1162, 1191, 1291, 1331, 837, 1096, 857, 719], dtype=int64)
x1 = movie_pivot.iloc[587].values
x2 = movie_pivot.iloc[746].values
cosine_similarity(x1.reshape(1,-1), x2.reshape(1,-1))
# array([[0.82012558]])
1 - 0.82012558
# 0.17987441999999998
# 약 0.18로 위의 영화 추천이 잘 계산되었음을 알 수 있음