영화 추천 - 높은 평균 평점 기준
2022. 3. 21. 18:36ㆍAI/Big data
- 목차
반응형
data loading
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('u.user', sep='|', names=u_cols, encoding='latin-1')
i_cols = ['movie_id', 'title', 'release date', 'video release date', 'IMDB URL', 'unknown',
'Action', 'Adventure', 'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary',
'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi',
'Thriller', 'War', 'Western']
movies = pd.read_csv('u.item', sep='|', names=i_cols, encoding='latin-1')
r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv('u.data', sep='\t', names=r_cols, encoding='latin-1')
user_id movie_id rating timestamp
0 196 242 3.0 881250949.0
1 186 302 3.0 891717742.0
2 22 377 1.0 878887116.0
3 244 51 2.0 880606923.0
4 166 346 1.0 886397596.0
... ... ... ... ...
53149 642 1311 3.0 886569715.0
53150 405 29 4.0 885545639.0
53151 151 614 4.0 879528729.0
53152 592 678 2.0 882607690.0
53153 194 2 NaN NaN
53154 rows × 4 columns
data cleaning
timestamp 제거
ratings = ratings.drop('timestamp', axis=1)
movies = movies[['movie_id', 'title']]
RMSE 및 score 함수 정의
def RMSE(y_true, y_pred):
return np.sqrt(np.mean((np.array(y_true) - np.array(y_pred))**2))
def score(model):
id_pairs = zip(x_test['user_id'], x_test['movie_id'])
y_pred = np.array([model(user, movie) for (user, movie) in id_pairs])
y_true = np.array(x_test['rating'])
return RMSE(y_true, y_pred)
data split
test와 train set으로 분리
x_train, x_test, y_train, y_test = train_test_split(ratings.copy(), ratings['user_id'], test_size=0.25, stratify=ratings['user_id'])
모든 user_id에 대해 movie_id를 갖도록 (NaN) matrix 생성
rating_matrix = x_train.pivot(index='user_id', columns='movie_id', values='rating')
movie_id 1 2 3 4 5 6 7 8 9 10 ... 1669 1670 1671 1672 1676 1677 1678 1680 1681 1682
user_id
1 NaN 3.0 NaN 3.0 3.0 5.0 4.0 1.0 5.0 3.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 4.0 NaN NaN NaN NaN NaN NaN NaN NaN 2.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 4.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
939 NaN NaN NaN NaN NaN NaN NaN NaN 5.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
940 NaN NaN NaN NaN NaN NaN NaN 5.0 3.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
941 NaN NaN NaN NaN NaN NaN 4.0 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
942 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
943 NaN 5.0 NaN NaN NaN NaN NaN NaN 3.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
943 rows × 1654 columns
movie_id 별 모든 평점에 대한 평균 계산
train_mean = x_train.groupby(['movie_id'])['rating'].mean()
def best_seller(user_id, movie_id):
try:
rating = train_mean[movie_id]
except:
rating = 3.0
return rating
모든 user에 대해 모든 movie로 모델 구동 후 RMSE의 평균 리턴
score(best_seller)
1.0283376783529838
train data와 user data의 merge
merge 하여 두 table을 비정규화
merged_ratings = pd.merge(x_train, users)
user_id movie_id rating age sex occupation zip_code
0 18 408 5 35 F other 37212
1 18 963 5 35 F other 37212
2 18 692 3 35 F other 37212
3 18 476 3 35 F other 37212
4 18 753 4 35 F other 37212
... ... ... ... ... ... ... ...
74995 801 332 5 22 M writer 92154
74996 801 313 5 22 M writer 92154
74997 801 326 4 22 M writer 92154
74998 801 681 1 22 M writer 92154
74999 801 890 2 22 M writer 92154
75000 rows × 7 columns
movie_id 별 sex로 평균을 구분하여 계산
g_mean = merged_ratings[['movie_id', 'sex', 'rating']].groupby(['movie_id', 'sex'])['rating'].mean()
movie_id sex
1 F 3.787234
M 3.910204
2 F 3.500000
M 3.214286
3 F 2.642857
...
1677 F 3.000000
1678 M 1.000000
1680 M 2.000000
1681 M 3.000000
1682 M 3.000000
Name: rating, Length: 3057, dtype: float64
def cf_gender(user_id, movie_id):
if movie_id in rating_matrix:
gender = users.loc[user_id]['sex']
if gender in g_mean[movie_id]:
gender_rating = g_mean[movie_id][gender]
else:
gender_rating = 3.0
else:
gender_rating = 3.0
return gender_rating
score(cf_gender)
1.0481358433234231
movie를 직업으로 구분하여 평균 계산
o_mean = merged_ratings[['movie_id', 'sex', 'rating', 'occupation']].groupby(['movie_id', 'occupation'])['rating'].mean()
movie_id occupation
1 administrator 4.086957
artist 4.000000
doctor 3.333333
educator 3.793103
engineer 4.171429
...
1677 student 3.000000
1678 student 1.000000
1680 student 2.000000
1681 writer 3.000000
1682 engineer 3.000000
Name: rating, Length: 16775, dtype: float64
def cf_occupation(user_id, movie_id):
if user_id >= 943:
return 3.0
if movie_id in rating_matrix:
gender = users.loc[user_id]['occupation']
if gender in o_mean[movie_id]:
gender_rating = o_mean[movie_id][gender]
else:
gender_rating = 3.0
else:
gender_rating = 3.0
return gender_rating
score(cf_occupation)
1.1415335518618561
반응형
'AI > Big data' 카테고리의 다른 글
CF considering neighbor (0) | 2022.03.22 |
---|---|
Collaboration Filtering (0) | 2022.03.21 |
hyperparameter tuning (0) | 2022.03.19 |
Titanic data training (0) | 2022.03.19 |
Titanic data analysis (0) | 2022.03.19 |