Exemple #1
0
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
Exemple #3
0
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")