class Hybrid3ScoreSubRecommender(BaseRecommender): """Hybrid3ScoreSubRecommender recommender""" RECOMMENDER_NAME = "Hybrid3ScoreRecommender" def __init__(self, data: DataObject): super(Hybrid3ScoreSubRecommender, self).__init__(data.urm_train) urm = sps.vstack([data.urm_train, data.icm_all_augmented.T]) urm = urm.tocsr() self.slim = SLIMElasticNetRecommender(urm) self.rp3 = RP3betaRecommender(self.URM_train) self.itemcf = ItemKNNCFRecommender(self.URM_train) self.random_seed = data.random_seed def fit(self, alpha_beta_ratio=1, alpha_gamma_ratio=1): try: self.slim.load_model('stored_recommenders/slim_elastic_net/', f'with_icm_{self.random_seed}_topK=100_l1_ratio=0.04705_alpha=0.00115_positive_only=True_max_iter=35') except: self.slim.fit(topK=100, l1_ratio=0.04705, alpha=0.00115, positive_only=True, max_iter=35) self.slim.save_model('stored_recommenders/slim_elastic_net/', f'with_icm_{self.random_seed}_topK=100_l1_ratio=0.04705_alpha=0.00115_positive_only=True_max_iter=35') self.rp3.fit(topK=20, alpha=0.16, beta=0.24) self.itemcf.fit(topK=22, shrink=850, similarity='jaccard', feature_weighting='BM25') self.alpha = 1 self.beta = alpha_beta_ratio self.gamma = alpha_gamma_ratio def _compute_item_score(self, user_id_array, items_to_compute = None): # ATTENTION! # THIS METHOD WORKS ONLY IF user_id_array IS A SCALAR AND NOT AN ARRAY # TODO scores_slim = self.slim._compute_item_score(user_id_array=user_id_array) scores_rp3 = self.rp3._compute_item_score(user_id_array=user_id_array) scores_itemcf = self.itemcf._compute_item_score(user_id_array=user_id_array) # normalization slim_max = scores_slim.max() rp3_max = scores_rp3.max() itemcf_max = scores_itemcf.max() if not slim_max == 0: scores_slim /= slim_max if not rp3_max == 0: scores_rp3 /= rp3_max if not itemcf_max == 0: scores_itemcf /= itemcf_max scores_total = self.alpha * scores_slim + self.beta * scores_rp3 + self.gamma * scores_itemcf return scores_total
class Hybrid3ScoreRecommender(BaseRecommender): """Hybrid3ScoreRecommender recommender""" RECOMMENDER_NAME = "Hybrid3ScoreRecommender" def __init__(self, data: DataObject, random_seed: int, alpha=1): super(Hybrid3ScoreRecommender, self).__init__(data.urm_train) self.random_seed = random_seed self.slim = SLIMElasticNetRecommender(self.URM_train) self.rp3 = RP3betaRecommender(self.URM_train) self.itemcf = ItemKNNCFRecommender(self.URM_train) self.alpha = alpha def fit(self, alpha_beta_ratio=1, alpha_gamma_ratio=1): self.slim.load_model( '', 'SLIM_ElasticNetURM_seed=' + str(self.random_seed) + '_topK=100_l1_ratio=0.04705_alpha=0.00115_positive_only=True_max_iter=35' ) self.rp3.fit(topK=20, alpha=0.16, beta=0.24) self.itemcf.fit(topK=22, shrink=850, similarity='jaccard', feature_weighting='BM25') # self.alpha = 1 self.beta = self.alpha * alpha_beta_ratio self.gamma = self.alpha * alpha_gamma_ratio def _compute_item_score(self, user_id_array, items_to_compute=None): # ATTENTION! # THIS METHOD WORKS ONLY IF user_id_array IS A SCALAR AND NOT AN ARRAY # TODO scores_slim = self.slim._compute_item_score( user_id_array=user_id_array) scores_rp3 = self.rp3._compute_item_score(user_id_array=user_id_array) scores_itemcf = self.itemcf._compute_item_score( user_id_array=user_id_array) # normalization slim_max = scores_slim.max() rp3_max = scores_rp3.max() itemcf_max = scores_itemcf.max() if not slim_max == 0: scores_slim /= slim_max if not rp3_max == 0: scores_rp3 /= rp3_max if not itemcf_max == 0: scores_itemcf /= itemcf_max scores_total = self.alpha * scores_slim + self.beta * scores_rp3 + self.gamma * scores_itemcf return scores_total
class LinearHybridC001(BaseItemSimilarityMatrixRecommender): RECOMMENDER_NAME = "LinearHybridC001" """ This hybrid works for users who have a profile length shorter or equal to 2 interactions """ # set the seed equal to the one of the parameter search!!!! def __init__(self, URM_train, ICM_train, submission=False, verbose=True, seed=1205): super(LinearHybridC001, self).__init__(URM_train, verbose=verbose) self.URM_train = URM_train self.ICM_train = ICM_train # seed 1205: {'num_factors': 83, 'confidence_scaling': 'linear', 'alpha': 28.4278070726612, 'epsilon': # 1.0234211788885077, 'reg': 0.0027328110246575004, 'epochs': 20} self.__rec1 = IALSRecommender(URM_train, verbose=False) self.__rec1_params = { 'num_factors': 83, 'confidence_scaling': 'linear', 'alpha': 28.4278070726612, 'epsilon': 1.0234211788885077, 'reg': 0.0027328110246575004, 'epochs': 15 } #### -5!! # seed 1205: {'topK': 225, 'shrink': 1000, 'similarity': 'cosine', 'normalize': True, 'feature_weighting': # 'BM25'} self.__rec2 = ItemKNNCBFRecommender(URM_train, ICM_train, verbose=False) self.__rec2_params = { 'topK': 225, 'shrink': 1000, 'similarity': 'cosine', 'normalize': True, 'feature_weighting': 'BM25' } # seed 1205: {'topK': 220, 'shrink': 175, 'similarity': 'cosine', 'normalize': False} self.__rec3 = ItemKNNCFRecommender(URM_train, verbose=False) self.__rec3_params = { 'topK': 220, 'shrink': 175, 'similarity': 'cosine', 'normalize': False } self.__a = self.__b = self.__c = None self.seed = seed self.__submission = submission def fit(self, alpha=0.5, l1_ratio=0.5): self.__a = alpha * l1_ratio self.__b = alpha - self.__a self.__c = 1 - self.__a - self.__b if not self.__submission: try: self.__rec1.load_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec1.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec1.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec1.RECOMMENDER_NAME} ...") self.__rec1.fit(**self.__rec1_params) print(f"done.") self.__rec1.save_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec1.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') try: self.__rec2.load_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec2.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec2.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec2.RECOMMENDER_NAME} ...") self.__rec2.fit(**self.__rec2_params) print(f"done.") self.__rec2.save_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec2.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') try: self.__rec3.load_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec3.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec3.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec3.RECOMMENDER_NAME} ...") self.__rec3.fit(**self.__rec3_params) print(f"done.") self.__rec3.save_model( f'stored_recommenders/seed_{str(self.seed)}_{self.__rec3.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') else: self.__rec1.fit(**self.__rec1_params) self.__rec2.fit(**self.__rec2_params) self.__rec3.fit(**self.__rec3_params) def _compute_item_score(self, user_id_array, items_to_compute=None): item_weights_1 = self.__rec1._compute_item_score(user_id_array) item_weights_2 = self.__rec2._compute_item_score(user_id_array) item_weights_3 = self.__rec3._compute_item_score(user_id_array) item_weights = item_weights_1 * self.__a + item_weights_2 * self.__b + item_weights_3 * self.__c return item_weights def save_model(self, folder_path, file_name=None): if file_name is None: file_name = self.RECOMMENDER_NAME self._print("Saving model in file '{}'".format(folder_path + file_name)) dataIO = DataIO(folder_path=folder_path) dataIO.save_data(file_name=file_name, data_dict_to_save={}) self._print("Saving complete")
class LinearHybrid001(BaseItemSimilarityMatrixRecommender): RECOMMENDER_NAME = "LinearHybrid001" # set the seed equal to the one of the parameter search!!!! def __init__(self, URM_train, ICM_train, submission=False, verbose=True, seed=1205): super(LinearHybrid001, self).__init__(URM_train, verbose = verbose) self.URM_train = URM_train self.ICM_train = ICM_train self.__rec1 = SLIMElasticNetRecommender(URM_train, verbose=False) self.__rec1_params = {'topK': 120, 'l1_ratio': 1e-5, 'alpha': 0.066} # seed 1205: 'topK': 620, 'shrink': 121, 'similarity': 'asymmetric', 'normalize': True, 'asymmetric_alpha': 0.5526988987666924 self.__rec2 = ItemKNNCFRecommender(URM_train, verbose=False) self.__rec2_params = {'topK': 620, 'shrink': 121, 'similarity': 'asymmetric', 'normalize': True, 'asymmetric_alpha': 0.5526988987666924} # seed 1205: 'topK': 115, 'shrink': 1000, 'similarity': 'cosine', 'normalize': True, 'feature_weighting': 'BM25' self.__rec3 = ItemKNNCBFRecommender(URM_train, ICM_train, verbose=False) self.__rec3_params = {'topK': 115, 'shrink': 1000, 'similarity': 'cosine', 'normalize': True, 'feature_weighting': 'BM25'} self.__a = self.__b = self.__c = None self.seed=seed self.__submission=submission def fit(self, alpha=0.5, l1_ratio=0.5): self.__a = alpha * l1_ratio self.__b = alpha - self.__a self.__c = 1 - self.__a - self.__b if not self.__submission: try: self.__rec1.load_model('stored_recommenders/'+self.__rec1.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') print(f"{self.__rec1.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec1.RECOMMENDER_NAME} ...") self.__rec1.fit(**self.__rec1_params) print(f"done.") self.__rec1.save_model('stored_recommenders/'+self.__rec1.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') try: self.__rec2.load_model('stored_recommenders/'+self.__rec2.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') print(f"{self.__rec2.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec2.RECOMMENDER_NAME} ...") self.__rec2.fit(**self.__rec2_params) print(f"done.") self.__rec2.save_model('stored_recommenders/'+self.__rec2.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') try: self.__rec3.load_model('stored_recommenders/'+self.__rec3.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') print(f"{self.__rec3.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec3.RECOMMENDER_NAME} ...") self.__rec3.fit(**self.__rec3_params) print(f"done.") self.__rec3.save_model('stored_recommenders/'+self.__rec3.RECOMMENDER_NAME+'/', f'seed_{str(self.seed)}_best_for_LinearHybrid001') else: self.__rec1.fit(**self.__rec1_params) self.__rec2.fit(**self.__rec2_params) self.__rec3.fit(**self.__rec3_params) def _compute_item_score(self, user_id_array, items_to_compute=None): item_weights_1 = self.__rec1._compute_item_score(user_id_array) item_weights_2 = self.__rec2._compute_item_score(user_id_array) item_weights_3 = self.__rec3._compute_item_score(user_id_array) item_weights = item_weights_1 * self.__a + item_weights_2 * self.__b + item_weights_3 * self.__c return item_weights def save_model(self, folder_path, file_name = None): if file_name is None: file_name = self.RECOMMENDER_NAME self._print("Saving model in file '{}'".format(folder_path + file_name)) dataIO = DataIO(folder_path=folder_path) dataIO.save_data(file_name=file_name, data_dict_to_save = {}) self._print("Saving complete")
class Hybrid(BaseRecommender): RECOMMENDER_NAME = "Hybrid" def __init__(self, URM_train, ICM): super(Hybrid, self).__init__(URM_train) self.ICM = ICM def fit(self): ICM = similaripy.normalization.bm25plus(self.ICM) URM_aug = sps.vstack([self.URM_train, ICM.T]) # initialize recommenders self.ItemCF1 = ItemKNNCFRecommender(self.URM_train) self.ItemCF2 = ItemKNNCFRecommender(self.URM_train) self.ItemCF4 = ItemKNNCFRecommender(self.URM_train) self.RP3BetaY = RP3betaRecommender(URM_aug) self.als2 = ALS(URM_aug) self.als3 = ALS(URM_aug) # fit recommenders self.ItemCF1.fit(2237, 1397, "rp3beta", "bm25plus", "bm25", rp3_alpha=0.301146, rp3_beta=0.602561) self.ItemCF2.fit(4820, 1998, "rp3beta", "bm25plus", "bm25", rp3_alpha=0.298947, rp3_beta=0.613693) self.ItemCF4.fit(2521, 330, "rp3beta", "bm25plus", "bm25", rp3_alpha=0.749552, rp3_beta=0.987574) self.RP3BetaY.fit(alpha=0.638822, beta=0.429194, topK=4161, implicit=False, normalize_similarity=False) self.h_4 = ItemKNNSimilarityHybridRecommender(self.URM_train, self.ItemCF4.W_sparse, self.RP3BetaY.W_sparse) self.h_4.fit(topK=3583, alpha=0.717524) self.als2.fit(latent_factors=610, regularization=0.09143425, iterations=10, alpha=44) self.als3.fit(latent_factors=418, regularization=0.08360787, iterations=10, alpha=34) def _compute_item_score(self, user_id_array, items_to_compute=None): item_weights = np.empty([len(user_id_array), 25975]) for i in range(len(user_id_array)): n_interactions = len(self.URM_train[user_id_array[i], :].indices) if n_interactions < 5: w = self.ItemCF1._compute_item_score(user_id_array[i], items_to_compute) item_weights[i, :] = w elif n_interactions > 4 and n_interactions < 10: w1 = self.ItemCF2._compute_item_score(user_id_array[i], items_to_compute) w2 = self.als2._compute_item_score(user_id_array[i], items_to_compute) w1 = w1 / la.norm(w1, 2) w2 = w2 / la.norm(w2, 2) w = w1 * 0.995739 + w2 * 0.997557 item_weights[i, :] = w elif n_interactions > 9 and n_interactions < 50: w1 = self.ItemCF1._compute_item_score(user_id_array[i], items_to_compute) w2 = self.als3._compute_item_score(user_id_array[i], items_to_compute) w1 = w1 / la.norm(w1, 2) w2 = w2 / la.norm(w2, 2) w = w1 * 0.988447 + w2 * 0.924441 item_weights[i, :] = w else: w = self.h_4._compute_item_score(user_id_array[i], items_to_compute) item_weights[i, :] = w return item_weights
class LinearHybridW001(BaseItemSimilarityMatrixRecommender): RECOMMENDER_NAME = "LinearHybridW001" """ This hybrid works for users who have a profile length greater than or equal to 3 interactions """ # set the seed equal to the one of the parameter search!!!! def __init__(self, URM_train, ICM_train, submission=False, verbose=True, seed=1205): super(LinearHybridW001, self).__init__(URM_train, verbose=verbose) self.URM_train = URM_train self.ICM_train = ICM_train # seed 1205: {'topK': 205, 'shrink': 1000, 'similarity': 'cosine', # 'normalize': True, 'feature_weighting': 'BM25'} self.__rec1 = ItemKNNCBFRecommender(URM_train,ICM_train, verbose=False) self.__rec1_params = {'topK': 205, 'shrink': 1000, 'similarity': 'cosine', 'normalize': True, 'feature_weighting': 'BM25'} # seed 1205: {'topK': 565, 'shrink': 554, 'similarity': 'tversky', 'normalize': True, # 'tversky_alpha': 1.9109121434662428, 'tversky_beta': 1.7823834698905734} self.__rec2 = ItemKNNCFRecommender(URM_train, verbose=False) self.__rec2_params = {'topK': 565, 'shrink': 554, 'similarity': 'tversky', 'normalize': True, 'tversky_alpha': 1.9109121434662428, 'tversky_beta': 1.7823834698905734} # seed 1205: {'topK': 753, 'alpha': 0.3873710051288722, 'beta': 0.0, 'normalize_similarity': False} self.__rec3 = RP3betaRecommender(URM_train, verbose=False) self.__rec3_params = {'topK': 753, 'alpha': 0.3873710051288722, 'beta': 0.0, 'normalize_similarity': False} self.__a = self.__b = self.__c = None self.seed = seed self.__submission = submission def fit(self, alpha=0.5, l1_ratio=0.5): self.__a = alpha * l1_ratio self.__b = alpha - self.__a self.__c = 1 - self.__a - self.__b if not self.__submission: try: self.__rec1.load_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec1.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec1.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec1.RECOMMENDER_NAME} ...") self.__rec1.fit(**self.__rec1_params) print(f"done.") self.__rec1.save_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec1.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') try: self.__rec2.load_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec2.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec2.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec2.RECOMMENDER_NAME} ...") self.__rec2.fit(**self.__rec2_params) print(f"done.") self.__rec2.save_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec2.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') try: self.__rec3.load_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec3.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') print(f"{self.__rec3.RECOMMENDER_NAME} loaded.") except: print(f"Fitting {self.__rec3.RECOMMENDER_NAME} ...") self.__rec3.fit(**self.__rec3_params) print(f"done.") self.__rec3.save_model(f'stored_recommenders/seed_{str(self.seed)}_{self.__rec3.RECOMMENDER_NAME}/', f'best_for_{self.RECOMMENDER_NAME}') else: self.__rec1.fit(**self.__rec1_params) self.__rec2.fit(**self.__rec2_params) self.__rec3.fit(**self.__rec3_params) def _compute_item_score(self, user_id_array, items_to_compute=None): item_weights_1 = self.__rec1._compute_item_score(user_id_array) item_weights_2 = self.__rec2._compute_item_score(user_id_array) item_weights_3 = self.__rec3._compute_item_score(user_id_array) item_weights = item_weights_1 * self.__a + item_weights_2 * self.__b + item_weights_3 * self.__c return item_weights def save_model(self, folder_path, file_name=None): if file_name is None: file_name = self.RECOMMENDER_NAME self._print("Saving model in file '{}'".format(folder_path + file_name)) dataIO = DataIO(folder_path=folder_path) dataIO.save_data(file_name=file_name, data_dict_to_save={}) self._print("Saving complete")