text_plain_output_3.png text_plain_output_2.png application_vnd.jupyter.stderr_output_1.png
import numpy as np # linear algebra

import pandas as pd

import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

import surprise

import surprise  #Scikit-Learn library for recommender systems.

raw = pd.read_csv('../input/ratings.csv')

raw.drop_duplicates(inplace=True)

raw = raw[['user_id', 'book_id', 'rating']]
reader = surprise.Reader(rating_scale=(1, 5))
data = surprise.Dataset.load_from_df(raw, reader)

class ProbabilisticMatrixFactorization(surprise.AlgoBase):
    def __init__(self, learning_rate, num_epochs, num_factors):
        self.alpha = learning_rate
        self.num_epochs = num_epochs
        self.num_factors = num_factors
    def fit(self, train):
        P = np.random.normal(0, 0.1, (train.n_users, self.num_factors))
        Q = np.random.normal(0, 0.1, (train.n_items, self.num_factors))
        for epoch in range(self.num_epochs):
            for u, i, r_ui in train.all_ratings():
                residual = r_ui - np.dot(P[u], Q[i])
                temp = P[u, :]
                P[u, :] += self.alpha * residual * Q[i]
                Q[i, :] += self.alpha * residual * temp
        self.P = P
        self.Q = Q
        self.trainset = train
    def estimate(self, u, i):
        if self.trainset.knows_user(u) and self.trainset.knows_item(i):
            nanCheck = np.dot(self.P[u], self.Q[i])
            if np.isnan(nanCheck):
                return self.trainset.global_mean
            else:
                return np.dot(self.P[u, :], self.Q[i, :])
        else:
            return self.trainset.global_mean

Alg1 = ProbabilisticMatrixFactorization(learning_rate=0.05, num_epochs=4, num_factors=10)
data1 = data.build_full_trainset()
Alg1.fit(data1)
Alg1.estimate(raw.user_id.iloc[4], raw.book_id.iloc[4])

gs = surprise.model_selection.GridSearchCV(ProbabilisticMatrixFactorization, param_grid={'learning_rate': [0.005, 0.01], 'num_epochs': [5, 10], 'num_factors': [10, 20]}, measures=['rmse', 'mae'], cv=2)
gs.fit(data)

best_params = gs.best_params['rmse']

bestVersion = ProbabilisticMatrixFactorization(learning_rate=best_params['learning_rate'], num_epochs=best_params['num_epochs'], num_factors=best_params['num_factors'])

kSplit = surprise.model_selection.KFold(n_splits=10, shuffle=True)
for train, test in kSplit.split(data):
    bestVersion.fit(train)
    prediction = bestVersion.test(test)
    surprise.accuracy.rmse(prediction, verbose=True)