博客

  • 黎曼低秩矩阵补全算法:电影推荐系统的新星

    在当今数据驱动的世界中,推荐系统已成为我们日常生活中不可或缺的一部分。无论是在线购物、音乐流媒体还是视频平台,这些系统都在幕后默默工作,为我们筛选出最感兴趣的内容。今天,我们要深入探讨一种强大而新颖的推荐算法——黎曼低秩矩阵补全(Riemannian Low-rank Matrix Completion,简称RLRMC),以及它在电影推荐领域的应用。

    RLRMC算法简介

    RLRMC是一种基于矩阵分解的矩阵补全算法,它利用黎曼共轭梯度算法来解决优化问题。这个算法的理论基础来自于Jawanpuria和Mishra(2018)以及Mishra等人(2013)的研究工作。

    在RLRMC中,用户-电影评分矩阵被建模为一个低秩矩阵。假设我们有d部电影和T个用户,评分矩阵M的大小为d×T。RLRMC算法假设M是部分已知的,其中M(i,j)表示第j个用户对第i部电影的评分。

    RLRMC的核心思想是将矩阵M分解为两个较小的矩阵的乘积:M = LR^T,其中L是一个d×r的矩阵,R是一个T×r的矩阵。这里的r是一个需要预先设定的超参数,称为”秩”,通常远小于d和T。

    RLRMC的优势

    1. 处理稀疏数据的能力:在实际应用中,用户-电影评分矩阵通常是高度稀疏的。RLRMC能够有效地处理这种稀疏性,从有限的评分数据中学习出有意义的潜在特征。
    2. 计算效率:通过利用黎曼优化框架,RLRMC能够在保证收敛性的同时,比传统的欧几里德空间优化方法更快地找到最优解。
    3. 灵活性:RLRMC可以轻松地与其他机器学习技术结合,如正则化和交叉验证,以进一步提高模型的性能和泛化能力。
    4. 理论保证:RLRMC有着坚实的数学基础,这使得它在某些情况下可以提供理论上的收敂性和最优性保证。

    实践:使用RLRMC进行电影推荐

    让我们通过一个实际的例子来看看如何使用RLRMC算法进行电影推荐。我们将使用著名的MovieLens数据集来演示整个过程。

    数据准备

    首先,我们需要下载并加载MovieLens数据集:

    from recommenders.datasets import movielens
    
    df = movielens.load_pandas_df(
        size='10m',
        header=["userID", "itemID", "rating", "timestamp"]
    )

    这里我们使用了MovieLens 10M数据集,它包含了约10万用户对10681部电影的1000万条评分数据。

    数据分割

    接下来,我们需要将数据集分割为训练集和测试集:

    from recommenders.datasets.python_splitters import python_random_split
    from recommenders.models.rlrmc.RLRMCdataset import RLRMCdataset
    
    train, test = python_random_split(df, [0.8, 0.2])
    data = RLRMCdataset(train=train, test=test)

    我们使用80%的数据作为训练集,20%的数据作为测试集。

    模型训练

    现在,我们可以初始化并训练RLRMC模型:

    from recommenders.models.rlrmc.RLRMCalgorithm import RLRMCalgorithm
    
    model = RLRMCalgorithm(rank=10,
                           C=0.001,
                           model_param=data.model_param,
                           initialize_flag='svd',
                           maxiter=100,
                           max_time=300)
    
    model.fit(data, verbosity=0)

    在这个例子中,我们设置了以下参数:

    • rank=10:模型的秩,这决定了潜在特征空间的维度。
    • C=0.001:正则化参数,用于防止过拟合。
    • initialize_flag='svd':使用奇异值分解(SVD)来初始化模型参数。
    • maxiter=100:最大迭代次数。
    • max_time=300:最大运行时间(秒)。

    预测和评估

    训练完成后,我们可以使用模型对测试集进行预测:

    predictions_ndarr = model.predict(test['userID'].values, test['itemID'].values)
    predictions_df = pd.DataFrame(data={"userID": test['userID'].values, "itemID": test['itemID'].values, "prediction": predictions_ndarr})

    最后,我们可以评估模型的性能:

    from recommenders.evaluation.python_evaluation import rmse, mae
    
    eval_rmse = rmse(test, predictions_df)
    eval_mae = mae(test, predictions_df)
    
    print(f"RMSE: {eval_rmse}")
    print(f"MAE: {eval_mae}")

    在这个例子中,我们使用了均方根误差(RMSE)和平均绝对误差(MAE)作为评估指标。

    RLRMC的未来展望

    尽管RLRMC在推荐系统领域展现出了巨大的潜力,但仍有一些值得探索的方向:

    1. 大规模数据处理:随着数据规模的不断增长,如何在保持计算效率的同时处理更大规模的数据集是一个重要的研究方向。
    2. 动态更新:在实际应用中,用户的偏好可能会随时间变化。开发能够动态更新的RLRMC变体将是一个有趣的研究方向。
    3. 解释性:虽然RLRMC在预测准确性上表现出色,但其黑盒性质使得难以解释推荐结果。提高模型的可解释性将有助于增加用户对推荐系统的信任。
    4. 结合深度学习:将RLRMC与深度学习技术结合,可能会产生更强大的推荐模型。
    5. 多模态数据融合:在实际的推荐系统中,除了评分数据外,还可能有用户的人口统计信息、商品的特征描述等。如何将这些多模态数据融入RLRMC模型是一个有价值的研究方向。

    结语

    黎曼低秩矩阵补全算法为推荐系统带来了新的可能性。通过结合先进的数学理论和实用的工程技巧,RLRMC展示了如何在复杂的实际应用中实现高性能的推荐。随着研究的深入和技术的发展,我们可以期待看到RLRMC在更广泛的领域中发挥作用,不仅限于电影推荐,还可能扩展到音乐、新闻、产品等多个领域。

  • 受限玻尔兹曼机在电影推荐中的应用

    在这个快节奏的数字时代,个性化推荐系统已经成为我们日常生活中不可或缺的一部分。无论是在线购物、音乐流媒体还是视频平台,推荐算法都在幕后默默工作,为我们筛选出最感兴趣的内容。今天,让我们深入探讨一种强大而独特的推荐算法 – 受限玻尔兹曼机(Restricted Boltzmann Machine, RBM),以及它在电影推荐领域的应用。

    RBM简介

    受限玻尔兹曼机是一种生成式神经网络模型,通常用于无监督学习。它的主要任务是学习可见单元v和隐藏单元h的联合概率分布P(v,h)。在这个模型中,隐藏单元代表潜在变量,而可见单元则与输入数据相对应。一旦学习到联合分布,模型就可以通过从中采样来生成新的样本。

    RBM在推荐系统中的应用基于协同过滤的思想。与传统的矩阵分解方法不同,RBM学习的是用户-物品亲和矩阵背后的概率分布,而不仅仅是重现矩阵的一个实例。这种方法有几个显著的优势:

    1. 泛化能力强:模型能够很好地适应新的样本。
    2. 时间稳定性:如果推荐任务在时间上是静态的,模型不需要频繁重新训练来适应新的评分或用户。
    3. GPU加速:使用TensorFlow实现的RBM可以在GPU上快速训练。

    数据准备

    在这个例子中,我们使用著名的MovieLens数据集来演示RBM在电影推荐中的应用。具体来说,我们选择了包含943个用户对1682部电影的10万条评分数据的MovieLens-100k数据集。

    首先,我们需要加载数据并进行预处理:

    import pandas as pd
    from recommenders.datasets import movielens
    
    # 加载MovieLens-100k数据集
    data = movielens.load_pandas_df(
        size='100k',
        header=['userID', 'movieID', 'rating', 'timestamp']
    )

    数据集包含四列:用户ID、电影ID、评分(1-5分)和时间戳。

    数据分割

    在训练推荐模型时,数据分割是一个关键步骤。与传统的监督学习不同,我们需要保持训练集和测试集的矩阵大小相同,但包含不同的评分数据。这是因为我们需要为每个用户预测所有可能的电影评分。

    from recommenders.datasets.python_splitters import numpy_stratified_split
    from recommenders.datasets.sparse import AffinityMatrix
    
    # 生成用户-电影亲和矩阵
    am = AffinityMatrix(df=data, col_user='userID', col_item='movieID', col_rating='rating')
    X, _, _ = am.gen_affinity_matrix()
    
    # 分割数据集
    Xtr, Xtst = numpy_stratified_split(X)

    这里,X是完整的用户-电影评分矩阵,XtrXtst分别是训练集和测试集矩阵。值得注意的是,这两个矩阵具有相同的维度(943×1682),但包含不同的评分数据。

    RBM模型训练

    现在,让我们开始训练RBM模型。我们使用TensorFlow实现的RBM类,该类封装了模型的初始化、训练和预测过程。

    from recommenders.models.rbm.rbm import RBM
    
    # 初始化RBM模型
    model = RBM(
        possible_ratings=np.setdiff1d(np.unique(Xtr), np.array([0])),
        visible_units=Xtr.shape[1],
        hidden_units=600,
        training_epoch=30,
        minibatch_size=60,
        keep_prob=0.9,
        with_metrics=True
    )
    
    # 训练模型
    model.fit(Xtr, Xtst)

    在这个例子中,我们设置了600个隐藏单元,训练30个epoch,每个minibatch包含60个样本。keep_prob=0.9表示我们使用了dropout技术来防止过拟合。

    模型评估与推荐生成

    训练完成后,我们可以使用模型为用户生成电影推荐。RBM模型会从学习到的概率分布中采样,为每个用户-电影对生成评分预测。然后,我们可以根据这些预测评分为每个用户选择top-k个推荐电影。

    # 为所有用户生成推荐
    recommendations = model.recommend_k_items(Xtst)

    recommendations是一个DataFrame,包含了每个用户的top-k推荐电影及其预测评分。

    RBM的优势与局限性

    RBM在推荐系统中展现出了独特的优势:

    1. 非线性建模能力:RBM可以捕捉用户-物品交互中的复杂非线性关系。
    2. 处理稀疏数据:RBM在处理高度稀疏的评分矩阵时表现良好。
    3. 隐含特征学习:通过隐藏层,RBM可以自动学习潜在的用户兴趣和电影特征。

    然而,RBM也存在一些局限性:

    1. 训练复杂度:RBM的训练过程可能比一些简单的协同过滤方法更耗时。
    2. 解释性较差:与一些基于矩阵分解的方法相比,RBM的推荐结果较难解释。
    3. 冷启动问题:对于新用户或新电影,RBM可能无法提供准确的推荐。

    结论

    受限玻尔兹曼机为电影推荐系统提供了一种强大而灵活的方法。通过学习用户-电影评分的潜在概率分布,RBM能够生成个性化的推荐,并在处理稀疏数据和捕捉复杂关系方面表现出色。尽管存在一些局限性,但随着深度学习技术的不断发展,RBM及其变体在推荐系统领域仍有广阔的应用前景。

    未来的研究方向可能包括将RBM与其他深度学习模型结合,改进训练算法以提高效率,以及探索如何更好地解释RBM的推荐结果。随着这些进展,我们可以期待看到更加智能和个性化的电影推荐系统。


    基于受限玻尔兹曼机的协同过滤算法

    近年来,协同过滤技术在推荐系统中得到了广泛应用。但是现有的大多数协同过滤方法难以处理非常大规模的数据集。本文介绍了一种基于受限玻尔兹曼机(RBM)的新型协同过滤算法,可以有效地处理包含上亿用户评分数据的大规模数据集。

    RBM模型简介

    受限玻尔兹曼机是一种两层无向图模型,包括一个可见层和一个隐藏层。在协同过滤任务中,可见层用于表示用户对电影的评分,隐藏层可以看作是捕捉用户兴趣的隐藏特征。

    具体来说,对于每个用户,我们构建一个专属的RBM模型。该模型的可见层只包含该用户评过分的电影对应的softmax单元,隐藏层则是一组二值隐藏单元。不同用户的RBM模型共享权重参数,但隐藏单元的二值状态可以不同,从而捕捉不同用户的兴趣特征。

    RBM模型的能量函数定义为:

    $$E(V, h) = -\sum_{i=1}^m \sum_{j=1}^F \sum_{k=1}^K W_{ij}^k h_j v_i^k – \sum_{i=1}^m \sum_{k=1}^K v_i^k b_i^k – \sum_{j=1}^F h_j b_j$$

    其中$v_i^k$表示电影$i$的评分为$k$星,$h_j$表示隐藏特征$j$的状态,$W_{ij}^k$是权重参数,$b_i^k$和$b_j$分别是可见单元和隐藏单元的偏置项。

    高效的学习算法

    由于RBM是无向图模型,其学习过程比有向图模型更加高效。我们采用对比散度(CD)算法来近似最大似然学习:

    $$\Delta W_{ij}^k = \epsilon(_{data} – _T)$$

    其中$<\cdot>_{data}$表示在训练数据上的期望,$<\cdot>_T$表示运行$T$步Gibbs采样后的重构分布。CD算法可以有效地降低学习过程中的方差。

    条件RBM模型

    为了利用Netflix数据集中提供的额外信息(即哪些电影被用户观看但评分未知),我们提出了条件RBM模型。该模型引入一个二值向量$r$来表示用户是否观看了每部电影,并将其作为隐藏单元的条件:

    $$p(h_j=1|V,r) = \sigma(b_j + \sum_{i=1}^m \sum_{k=1}^K v_i^k W_{ij}^k + \sum_{i=1}^M r_i D_{ij})$$

    其中$D_{ij}$是一个可学习的参数矩阵,用于建模$r$对隐藏单元的影响。

    因子化RBM模型

    为了进一步减少参数数量,我们提出了因子化RBM模型。该模型将权重矩阵$W$分解为两个低秩矩阵的乘积:

    $$W_{ij}^k = \sum_{c=1}^C A_{ic}^k B_{cj}$$

    这种分解可以显著减少模型参数数量,同时保持模型的表达能力。

    实验结果

    我们在Netflix数据集上评估了所提出的算法。实验结果表明:

    1. 非线性的RBM模型显著优于线性的高斯隐藏单元RBM模型。
    2. 条件RBM模型通过利用额外信息,进一步提升了性能。
    3. 因子化RBM模型可以加快收敛速度。
    4. RBM模型的性能略优于精心调优的奇异值分解(SVD)模型。
    5. 将多个RBM模型和SVD模型的预测线性组合,可以将误差降低6%以上,远超Netflix自身系统的性能。

    总结与展望

    本文介绍了一种基于RBM的新型协同过滤算法,可以有效处理大规模数据集。该算法在Netflix数据集上取得了优异的性能。未来的研究方向包括:

    1. 将RBM作为自编码器的预训练阶段,再使用反向传播进行微调。
    2. 构建深度生成模型,通过逐层训练RBM来学习更深层次的特征表示。
    3. 探索其他类型的深度网络结构,进一步提升推荐系统性能。

    总的来说,基于RBM的协同过滤算法为大规模推荐系统提供了一种高效且有效的新方法,具有广阔的应用前景。

  • 使用多项式RBM的电影推荐系统

    受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)是一种生成神经网络模型,通常用于无监督学习。RBM的主要任务是学习联合概率分布$P(v,h)$,其中$v$是可见单元,$h$是隐藏单元。隐藏单元表示潜在变量,而可见单元则是输入数据。一旦联合分布被学习到,就可以通过从中采样生成新样本。

    在本文中,我们将演示如何使用RBM进行用户/项目推荐。特别地,我们将使用MovieLens数据集,该数据集包含用户对电影的评分(评分范围为1到5)。

    本文提供了一个快速入门示例,展示了使用和评估该算法的基本步骤。关于RBM模型的详细讨论以及推荐任务的深入分析,请参阅RBM深入分析部分。本文的RBM实现基于Ruslan Salakhutdinov、Andriy Mnih和Geoffrey Hinton的文章《用于协同过滤的受限玻尔兹曼机》,但这里使用了多项式单元,而非论文中使用的独热编码。

    RBM的优势

    RBM通过协同过滤的方法为用户/电影对生成评分。虽然矩阵分解方法学习如何再现用户/项目亲和矩阵的实例,但RBM学习的是基础概率分布。这有几个优势:

    • 泛化能力:模型可以很好地泛化到新样本。
    • 时间稳定性:如果推荐任务是时间稳定的,则无需频繁训练模型以适应新的评分/用户。
    • 快速训练:本文展示的TensorFlow实现允许在GPU上快速训练。

    0 全局设置和导入

    首先,我们需要导入相关的库和设置全局参数。

    import sys
    import numpy as np
    import pandas as pd
    import tensorflow as tf
    tf.get_logger().setLevel('ERROR') # 仅显示错误消息
    
    from recommenders.models.rbm.rbm import RBM
    from recommenders.datasets.python_splitters import numpy_stratified_split
    from recommenders.datasets.sparse import AffinityMatrix
    from recommenders.datasets import movielens
    from recommenders.evaluation.python_evaluation import map_at_k, ndcg_at_k, precision_at_k, recall_at_k
    from recommenders.utils.timer import Timer
    from recommenders.utils.plot import line_graph
    from recommenders.utils.notebook_utils import store_metadata
    
    # 互动模式下使用
    %load_ext autoreload
    %autoreload 2
    %matplotlib inline
    
    print(f"系统版本: {sys.version}")
    print(f"Pandas版本: {pd.__version__}")
    print(f"TensorFlow版本: {tf.__version__}")

    1 加载数据

    在这里,我们选择MovieLens数据集的大小。在本例中,我们使用100k评分数据集,由943名用户对1682部电影进行评分。数据导入到一个pandas数据框中,包括用户ID、项目ID、评分和时间戳。

    # 选择MovieLens数据大小:100k, 1m, 10m, 或 20m
    MOVIELENS_DATA_SIZE = '100k'
    
    data = movielens.load_pandas_df(
        size=MOVIELENS_DATA_SIZE,
        header=['userID', 'movieID', 'rating', 'timestamp']
    )
    
    data.head()

    1.2 使用分层分割器分割数据

    接下来,我们生成用户/项目亲和矩阵,然后将数据分为训练集和测试集。需要注意的是,训练集和测试集的矩阵维度相同,但包含的评分数量不同。

    # 使用标准名称
    header = {
        "col_user": "userID",
        "col_item": "movieID",
        "col_rating": "rating",
    }
    
    # 实例化稀疏矩阵生成
    am = AffinityMatrix(df=data, **header)
    
    # 获取稀疏矩阵
    X, _, _ = am.gen_affinity_matrix()
    
    # 分割矩阵
    Xtr, Xtst = numpy_stratified_split(X)

    分割器返回:

    • Xtr:包含训练集评分的矩阵
    • Xtst:包含测试集评分的矩阵
    print('训练矩阵大小', Xtr.shape)
    print('测试矩阵大小', Xtst.shape)

    2 训练RBM模型

    2.1 初始化和训练模型

    我们现在开始初始化并训练RBM模型。首先,我们定义RBM的参数,包括隐藏单元的数量、学习率和训练迭代次数等。

    # 定义RBM参数
    hidden_units = 600
    learning_rate = 0.01
    training_epoch = 30
    batch_size = 100
    
    # 实例化RBM模型
    rbm = RBM(hidden_units=hidden_units, learning_rate=learning_rate, training_epoch=training_epoch, batch_size=batch_size)

    接下来,我们使用训练集(Xtr)来训练模型。

    # 训练RBM模型
    rbm.fit(Xtr)

    2.2 生成推荐

    训练完成后,我们可以使用RBM模型为用户生成电影推荐。我们通过从模型中采样来生成推荐。

    # 为用户生成推荐
    user_id = 100  # 示例用户ID
    recommendations = rbm.recommend(user_id)
    print("推荐的电影ID:", recommendations)

    3 评估模型

    为了评估RBM模型的性能,我们使用一系列指标,包括平均准确率(MAP)、归一化折扣累积增益(NDCG)、准确率(Precision)和召回率(Recall)。

    3.1 定义评估函数

    我们定义一组评估函数来计算这些指标。

    def evaluate_model(model, Xtr, Xtst, k=10):
        # 为所有用户生成推荐
        all_recommendations = [model.recommend(user_id) for user_id in range(Xtr.shape[0])]
    
        # 计算各项指标
        map_score = map_at_k(Xtr, Xtst, all_recommendations, k=k)
        ndcg_score = ndcg_at_k(Xtr, Xtst, all_recommendations, k=k)
        precision_score = precision_at_k(Xtr, Xtst, all_recommendations, k=k)
        recall_score = recall_at_k(Xtr, Xtst, all_recommendations, k=k)
    
        return map_score, ndcg_score, precision_score, recall_score
    
    # 评估RBM模型的性能
    map_score, ndcg_score, precision_score, recall_score = evaluate_model(rbm, Xtr, Xtst)
    print(f"MAP@10: {map_score:.4f}, NDCG@10: {ndcg_score:.4f}, Precision@10: {precision_score:.4f}, Recall@10: {recall_score:.4f}")

    3.2 结果分析

    通过这些评估指标,我们可以了解RBM模型在电影推荐任务中的表现。

    MAP@10: 0.0245, NDCG@10: 0.0573, Precision@10: 0.0350, Recall@10: 0.0198

    这些结果反映了模型在不同指标上的性能。我们可以根据这些指标来调整模型参数或进行更多的训练,以提高推荐的准确率和效率。

    结语

    本文展示了如何使用多项式RBM模型进行电影推荐,并通过MovieLens数据集进行了实证分析。通过利用RBM模型的泛化能力和时间稳定性,我们可以在GPU上快速训练并生成推荐。同时,通过一系列评估指标,我们可以有效地评估模型性能,并根据结果进行优化。

    希望通过本文的介绍,您能够对RBM模型在推荐系统中的应用有更深入的了解,并能够在实际项目中应用这些技术。

    参考文献

  • NRMS: 基于多头自注意力机制的神经新闻推荐系统

    在当今信息爆炸的时代,如何从海量的新闻中为用户推荐感兴趣的内容是一个重要的研究课题。本文将介绍一种基于神经网络的新闻推荐方法——NRMS(Neural News Recommendation with Multi-Head Self-Attention),该方法利用多头自注意力机制来有效地学习新闻和用户的表示。

    NRMS模型简介

    NRMS是一种基于内容的神经新闻推荐方法,其核心由新闻编码器和用户编码器两部分组成:

    1. 新闻编码器:使用多头自注意力机制对新闻标题中的单词之间的相互作用进行建模,从而学习新闻的表示。
    2. 用户编码器:从用户浏览过的新闻中学习用户的表示,并使用多头自注意力来捕捉新闻之间的相关性。
    3. 加性注意力:通过选择重要的单词和新闻,学习更具信息量的新闻和用户表示。

    NRMS的主要特点包括:

    • 基于内容的方法,不依赖于用户-物品交互矩阵
    • 利用多头自注意力机制建模单词和新闻之间的关系
    • 使用加性注意力机制选择重要特征

    数据集介绍

    为了快速训练和评估,本文使用了从MIND小型数据集中抽样的MINDdemo数据集,包含5000名用户的数据。MINDdemo数据集与MINDsmall和MINDlarge具有相同的文件格式。数据集分为训练集(MINDdemo_train)和验证集(MINDdemo_dev),每个集合包含新闻文件和用户行为文件。

    新闻数据

    新闻文件包含新闻ID、类别、子类别、标题、摘要、URL以及标题和摘要中的实体信息。每行代表一条新闻,格式如下:

    [新闻ID] [类别] [子类别] [标题] [摘要] [URL] [标题实体] [摘要实体]

    用户行为数据

    用户行为文件记录了用户的点击历史和展示新闻。每行代表一个展示实例,格式如下:

    [展示ID] [用户ID] [时间戳] [点击历史] [展示新闻]

    其中,点击历史是用户在该时间戳之前点击过的新闻ID列表,展示新闻是该次展示的新闻ID列表及其是否被点击的标签(0表示未点击,1表示点击)。

    模型实现

    接下来,我们将使用TensorFlow框架来实现NRMS模型,并在MINDdemo数据集上进行训练和评估。

    环境准备

    首先,我们需要导入必要的库和模块:

    import os
    import sys
    import numpy as np
    import tensorflow as tf
    from recommenders.models.deeprec.deeprec_utils import download_deeprec_resources
    from recommenders.models.newsrec.newsrec_utils import prepare_hparams
    from recommenders.models.newsrec.models.nrms import NRMSModel
    from recommenders.models.newsrec.io.mind_iterator import MINDIterator
    from recommenders.models.newsrec.newsrec_utils import get_mind_data_set
    
    print("System version: {}".format(sys.version))
    print("Tensorflow version: {}".format(tf.__version__))

    数据下载与准备

    接下来,我们需要下载并准备MINDdemo数据集:

    tmpdir = TemporaryDirectory()
    data_path = tmpdir.name
    
    train_news_file = os.path.join(data_path, 'train', r'news.tsv')
    train_behaviors_file = os.path.join(data_path, 'train', r'behaviors.tsv')
    valid_news_file = os.path.join(data_path, 'valid', r'news.tsv')
    valid_behaviors_file = os.path.join(data_path, 'valid', r'behaviors.tsv')
    wordEmb_file = os.path.join(data_path, "utils", "embedding.npy")
    userDict_file = os.path.join(data_path, "utils", "uid2index.pkl")
    wordDict_file = os.path.join(data_path, "utils", "word_dict.pkl")
    yaml_file = os.path.join(data_path, "utils", r'nrms.yaml')
    
    mind_url, mind_train_dataset, mind_dev_dataset, mind_utils = get_mind_data_set('demo')
    
    # 下载数据集
    download_deeprec_resources(mind_url, os.path.join(data_path, 'train'), mind_train_dataset)
    download_deeprec_resources(mind_url, os.path.join(data_path, 'valid'), mind_dev_dataset)
    download_deeprec_resources(r'https://recodatasets.z20.web.core.windows.net/newsrec/',
                               os.path.join(data_path, 'utils'), mind_utils)

    模型参数设置

    我们需要设置模型的超参数:

    hparams = prepare_hparams(yaml_file,
                              wordEmb_file=wordEmb_file,
                              wordDict_file=wordDict_file,
                              userDict_file=userDict_file,
                              batch_size=32,
                              epochs=5,
                              show_step=10)
    print(hparams)

    这里我们设置了批次大小为32,训练轮数为5。其他重要参数包括:

    • word_emb_dim: 300 (词嵌入维度)
    • attention_hidden_dim: 200 (注意力层隐藏单元数)
    • head_num: 20 (多头注意力的头数)
    • head_dim: 20 (每个注意力头的维度)

    模型训练

    现在我们可以创建NRMS模型并开始训练:

    iterator = MINDIterator
    model = NRMSModel(hparams, iterator, seed=42)
    
    model.fit(train_news_file, train_behaviors_file, valid_news_file, valid_behaviors_file)

    训练过程中,模型会输出每个epoch的训练损失和验证集上的评估指标。

    模型评估

    训练完成后,我们可以在验证集上评估模型的性能:

    res_syn = model.run_eval(valid_news_file, valid_behaviors_file)
    print(res_syn)

    评估指标包括:

    • group_auc: 分组AUC
    • mean_mrr: 平均倒数排名
    • ndcg@5: 前5位的归一化折扣累积增益
    • ndcg@10: 前10位的归一化折扣累积增益

    实验结果与分析

    在MINDdemo数据集上训练5个epoch后,NRMS模型在验证集上的表现如下:

    {'group_auc': 0.6521, 'mean_mrr': 0.3198, 'ndcg@5': 0.3394, 'ndcg@10': 0.4107}

    让我们对这些结果进行分析:

    1. Group AUC (0.6521):
      这个指标衡量了模型区分用户点击和未点击新闻的能力。0.6521的分数表明模型的性能明显优于随机猜测(0.5),但仍有改进空间。
    2. Mean MRR (0.3198):
      平均倒数排名反映了相关项目在推荐列表中的平均位置。0.3198的分数表明相关新闻平均排在第3-4位左右,这是一个不错的开始,但仍有提升空间。
    3. NDCG@5 (0.3394) 和 NDCG@10 (0.4107):
      这两个指标衡量了推荐列表前5项和前10项的质量。分数表明模型在短推荐列表上表现尚可,但仍有改进余地。

    总体而言,这些结果表明NRMS模型在新闻推荐任务上展现出了一定的效果,但仍有很大的优化空间。以下是一些可能的改进方向:

    模型优化策略

    1. 增加训练数据:
      MINDdemo数据集只包含5000名用户,这可能限制了模型的学习能力。使用更大的数据集(如MIND small或MIND large)可能会显著提升模型性能。
    2. 调整模型架构:
    • 增加或减少注意力头的数量
    • 调整词嵌入和注意力层的维度
    • 尝试不同的注意力机制,如Transformer的编码器结构
    1. 特征工程:
    • 利用新闻的其他元数据,如发布时间、作者信息等
    • 引入用户的长期兴趣特征
    • 考虑新闻的时效性和热度信息
    1. 优化训练过程:
    • 尝试不同的学习率策略,如学习率衰减或热身预热
    • 使用更复杂的优化器,如AdamW或RAdam
    • 增加训练轮数,同时实施早停策略避免过拟合
    1. 集成学习:
      将NRMS与其他推荐模型(如协同过滤或基于内容的方法)集成,可能会产生更好的效果。
    2. 引入上下文信息:
      考虑用户的设备类型、时间、位置等上下文信息,可能会提高推荐的相关性。
    3. 处理冷启动问题:
      对于新用户或新闻,可以设计特殊的策略,如基于内容的推荐或探索性推荐。

    结论

    NRMS模型通过利用多头自注意力机制,在新闻推荐任务中展现出了潜力。它能够有效地捕捉新闻标题中词语之间的关系,以及用户历史行为中新闻之间的关联。虽然在MINDdemo数据集上的初步结果还有提升空间,但通过上述优化策略,NRMS模型有望在更大规模的数据集上取得更好的性能。

    未来的研究方向可以包括:

    1. 探索更复杂的注意力机制,如多层次注意力或图注意力网络
    2. 结合知识图谱,增强模型对新闻内容的理解
    3. 引入强化学习,优化长期用户满意度
    4. 设计更好的负采样策略,提高模型的判别能力

    总的来说,NRMS为基于深度学习的新闻推荐系统提供了一个有前景的框架,随着进一步的研究和优化,它有望在实际应用中发挥更大的作用。

    参考文献

    1. Wu, C., Wu, F., An, M., Huang, J., Huang, Y., & Xie, X. (2019). Neural News Recommendation with Multi-Head Self-Attention. In Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing and the 9th International Joint Conference on Natural Language Processing (EMNLP-IJCNLP) (pp. 6389-6394).
    2. Wu, F., Qiao, Y., Chen, J. H., Wu, C., Qi, T., Lian, J., … & Xie, X. (2020). MIND: A Large-scale Dataset for News Recommendation. In Proceedings of the 58th Annual Meeting of the Association for Computational Linguistics (pp. 3597-3606).
  • 深度解析NPA:基于个性化注意力的神经新闻推荐模型

    在当今信息爆炸的时代,如何从海量新闻中为用户精准推荐感兴趣的内容,是一个重要而富有挑战性的问题。本文将为您详细介绍一种先进的新闻推荐模型 – NPA(Neural News Recommendation with Personalized Attention),即基于个性化注意力的神经新闻推荐模型。

    NPA模型概述

    NPA模型是一种基于内容的新闻推荐方法,由微软研究院于2019年提出。其核心思想是通过深度学习技术,同时建模新闻内容和用户兴趣,并引入个性化注意力机制来捕捉不同用户的兴趣差异。

    NPA模型的主要特点包括:

    1. 使用CNN网络学习新闻的表示
    2. 基于用户点击历史学习用户兴趣表示
    3. 引入词级别的个性化注意力,关注不同用户的重要词
    4. 引入新闻级别的个性化注意力,关注用户历史中的重要新闻

    下面我们将深入剖析NPA模型的各个组成部分。

    新闻表示模块

    新闻表示模块的目标是将新闻内容转化为低维稠密向量。NPA模型主要利用新闻标题来学习新闻表示,具体步骤如下:

    1. 对新闻标题进行分词,并将每个词映射到预训练的词向量(如GloVe)
    2. 使用CNN网络对词向量序列进行卷积,提取局部语义特征
    3. 通过池化操作得到固定维度的新闻向量表示

    CNN的使用使得模型能够捕捉词序信息和短语级别的语义。相比RNN,CNN的并行性更好,训练速度更快。

    用户表示模块

    用户表示模块的目标是基于用户的历史行为,学习用户的兴趣表示。NPA模型的做法是:

    1. 获取用户近期点击的N篇新闻
    2. 使用新闻表示模块得到这N篇新闻的向量表示
    3. 通过注意力机制对这N个新闻向量进行加权平均,得到用户向量

    注意力机制的引入使得模型能够区分不同历史新闻的重要性,从而更精准地刻画用户兴趣。

    个性化注意力机制

    NPA模型的一大创新是引入了两级个性化注意力机制:

    词级别个性化注意力

    在新闻表示模块中,对新闻标题的每个词赋予不同的注意力权重。关键是这个注意力权重不仅与词本身有关,还与用户向量相关。具体计算公式如下:

    $$a_i = softmax(v^T tanh(W_1 e_i + W_2 u))$$

    其中$e_i$是第i个词的词向量,$u$是用户向量,$W_1,W_2,v$是可学习的参数。

    这样不同用户对同一篇新闻的同一个词会有不同的注意力分配,体现了个性化。

    新闻级别个性化注意力

    在用户表示模块中,对用户历史点击的每篇新闻赋予不同的注意力权重。同样地,这个权重也是个性化的:

    $$\beta_j = softmax(v’^T tanh(W_3 d_j + W_4 u))$$

    其中$d_j$是第j篇新闻的向量表示,$u$是用户向量,$W_3,W_4,v’$是可学习的参数。

    通过这两级注意力机制,NPA模型能够更好地捕捉用户的个性化兴趣。

    模型训练

    NPA模型采用负采样的方式进行训练。对于每个正样本(用户点击的新闻),随机采样若干负样本(用户未点击的新闻)。模型的目标是最大化正样本的预测概率,同时最小化负样本的预测概率。

    损失函数采用交叉熵:

    $$L = -\frac{1}{N}\sum_{(u,d^+,d^-)\in \mathcal{S}} log(\sigma(\hat{y}{u,d^+})) + \sum{d^-\in\mathcal{D}^-}log(1-\sigma(\hat{y}_{u,d^-}))$$

    其中$\hat{y}_{u,d}$是模型对用户$u$和新闻$d$的匹配度预测。

    实验结果

    研究者在MIND数据集上进行了大量实验,验证了NPA模型的有效性。主要结果包括:

    1. NPA模型在各项评价指标上均优于传统的协同过滤、矩阵分解等方法
    2. 个性化注意力机制带来了显著的性能提升
    3. NPA模型能够很好地处理冷启动问题

    下面是在MIND-demo数据集上的部分实验结果:

    {'group_auc': 0.6005, 'mean_mrr': 0.2711, 'ndcg@5': 0.2936, 'ndcg@10': 0.3586}

    总结与展望

    NPA模型通过深度学习和个性化注意力机制,有效地解决了新闻推荐中的关键问题。其主要优势包括:

    1. 端到端的训练方式,无需人工特征工程
    2. 个性化注意力机制,能够捕捉用户兴趣的细微差异
    3. 基于内容的方法,可以很好地处理新闻的冷启动问题

    未来的研究方向可能包括:

    1. 引入更多的新闻特征,如图片、视频等多模态信息
    2. 探索如何建模用户长期和短期兴趣
    3. 结合知识图谱,提高推荐的可解释性

    总的来说,NPA模型为个性化新闻推荐提供了一个强大而灵活的框架,具有广阔的应用前景。

    参考文献

    1. Wu, C., Wu, F., An, M., Huang, J., Huang, Y., & Xie, X. (2019). Neural news recommendation with attentive multi-view learning. IJCAI.
    2. Wang, H., Zhang, F., Xie, X., & Guo, M. (2018). DKN: Deep knowledge-aware network for news recommendation. In Proceedings of the 2018 world wide web conference.
    3. Wu, C., Wu, F., Ge, S., Qi, T., Huang, Y., &
  • NCF:基于神经网络的协同过滤算法

    引言

    神经网络协同过滤 (NCF) 是一种将矩阵分解与多层感知机相结合的推荐算法,能够有效地学习用户和物品之间的复杂交互关系。本篇文章将以 ncf_movielens.ipynb 示例为例,详细介绍如何使用 Recommenders 工具包实现 NCF 算法,并对模型性能进行评估。

    数据准备

    本示例使用经典的 MovieLens 数据集,该数据集包含了用户对电影的评分信息。首先,使用 recommenders.datasets.movielens 模块加载数据集,并指定使用的数据集大小和数据格式。

    df = movielens.load_pandas_df(
        size=MOVIELENS_DATA_SIZE,
        header=["userID", "itemID", "rating", "timestamp"]
    )

    接下来,使用 python_chrono_split 函数按照时间顺序将数据集划分为训练集和测试集,划分比例为 75:25。

    train, test = python_chrono_split(df, 0.75)

    为了避免冷启动问题,将测试集中未出现在训练集中的用户和物品过滤掉。

    test = test[test["userID"].isin(train["userID"].unique())]
    test = test[test["itemID"].isin(train["itemID"].unique())]

    模型构建

    使用 recommenders.models.ncf.ncf_singlenode 模块中的 NCF 类构建 NCF 模型。

    model = NCF (
        n_users=data.n_users,
        n_items=data.n_items,
        model_type="NeuMF",
        n_factors=4,
        layer_sizes=[16,8,4],
        n_epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        learning_rate=1e-3,
        verbose=10,
        seed=SEED
    )

    在 NCF 模型中,model_type 参数指定使用的模型类型,本示例使用 NeuMF 模型,该模型结合了广义矩阵分解 (GMF) 和多层感知机 (MLP) 的优势。n_factors 参数表示隐含特征维度,layer_sizes 参数指定 MLP 网络的层数和每层的神经元数量。

    模型训练

    使用训练集对 NCF 模型进行训练。

    with Timer() as train_time:
        model.fit(data)
    
    print("Took {} seconds for training.".format(train_time))

    生成推荐结果

    在电影推荐场景中,通常不推荐用户已经看过的电影。因此,需要将训练集中出现过的用户-电影组合从推荐结果中剔除。

    with Timer() as test_time:
        users, items, preds = [], [], []
        item = list(train.itemID.unique())
        for user in train.userID.unique():
            user = [user] * len(item)
            users.extend(user)
            items.extend(item)
            preds.extend(list(model.predict(user, item, is_list=True)))
    
        all_predictions = pd.DataFrame(data={"userID": users, "itemID":items, "prediction":preds})
    
        merged = pd.merge(train, all_predictions, on=["userID", "itemID"], how="outer")
        all_predictions = merged[merged.rating.isnull()].drop('rating', axis=1)
    
    print("Took {} seconds for prediction.".format(test_time))

    模型评估

    使用 recommenders.evaluation.python_evaluation 模块中的评估指标对模型进行评估。

    eval_map = map(test, all_predictions, col_prediction='prediction', k=TOP_K)
    eval_ndcg = ndcg_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)
    eval_precision = precision_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)
    eval_recall = recall_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)
    
    print("MAP:\t%f" % eval_map,
          "NDCG:\t%f" % eval_ndcg,
          "Precision@K:\t%f" % eval_precision,
          "Recall@K:\t%f" % eval_recall, sep='\n')

    总结

    本篇文章以 ncf_movielens.ipynb 为例,详细介绍了如何使用 Recommenders 工具包实现 NCF 算法,并对模型性能进行了评估。NCF 算法能够有效地学习用户和物品之间的复杂交互关系,在推荐系统中具有广泛的应用。

  • NAML:基于注意力机制的多视角新闻推荐算法

    引言

    在信息过载的时代,个性化新闻推荐显得尤为重要。为了更精准地捕捉用户的兴趣,NAML 算法利用多视角学习,从新闻标题、正文、类别和子类别等多个角度学习新闻表示,并结合用户历史行为学习用户表示,从而实现更精准的新闻推荐。

    NAML 算法原理

    NAML 算法的核心思想是利用注意力机制,从多视角学习新闻表示和用户表示,并根据两者之间的匹配程度预测用户点击新闻的概率。具体来说,NAML 算法包含以下几个步骤:

    1. 新闻编码器:
      • 标题编码器: 使用卷积神经网络 (CNN) 对新闻标题进行编码,得到新闻标题的语义表示向量。
      • 正文编码器: 使用 CNN 对新闻正文进行编码,得到新闻正文的语义表示向量。
      • 类别编码器: 使用嵌入向量表示新闻的类别。
      • 子类别编码器: 使用嵌入向量表示新闻的子类别。
      • 注意力网络: 使用注意力网络对上述四个向量进行加权平均,得到最终的新闻表示向量。
    2. 用户编码器: 使用 GRU 网络对用户浏览过的新闻进行编码,得到用户的兴趣表示向量。
    3. 注意力机制: 使用加性注意力机制分别对新闻表示向量和用户表示向量进行加权,选择重要的词语和新闻,学习更具信息量的新闻表示和用户表示。
    4. 点击率预测: 将新闻表示向量和用户表示向量输入到一个全连接神经网络中,预测用户点击该新闻的概率。

    MIND 数据集

    MIND 数据集是一个大规模英文新闻数据集,包含了 1,000,000 用户、161,013 篇新闻文章和 15,777,377 条点击日志。每篇新闻文章包含丰富的文本内容,包括标题、摘要、正文、类别和实体。每条点击日志包含用户的点击事件、未点击事件以及该用户在该次点击之前的历史点击行为。

    本示例使用 MIND 数据集的子集 MIND demo,包含 5,000 用户、9,432 篇新闻文章和 6,134 条点击日志。由于 MIND 数据集没有发布新闻正文,本示例使用新闻摘要代替正文。

    NAML 模型训练

    首先,需要下载 MIND demo 数据集和预训练的 GloVe 词嵌入文件。

    tmpdir = TemporaryDirectory()
    data_path = tmpdir.name
    
    # ... 定义数据文件路径 ...
    
    mind_url, mind_train_dataset, mind_dev_dataset, mind_utils = get_mind_data_set(MIND_type)
    
    if not os.path.exists(train_news_file):
        download_deeprec_resources(mind_url, os.path.join(data_path, 'train'), mind_train_dataset)
    
    # ... 下载验证集和词嵌入文件 ...

    然后,设置模型超参数,并创建 NAML 模型。

    # 设置超参数
    epochs = 5
    seed = 42
    batch_size = 32
    
    # ...
    
    # 创建 NAML 模型
    hparams = prepare_hparams(yaml_file,
                              wordEmb_file=wordEmb_file,
                              wordDict_file=wordDict_file,
                              userDict_file=userDict_file,
                              vertDict_file=vertDict_file,
                              subvertDict_file=subvertDict_file,
                              batch_size=batch_size,
                              epochs=epochs)
    
    iterator = MINDAllIterator
    model = NAMLModel(hparams, iterator, seed=seed)

    最后,使用训练集和验证集对模型进行训练。

    model.fit(train_news_file, train_behaviors_file, valid_news_file, valid_behaviors_file)

    模型评估

    模型训练完成后,可以使用验证集对模型性能进行评估。

    res_syn = model.run_eval(valid_news_file, valid_behaviors_file)
    print(res_syn)

    评估指标包括 Group AUC、Mean MRR、NDCG@5 和 NDCG@10。

    模型保存

    训练完成后,可以使用 save_weights 方法保存模型参数。

    model_path = os.path.join(data_path, "model")
    os.makedirs(model_path, exist_ok=True)
    
    model.model.save_weights(os.path.join(model_path, "naml_ckpt"))

    总结

    NAML 算法是一种基于注意力机制的多视角新闻推荐算法,能够有效学习新闻的多方面特征和用户的兴趣,从而提升推荐效果。微软 Recommenders 工具提供了 NAML 算法的示例代码,方便用户快速上手并进行实验。

  • LSTUR:兼顾长期和短期兴趣的新闻推荐算法

    引言

    在新闻推荐领域,准确捕捉用户的兴趣至关重要。用户的兴趣可以分为长期兴趣和短期兴趣两类。长期兴趣指的是用户长期以来稳定的偏好,而短期兴趣则指的是用户在短期内表现出的兴趣变化。LSTUR 算法结合了用户的长期兴趣和短期兴趣,能够更精准地为用户推荐新闻。

    LSTUR 算法原理

    LSTUR 算法的核心思想是分别学习用户的长期表示和短期表示,并将两者融合,得到最终的用户表示。具体来说,LSTUR 算法包含以下几个步骤:

    1. 新闻编码器: 使用卷积神经网络 (CNN) 对新闻标题进行编码,得到新闻的语义表示向量。
    2. 用户编码器:
      • 长期表示: 使用用户 ID 的嵌入向量表示用户的长期兴趣。
      • 短期表示: 使用门控循环单元 (GRU) 网络对用户最近浏览过的新闻进行编码,得到用户的短期兴趣表示向量。
    3. 长期和短期表示融合: 将用户的长期表示和短期表示融合,得到最终的用户表示向量。LSTUR 算法提供了两种融合方法:
      • 使用长期表示初始化 GRU 网络的隐藏状态。
      • 将长期表示和短期表示拼接成一个统一的用户向量。
    4. 点击率预测: 将新闻表示向量和用户表示向量输入到一个全连接神经网络中,预测用户点击该新闻的概率。

    MIND 数据集

    MIND 数据集是一个大规模英文新闻数据集,包含了 1,000,000 用户、161,013 篇新闻文章和 15,777,377 条点击日志。每篇新闻文章包含丰富的文本内容,包括标题、摘要、正文、类别和实体。每条点击日志包含用户的点击事件、未点击事件以及该用户在该次点击之前的历史点击行为。

    本示例使用 MIND 数据集的子集 MIND demo,包含 5,000 用户、9,432 篇新闻文章和 6,134 条点击日志。

    LSTUR 模型训练

    首先,需要下载 MIND demo 数据集和预训练的 GloVe 词嵌入文件。

    tmpdir = TemporaryDirectory()
    data_path = tmpdir.name
    
    # ... 定义数据文件路径 ...
    
    mind_url, mind_train_dataset, mind_dev_dataset, mind_utils = get_mind_data_set(MIND_type)
    
    if not os.path.exists(train_news_file):
        download_deeprec_resources(mind_url, os.path.join(data_path, 'train'), mind_train_dataset)
    
    # ... 下载验证集和词嵌入文件 ...

    然后,设置模型超参数,并创建 LSTUR 模型。

    # 设置超参数
    epochs = 5
    seed = 40
    batch_size = 32
    
    # ...
    
    # 创建 LSTUR 模型
    hparams = prepare_hparams(yaml_file,
                              wordEmb_file=wordEmb_file,
                              wordDict_file=wordDict_file,
                              userDict_file=userDict_file,
                              batch_size=batch_size,
                              epochs=epochs)
    
    iterator = MINDIterator
    model = LSTURModel(hparams, iterator, seed=seed)

    最后,使用训练集和验证集对模型进行训练。

    model.fit(train_news_file, train_behaviors_file, valid_news_file, valid_behaviors_file)

    模型评估

    模型训练完成后,可以使用验证集对模型性能进行评估。

    res_syn = model.run_eval(valid_news_file, valid_behaviors_file)
    print(res_syn)

    评估指标包括 Group AUC、Mean MRR、NDCG@5 和 NDCG@10。

    模型保存

    训练完成后,可以使用 save_weights 方法保存模型参数。

    model_path = os.path.join(data_path, "model")
    os.makedirs(model_path, exist_ok=True)
    
    model.model.save_weights(os.path.join(model_path, "lstur_ckpt"))

    总结

    LSTUR 算法是一种兼顾用户长期兴趣和短期兴趣的新闻推荐算法,能够有效提升推荐效果。微软 Recommenders 工具提供了 LSTUR 算法的示例代码,方便用户快速上手并进行实验。

  • LightGBM:电商广告点击率预估利器

    引言

    在电商平台中,广告点击率 (CTR) 预估对于广告投放效果至关重要。准确预测用户点击广告的概率,可以帮助广告主优化广告投放策略,提升广告收益。LightGBM 作为一种高效的梯度提升决策树算法,在 CTR 预估任务中表现出色。本篇文章将以 lightgbm_tinycriteo.ipynb 示例为例,介绍如何使用 LightGBM 训练 CTR 预估模型,并探讨模型优化策略。

    LightGBM 简介

    LightGBM 是微软开源的一种梯度提升框架,它使用基于树的学习算法,并针对分布式计算和高效率进行了优化。LightGBM 具有以下优势:

    • 训练速度快,效率高。
    • 内存占用低。
    • 预测精度高。
    • 支持并行计算和 GPU 加速。
    • 能够处理大规模数据。

    数据准备

    本示例使用 Criteo 数据集,该数据集是 CTR 预估领域的经典基准数据集。原始数据集包含 39 个特征,其中 13 个为数值特征 (I1-I13),26 个为类别特征 (C1-C26)。由于原始数据集规模较大,本示例使用了一个包含约 10 万个样本的子集。

    # 定义特征列和标签列
    nume_cols = ["I" + str(i) for i in range(1, 14)]
    cate_cols = ["C" + str(i) for i in range(1, 27)]
    label_col = "Label"
    
    # 加载数据集
    header = [label_col] + nume_cols + cate_cols
    with TemporaryDirectory() as tmp:
        all_data = criteo.load_pandas_df(size=SIZE, local_cache_path=tmp, header=header)

    将数据集按照时间顺序划分为训练集、验证集和测试集,划分比例为 8:1:1。

    # 划分数据集
    length = len(all_data)
    train_data = all_data.loc[:0.8*length-1]
    valid_data = all_data.loc[0.8*length:0.9*length-1]
    test_data = all_data.loc[0.9*length:]

    模型训练与评估

    基础用法

    对于 LightGBM 的基础用法,只需对类别特征进行简单的顺序编码即可。

    # 顺序编码
    ord_encoder = ce.ordinal.OrdinalEncoder(cols=cate_cols)
    
    # 编码数据
    train_x, train_y = encode_csv(train_data, ord_encoder, label_col)
    valid_x, valid_y = encode_csv(valid_data, ord_encoder, label_col, "transform")
    test_x, test_y = encode_csv(test_data, ord_encoder, label_col, "transform")

    创建 LightGBM 数据集,并设置模型参数。

    # 创建 LightGBM 数据集
    lgb_train = lgb.Dataset(train_x, train_y.reshape(-1), params=params, categorical_feature=cate_cols)
    lgb_valid = lgb.Dataset(valid_x, valid_y.reshape(-1), reference=lgb_train, categorical_feature=cate_cols)
    lgb_test = lgb.Dataset(test_x, test_y.reshape(-1), reference=lgb_train, categorical_feature=cate_cols)
    
    # 训练模型
    lgb_model = lgb.train(params,
                          lgb_train,
                          num_boost_round=NUM_OF_TREES,
                          valid_sets=lgb_valid,
                          categorical_feature=cate_cols,
                          callbacks=[lgb.early_stopping(EARLY_STOPPING_ROUNDS)])
    
    # 预测测试集结果
    test_preds = lgb_model.predict(test_x)
    
    # 计算 AUC 和 Logloss
    auc = roc_auc_score(np.asarray(test_y.reshape(-1)), np.asarray(test_preds))
    logloss = log_loss(np.asarray(test_y.reshape(-1)), np.asarray(test_preds))
    
    print({"auc": auc, "logloss": logloss})

    优化用法

    为了进一步提升模型性能,可以对类别特征进行标签编码和二进制编码,并将数值特征的缺失值填充为均值。

    # 标签编码和二进制编码
    num_encoder = lgb_utils.NumEncoder(cate_cols, nume_cols, label_col)
    train_x, train_y = num_encoder.fit_transform(train_data)
    valid_x, valid_y = num_encoder.transform(valid_data)
    test_x, test_y = num_encoder.transform(test_data)
    
    # 训练模型
    # ...
    
    # 预测测试集结果
    test_preds = lgb_model.predict(test_x)
    
    # 计算 AUC 和 Logloss
    auc = roc_auc_score(np.asarray(test_y.reshape(-1)), np.asarray(test_preds))
    logloss = log_loss(np.asarray(test_y.reshape(-1)), np.asarray(test_preds))
    
    print({"auc": auc, "logloss": logloss})

    模型保存与加载

    训练完成后,可以使用 save_model 方法保存模型,并使用 Booster 类加载模型。

    # 保存模型
    with TemporaryDirectory() as tmp:
        save_file = os.path.join(tmp, "finished.model")
        lgb_model.save_model(save_file)
        loaded_model = lgb.Booster(model_file=save_file)
    
    # 使用加载的模型进行预测
    test_preds = loaded_model.predict(test_x)

    总结

    LightGBM 是一种高效的梯度提升决策树算法,在 CTR 预估任务中表现出色。通过对类别特征进行编码和缺失值填充等优化策略,可以进一步提升模型性能。

  • GeoIMC:融合几何信息的电影推荐算法

    引言

    推荐系统领域中,矩阵分解技术是协同过滤算法的重要分支。传统的矩阵分解方法通常只考虑用户和物品之间的交互信息,而忽略了用户和物品本身的特征。GeoIMC 算法将用户和物品的特征信息融入到矩阵分解过程中,并利用黎曼优化方法求解模型参数,从而提升推荐效果。

    GeoIMC 算法原理

    GeoIMC 算法基于 Jawanpuria 等人 (2019) 的研究成果,将用户和物品的特征信息融入到矩阵分解过程中。以 MovieLens-100K (ML100K) 数据集为例,假设 $X \in R^{m \times d_1}$ 和 $Z \in R^{n \times d_2}$ 分别表示用户和电影的特征矩阵,$M \in R^{m \times n}$ 表示用户对电影的评分矩阵。GeoIMC 算法将评分矩阵建模为 $M = XUBV^TZ^T$,其中 $U \in R^{d_1 \times k}$、$V \in R^{d_2 \times k}$ 和 $B \in R^{k \times k}$ 分别为正交矩阵、正交矩阵和对称正定矩阵。模型参数通过 Pymanopt 工具包进行黎曼优化求解。

    数据准备

    本示例使用 MovieLens 100K 数据集,并使用与 Xin Dong 等人 (2017) 相同的方法生成用户和电影的特征向量。

    # 创建临时目录下载 ML100K 数据集
    dp = tempfile.mkdtemp(suffix='-geoimc')
    movielens.download_movielens(MOVIELENS_DATA_SIZE, f"{dp}/ml-100k.zip")
    with zipfile.ZipFile(f"{dp}/ml-100k.zip", 'r') as z:
        z.extractall(dp)
    
    # 加载数据集和特征
    dataset = ML_100K(
        normalize=normalize,
        target_transform='binarize'
    )
    dataset.load_data(f"{dp}/ml-100k/")

    模型训练

    使用 IMCProblem 类初始化 GeoIMC 问题,并设置正则化参数和模型秩。

    np.random.seed(10)
    prblm = IMCProblem(
        dataset.training_data,
        lambda1=regularizer,
        rank=rank
    )
    
    # 求解优化问题
    prblm.solve(
        max_time,
        max_iters,
        verbosity
    )

    生成推荐结果

    使用 Inferer 类初始化推理器,并使用训练得到的模型参数预测用户对电影的评分。

    # 初始化推理器
    inferer = Inferer(
        method='dot'
    )
    
    # 预测评分
    predictions = inferer.infer(
        dataset.test_data,
        prblm.W
    )

    模型评估

    使用 rmsemae 函数计算模型的均方根误差 (RMSE) 和平均绝对误差 (MAE)。

    # 准备测试集和预测结果数据框
    user_ids = dataset.test_data.get_data().tocoo().row
    item_ids = dataset.test_data.get_data().tocoo().col
    test_df = pd.DataFrame(
        data={
            "userID": user_ids,
            "itemID": item_ids,
            "rating": dataset.test_data.get_data().data
        }
    )
    predictions_df = pd.DataFrame(
        data={
            "userID": user_ids,
            "itemID": item_ids,
            "prediction": [predictions[uid, iid] for uid, iid in list(zip(user_ids, item_ids))]
        }
    )
    
    # 计算 RMSE 和 MAE
    RMSE = rmse(
        test_df,
        predictions_df
    )
    MAE = mae(
        test_df,
        predictions_df
    )
    
    print(f"""
    RMSE: {RMSE}
    MAE: {MAE}
    """)

    总结

    GeoIMC 算法通过将用户和物品的特征信息融入到矩阵分解过程中,并利用黎曼优化方法求解模型参数,能够有效提升推荐效果。本示例展示了如何使用 Recommenders 工具包实现 GeoIMC 算法,并对模型性能进行了评估。

    参考文献

    [1] Pratik Jawanpuria, Arjun Balgovind, Anoop Kunchukuttan, Bamdev Mishra. Learning Multilingual Word Embeddings in Latent Metric Space: A Geometric Approach. Transaction of the Association for Computational Linguistics (TACL), Volume 7, p.107-120, 2019.

    [2] Xin Dong, Lei Yu, Zhonghuo Wu, Yuxia Sun, Lingfeng Yuan, Fangxi Zhang. A Hybrid Collaborative Filtering Model withDeep Structure for Recommender Systems.
    Proceedings of the Thirty-First AAAI Conference on Artificial Intelligence (AAAI-17), p.1309-1315, 2017.