from ..base import FeatureRecommenderMixin from ..model import OnlineSketch import numpy as np import numpy.linalg as ln import scipy.sparse as sp from sklearn import preprocessing from sklearn.utils.extmath import safe_sparse_dot class SketchRecommender(OnlineSketch, FeatureRecommenderMixin): """Online-matrix-sketching-based recommender References ---------- - T. Kitazawa. `Sketching Dynamic User-Item Interactions for Online Item Recommendation <http://dl.acm.org/citation.cfm?id=3022152>`_. In *Proc. of CHIIR 2017*, March 2017. """ def initialize(self): super(SketchRecommender, self).initialize() def register_user(self, user): super(SketchRecommender, self).register_user(user) def register_item(self, item): super(SketchRecommender, self).register_item(item) i_vec = item.encode(index=False, feature=True, vertical=True) i_vec = sp.csr_matrix(i_vec) if self.i_mat.size == 0: self.i_mat = i_vec else: self.i_mat = sp.csr_matrix(sp.hstack((self.i_mat, i_vec))) def update(self, e, batch_train=False): y = e.encode(index=False, feature=True, context=True) self.update_model(y) def score(self, user, candidates, context): # i_mat is (n_item_context, n_item) for all possible items # extract only target items i_mat = self.i_mat[:, candidates] n_target = len(candidates) # u_mat will be (n_user_context, n_item) for the target user u_vec = np.concatenate((user.feature, context)) u_vec = np.array([u_vec]).T u_mat = sp.csr_matrix(np.repeat(u_vec, n_target, axis=1)) # stack them into (p, n_item) matrix Y = sp.vstack((u_mat, i_mat)) Y = self.proj.reduce(Y) Y = sp.csr_matrix(preprocessing.normalize(Y, norm='l2', axis=0)) X = np.identity(self.k) - np.dot(self.U_r, self.U_r.T) A = safe_sparse_dot(X, Y, dense_output=True) return ln.norm(A, axis=0, ord=2) def recommend(self, user, candidates, context): scores = self.score(user, candidates, context) return self.scores2recos(scores, candidates)