# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('./archive/ml-100k/u.user', sep='|', names=u_cols, encoding='latin-1')
users.head()

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('./archive/ml-100k/u.item', sep='|', names=i_cols, encoding='latin-1')
movies.head()

movies = movies[['movie_id', 'title']]

r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv('./archive/ml-100k/u.data', sep='\t', names=r_cols, encoding='latin-1')
ratings.head()

ratings = ratings.drop('timestamp', axis=1)

from sklearn.model_selection import train_test_split

X = ratings.copy()
y = ratings['user_id']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)

from sklearn.metrics import mean_squared_error


def rmse(y_true, y_pred):
    return np.sqrt(mean_squared_error(y_true, y_pred))


def baseline(user_id, movie_id):
    return 3.0


def score(cf_model):
    id_pairs = zip(X_test['user_id'], X_test['movie_id'])
    y_pred = np.array([cf_model(user_id, movie_id) for user_id, movie_id in id_pairs])
    y_true = np.array(X_test['rating'])
    return rmse(y_true, y_pred)


score(baseline)

# # User based collaborative filtering

r_matrix = X_train.pivot_table(values='rating', index='user_id', columns='movie_id')

r_matrix.head()


def cf_user_mean(user_id, movie_id):
    if movie_id in r_matrix:
        mean_rating = r_matrix[movie_id].mean()
    else:
        mean_rating = 3.0
    return mean_rating


score(cf_user_mean)

r_matrix_dummy = r_matrix.copy().fillna(0)

from sklearn.metrics.pairwise import cosine_similarity

cosine_sim = cosine_similarity(r_matrix_dummy, r_matrix_dummy)

cosine_sim = pd.DataFrame(cosine_sim, index=r_matrix.index, columns=r_matrix.index)

cosine_sim.head()


def  cf_user_wmean(user_id, movie_id):
    if movie_id in r_matrix:
        sim_score = cosine_sim[user_id]
        m_ratings =  r_matrix[movie_id]
        idx = m_ratings[m_ratings.isnull()].index
        m_ratings = m_ratings.dropna()
        sim_score = sim_score.drop(idx)
        wmean_rating = np.dot(sim_score, m_ratings)/sim_score.sum()
        
    else:
        wmean_rating = 3.0
    return wmean_rating


score(cf_user_wmean)

merged_df = pd.merge(X_train, users)

merged_df.head()

gender_mean = merged_df[['movie_id', 'sex', 'rating']].groupby(['movie_id','sex']).mean()

users = users.set_index('user_id')


def cf_gender(user_id, movie_id):
    if (movie_id in gender_mean) & (movie_id in r_matrix):
        gender = users.loc[user_id]['sex']
        if gender in gender_mean[movie_id]:
            gender_rating = gender_mean[movie_id][gender]
        else:
            gender_rating = 3.0
    else:
        gender_rating = 3.0
    return gender_rating


score(cf_gender)

gen_occ_mean = merged_df[['sex', 'rating', 'movie_id', 'occupation']].pivot_table(values='rating', index='movie_id', columns=['occupation', 'sex'],aggfunc='mean')
gen_occ_mean.head()


def cf_gen_occ(user_id, movie_id):
    if (movie_id in gen_occ_mean) & (movie_id in r_matrix):
        user = users[user_id]
        
        occ = user['occupation']
        gen = user['sex']
        
        if occ in gen_occ_mean.loc[movie_id]:
            if gender in gen_occ_mean.loc[movie_id][occ]:
                rating = gen_occ_mean.loc[movie_id][occ][gender]
                if np.isnan(rating):
                    rating = 3.0
                return rating
    
    return 3.0


score(cf_gen_occ)

from surprise import Reader, Dataset, KNNBasic
from surprise.model_selection import cross_validate

reader = Reader()

data = Dataset.load_from_df(ratings, reader)

knn = KNNBasic()

cross_validate(knn, data, measures=['RMSE'])

from surprise import SVD

svd = SVD()

cross_validate(svd, data, measures=['RMSE'])

ratings = pd.read_csv('./archive/ratings_small.csv')
data = Dataset.load_from_df(ratings[['userId', 'movieId', 'rating']], reader)

svd = SVD()
trainset = data.build_full_trainset()

svd.fit(trainset)

id_map = pd.read_csv('./archive/movies_metadata.csv')
id_to_title = id_map.set_index('id')
title_to_id = id_map.set_index('title')

cosine_sim_map = {}
for i in cosine_sim.index:
    title = id


def hybrid(userId, title):
    idx = title_to_id.loc[title]['id']
    tmdbId = title_to_id.loc[title]['id']
    movie_id = title_to_id.loc[title]['id']
    sim_scores = list(enumerate(cosine_sim[int(idx)]))
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    sim_scores = sim_scores[1:26]
    movie_indices = [i[0] for i in sim_scores]
#     print(movie_indices)
    movies = id_map.iloc[movie_indices][['title', 'vote_count', 'vote_average','id']]
    movies['est'] = movies['id'].apply(lambda x: svd.predict(userId, x).est)
    movies = movies.sort_values('est', ascending=False)
    return movies.head(10)


hybrid(1, 'Toy Story')

hybrid(2, 'Toy Story')





StarcoderdataJupyterScriptsDedupFiltered