일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- linalg
- pivot table
- Python 유래
- scatter
- 표집분포
- boolean & fancy index
- subplot
- unstack
- ndarray
- 정규분포 MLE
- dtype
- 카테고리분포 MLE
- 가능도
- Array operations
- 부스트캠프 AI테크
- Numpy
- VSCode
- Python 특징
- 딥러닝
- python 문법
- Operation function
- namedtuple
- 최대가능도 추정법
- seaborn
- type hints
- Numpy data I/O
- groupby
- Comparisons
- BOXPLOT
- Python
- Today
- Total
또르르's 개발 Story
[24-3] 추천 시스템 using surprise library 본문
1️⃣ 설정
Surprise 모듈을 설치합니다.
!pip install surprise
필요한 모듈을 import 합니다.
import numpy as np
import pandas as pd
from surprise import SVD # 잠재 인수 모형
from surprise.model_selection import train_test_split
from surprise.dataset import DatasetAutoFolds
from surprise.model_selection import cross_validate # hyperparameter 찾기
from surprise import Dataset, Reader
from surprise import accuracy
2️⃣ 데이터셋 확인하기
데이터셋은 다음과 같은 형태로 구성되어 있습니다.
- ratings.csv : 평점
### Rating Dataset Format ###
userId movieId rating timestamp
0 1 1 4.0 964982703
1 1 3 4.0 964981247
2 1 6 4.0 964982224
3 1 47 5.0 964983815
4 1 50 5.0 964982931
- movies.csv : 영화
### Movie Dataset Format ###
Columns of Movie Dataset : Index(['movieId', 'title', 'genres'], dtype='object')
movieId ... genres
0 1 ... Adventure|Animation|Children|Comedy|Fantasy
1 2 ... Adventure|Children|Fantasy
2 3 ... Comedy|Romance
3 4 ... Comedy|Drama|Romance
4 5 ... Comedy
Dataset의 User, Movie 수를 확인하면 다음과 같습니다.
n_users = df_ratings.userId.unique().shape[0] # user의 유일한 값의 개수
n_items = df_ratings.movieId.unique().shape[0]
>>> print("num users: {}, num items:{}".format(n_users, n_items))
num users: 611, num items:9724
3️⃣ 데이터 전처리
영화 ID로부터 영화 제목을 얻는 과정입니다.
movie_set = set()
ratings = np.zeros((n_users, n_items))
for (_, movie_id, _) in df_ratings.itertuples(index=False):
movie_set.add(movie_id)
movie_id_to_name=dict()
movie_id_to_genre=dict()
for (movie_id, movie_name, movie_genre) in df_movies.itertuples(index=False):
if movie_id not in movie_set: # 어떤 영화가 rating data에 없는 경우 skip
continue
movie_id_to_name[movie_id] = movie_name
movie_id_to_genre[movie_id] = movie_genre
pandas dataframe을 surprise dataset 형태로 바꿔준 후, train set과 test set을 split 해줍니다.
reader = Reader(rating_scale=(0, 5)) # rating_scale : 평점의 최저점과 최고점
data = Dataset.load_from_df(df_ratings[['userId','movieId','rating']], reader=reader) # 사용자 col, movie col, 점수 col
train, test = train_test_split(data, test_size=0.2, shuffle=True) # 훈련 데이터, test 데이터를 나눠줌
Grid Search를 위해 surprise.trainset 형태의 데이터를 surprise.dataset으로 변경해줍니다.
iterator = train.all_ratings()
train_df = pd.DataFrame(columns=['userId', 'movieId', 'rating'])
i = 0
for (uid, iid, rating) in iterator:
train_df.loc[i] = [train.to_raw_uid(int(uid)), train.to_raw_iid(iid), rating]
i = i+1
train_data = Dataset.load_from_df(train_df, reader=reader)
4️⃣ 모델 설정 및 학습
Grid Search를 통해 최적의 Hyperparameter를 찾는 과정입니다.
from surprise.model_selection import GridSearchCV
param_grid = {'n_factors': [10,15,20,30,50,100]} # embedding 공간의 차원 6개를 시도할 것
다음 위의 param_grid의 6개 차원을 하나씩 돌려본 후 제일 좋은 성능의 차원으로 선택해서 hyperparameter를 설정합니다.
# SVD 모형 사용
# 탐색을 할 때 기준점으로 rmse, mae를 사용, rmse, mae를 기준으로 제일 좋은 hyperparameter 차원을 선택
# cv : cross validation을 할 때 4등분을 함
grid = GridSearchCV(SVD, param_grid, measures = ['rmse', 'mae'], cv=4)
grid.fit(train_data)
여기서 CV = 4는 Cross-validation의 약자로 다음과 같은 역할을 수행합니다.
평가 데이터를 제외한 train data 중 4등분을 해서 hyperparameter를 결정하는 방법입니다.
1,2,3번 데이터를 SVD train 시켜서 4번 데이터 평점을 가지고 가장 좋은 hyperparameter을 결정합니다.
한 번만 하는 것이 아닌,
- 1,2,3 -> 4번
- 1,2,4 -> 3번
- 2,3,4 -> 1번
- 1,3,4 -> 2번
총 4번을 각각 수행합니다.
Cross-validation을 사용하면 많은 데이터를 기반으로 학습을 할 수 있습니다.
가장 좋은 차원과 그때의 score는 다음과 같습니다.
>>> print(grid.best_params['rmse'])
{'n_factors': 10}
>>> print(grid.best_score['rmse'])
0.8760004730634828
이후, 가장 좋았던 차원을 입력으로 SVD를 사용해 학습시킵니다.
# grid.best_params['rmse']['n_factors'] : rmse 기준 가장 좋았던 차원을 입력으로 SVD에 집어넣음
# 이후 SVD로 학습을 수행
algorithm = SVD(grid.best_params['rmse']['n_factors'])
algorithm.fit(train)
5️⃣ 모델 예측
모델 예측은 SVD의 test 함수를 사용해 test data를 집어넣고 예측합니다.
prediction = algorithm.test(test)
for p in prediction[:5]: # prediction 결과값 5개 미리보기
print(p) # r_ui : 실제 rating 값, est: 예측된 rating 값
user: 318 item: 48 r_ui = 3.50 est = 3.34 {'was_impossible': False}
user: 68 item: 6944 r_ui = 4.50 est = 3.28 {'was_impossible': False}
user: 414 item: 5553 r_ui = 4.00 est = 3.17 {'was_impossible': False}
user: 298 item: 8641 r_ui = 4.00 est = 2.41 {'was_impossible': False}
user: 600 item: 1371 r_ui = 3.50 est = 2.60 {'was_impossible': False}
새로운 user, 새로운 item에 대한 prediction 값을 다음과 같이 구할 수 있습니다.
uid = 800
iid = 8368
prediction_user_item = algorithm.predict(uid, iid) # 학습한 객체로 predict 수행
>>> print(prediction_user_item)
user: 800 item: 8368 r_ui = None est = 3.98 {'was_impossible': False}
'부스트캠프 AI 테크 U stage > 실습' 카테고리의 다른 글
[31-2] VGG-11 구현 using PyTorch (0) | 2021.03.08 |
---|---|
[25-1] GraphSAGE 모델 구현 using DGL Library (0) | 2021.02.27 |
[24-2] Node2vec Library (0) | 2021.02.26 |
[23-3] Collaborative Filtering 구현 (0) | 2021.02.25 |
[23-2] Girvan-Newman Algorithm Using networkx (0) | 2021.02.25 |