如何优化LightFM的超参数?

时间:2018-04-18 10:02:27

标签: optimization hyperparameters recommender-systems

我在我的数据集中使用了LightFM推荐程序库,它会在下面的图片中显示结果。

Poor results after some epochs

NUM_THREADS = 4
NUM_COMPONENTS = 30
NUM_EPOCHS = 5
ITEM_ALPHA = 1e-6
LEARNING_RATE = 0.005
LEARNING_SCHEDULE = 'adagrad'
RANDOM_SEED = 29031994    

warp_model = LightFM(loss='warp',
                    learning_rate=LEARNING_RATE,
                    learning_schedule=LEARNING_SCHEDULE,
                    item_alpha=ITEM_ALPHA,
                    no_components=NUM_COMPONENTS,
                    random_state=RANDOM_SEED)

bpr_model = LightFM(loss='bpr',
                    learning_rate=LEARNING_RATE,
                    learning_schedule=LEARNING_SCHEDULE,
                    item_alpha=ITEM_ALPHA,
                    no_components=NUM_COMPONENTS,
                    random_state=RANDOM_SEED)

我的功能形状如下:

Item and user features shapes

如何优化我的超参数以改善曲线下面积(AUC)分数?

1 个答案:

答案 0 :(得分:4)

您可以在sklearn docs中找到有关超参数优化的良好一般指南。

您可以应用于优化LightFM模型的一种简单但有效的技术是random search。粗略地说,它包括以下步骤:

  1. 将您的数据拆分为训练集,验证集和测试集。
  2. 为要优化的每个超参数定义分布。例如,如果您正在优化学习率,则可以使用指数分布,平均值为0.05;如果您正在优化损失函数,则可以从['warp', 'bpr', 'warp-kos']
  3. 统一采样
  4. 在优化的每次迭代中,对所有超参数进行采样,并使用它们使模型适合训练数据。评估模型在验证集上的性能。
  5. 执行了许多优化步骤后,请选择具有最佳验证性能的步骤。
  6. 要衡量最终模型的性能,您应该使用测试集:只需评估测试集上的最佳验证模型。

    以下脚本说明了这一点:

    import itertools
    
    import numpy as np
    
    from lightfm import LightFM
    from lightfm.evaluation import auc_score
    
    
    def sample_hyperparameters():
        """
        Yield possible hyperparameter choices.
        """
    
        while True:
            yield {
                "no_components": np.random.randint(16, 64),
                "learning_schedule": np.random.choice(["adagrad", "adadelta"]),
                "loss": np.random.choice(["bpr", "warp", "warp-kos"]),
                "learning_rate": np.random.exponential(0.05),
                "item_alpha": np.random.exponential(1e-8),
                "user_alpha": np.random.exponential(1e-8),
                "max_sampled": np.random.randint(5, 15),
                "num_epochs": np.random.randint(5, 50),
            }
    
    
    def random_search(train, test, num_samples=10, num_threads=1):
        """
        Sample random hyperparameters, fit a LightFM model, and evaluate it
        on the test set.
    
        Parameters
        ----------
    
        train: np.float32 coo_matrix of shape [n_users, n_items]
            Training data.
        test: np.float32 coo_matrix of shape [n_users, n_items]
            Test data.
        num_samples: int, optional
            Number of hyperparameter choices to evaluate.
    
    
        Returns
        -------
    
        generator of (auc_score, hyperparameter dict, fitted model)
    
        """
    
        for hyperparams in itertools.islice(sample_hyperparameters(), num_samples):
            num_epochs = hyperparams.pop("num_epochs")
    
            model = LightFM(**hyperparams)
            model.fit(train, epochs=num_epochs, num_threads=num_threads)
    
            score = auc_score(model, test, train_interactions=train, num_threads=num_threads).mean()
    
            hyperparams["num_epochs"] = num_epochs
    
            yield (score, hyperparams, model)
    
    
    if __name__ == "__main__":
        from lightfm.datasets import fetch_movielens
    
        data = fetch_movielens()
        train = data["train"]
        test = data["test"]
    
        (score, hyperparams, model) = max(random_search(train, test, num_threads=2), key=lambda x: x[0])
    
        print("Best score {} at {}".format(score, hyperparams))