SAR算法在MovieLens数据集上的应用

推荐系统是现代互联网应用中不可或缺的一部分。无论是电子商务、社交媒体还是内容平台,都在使用各种推荐算法来为用户提供个性化的体验。今天,我们将深入探讨一种简单而有效的推荐算法——简单算法推荐(Simple Algorithm for Recommendation, SAR),并通过在著名的MovieLens数据集上的实践来展示其应用。

SAR算法简介

SAR是一种基于用户交互历史的快速、可扩展的个性化推荐算法。它的主要特点包括:

  1. 生成易于解释和理解的推荐结果
  2. 能够处理”冷启动物品”和”半冷启动用户”的场景
  3. 属于基于邻域的算法,旨在为每个用户推荐最合适的物品

SAR的核心思想是推荐与用户已有偏好相似的物品。这里的”相似”指的是:如果用户与物品A交互,那么他们也很可能与物品B交互;而”偏好”则指用户在过去与某个物品有过交互。

SAR的优势

  1. 高准确度:虽然算法简单,但能达到很好的推荐效果
  2. 训练速度快:只需要进行简单的计数就可以构建预测时使用的矩阵
  3. 预测速度快:预测过程仅涉及相似度矩阵与偏好向量的乘法运算

SAR的使用注意事项

  1. 由于不使用物品或用户特征,在某些场景下可能不如使用这些特征的算法
  2. 内存消耗大:需要创建一个m×m的稀疏方阵(m为物品数量)
  3. SAR更适合隐式评分场景,不适合预测具体评分值

数据准备

我们使用MovieLens数据集来演示SAR算法的应用。MovieLens是一个包含用户对电影评分的数据集,非常适合用来测试推荐算法。

首先,我们加载所需的库和数据:

import sys
import logging
import numpy as np
import pandas as pd
from recommenders.datasets import movielens
from recommenders.models.sar import SAR
from recommenders.datasets.python_splitters import python_stratified_split

# 加载MovieLens 100k数据集
data = movielens.load_pandas_df(size="100k")
data["rating"] = data["rating"].astype(np.float32)

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

train, test = python_stratified_split(data, ratio=0.75, col_user="userID", col_item="itemID", seed=42)

这里我们使用了分层抽样的方法,保证每个用户的75%评分进入训练集,25%进入测试集。

模型训练与预测

现在,我们可以开始训练SAR模型了:

model = SAR(
    col_user="userID",
    col_item="itemID",
    col_rating="rating",
    col_timestamp="timestamp",
    similarity_type="jaccard", 
    time_decay_coefficient=30, 
    timedecay_formula=True,
    normalize=True
)

model.fit(train)

在这个过程中,SAR会计算物品之间的共现矩阵,然后基于Jaccard相似度计算物品相似度矩阵。同时,它还会计算用户-物品亲和度矩阵,捕捉用户与物品之间关系的强度。

训练完成后,我们可以为测试集中的用户生成Top-K推荐:

TOP_K = 10
top_k = model.recommend_k_items(test, top_k=TOP_K, remove_seen=True)

模型评估

为了评估SAR的性能,我们使用了几个常见的排序指标:

  1. 平均精度均值(MAP)
  2. 归一化折损累积增益(NDCG)
  3. 准确率(Precision)
  4. 召回率(Recall)

同时,我们还计算了一些评分指标:

  1. 均方根误差(RMSE)
  2. 平均绝对误差(MAE)
  3. R方(R-squared)
  4. 可解释方差(Explained Variance)
eval_map = map(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_ndcg = ndcg_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)
eval_precision = precision_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_recall = recall_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)

eval_rmse = rmse(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_mae = mae(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_rsquared = rsquared(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_exp_var = exp_var(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")

这些指标能够全面地评估SAR算法在MovieLens数据集上的表现。

结论

通过在MovieLens数据集上的实验,我们展示了SAR算法的实际应用。SAR作为一种简单而有效的推荐算法,在许多场景下都能取得不错的效果。它的快速训练和预测特性使其特别适合需要实时推荐的应用场景。

然而,SAR也有其局限性。例如,它不能利用物品或用户的特征信息,这在某些场景下可能会限制其性能。此外,对于大规模数据集,其内存消耗可能会成为一个挑战。

总的来说,SAR是推荐系统工具箱中的一个有力工具。在实际应用中,我们需要根据具体的业务需求和数据特征,选择适合的算法或者多种算法的组合。

参考文献

  1. Recommenders contributors. (2023). SAR Single Node on MovieLens (Python, CPU). GitHub. https://github.com/recommenders-team/recommenders/blob/main/examples/00_quick_start/sar_movielens.ipynb
  2. Aggarwal, C. C. (2016). Recommender Systems: The Textbook. Springer International Publishing.
  3. Harper, F. M., & Konstan, J. A. (2015). The MovieLens Datasets: History and Context. ACM Transactions on Interactive Intelligent

这篇文章将介绍如何使用简单算法推荐(SAR)模型对MovieLens数据集进行协同过滤推荐。SAR是一种基于用户交互历史的快速可扩展的个性化推荐算法,具有易于解释和处理冷启动问题的优势。让我们一步步来看SAR模型的实现过程。

1. 数据准备

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

data = movielens.load_pandas_df(size="100k")
data["rating"] = data["rating"].astype(np.float32)

这里我们使用了MovieLens 100k数据集,包含10万条用户对电影的评分记录。

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

train, test = python_stratified_split(data, ratio=0.75, col_user="userID", col_item="itemID", seed=42)

我们使用了分层抽样的方法,保留75%的数据作为训练集,25%作为测试集。这种分割方法可以确保每个用户在训练集和测试集中都有数据。

2. SAR模型训练

SAR模型的核心思想是基于用户的历史交互来推荐相似的物品。我们首先实例化SAR模型:

model = SAR(
    col_user="userID",
    col_item="itemID",
    col_rating="rating",
    col_timestamp="timestamp",
    similarity_type="jaccard", 
    time_decay_coefficient=30, 
    timedecay_formula=True,
    normalize=True
)

这里我们使用了Jaccard相似度,并启用了时间衰减和归一化。

然后我们开始训练模型:

model.fit(train)

SAR模型的训练过程主要包括以下步骤:

  1. 计算物品共现矩阵
  2. 基于共现矩阵计算物品相似度矩阵
  3. 计算用户-物品亲和度矩阵

训练完成后,我们可以为测试集中的用户生成Top-K推荐:

top_k = model.recommend_k_items(test, top_k=TOP_K, remove_seen=True)

3. 模型评估

为了评估SAR模型的性能,我们使用了多个常用的推荐系统评估指标:

eval_map = map(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_ndcg = ndcg_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)
eval_precision = precision_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_recall = recall_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)

这些指标包括平均精度均值(MAP)、归一化折损累积增益(NDCG)、精确率和召回率。

此外,我们还计算了一些评分预测相关的指标:

eval_rmse = rmse(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_mae = mae(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_rsquared = rsquared(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_exp_var = exp_var(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")

这些指标包括均方根误差(RMSE)、平均绝对误差(MAE)、R方和解释方差。

4. 结果分析

在MovieLens 100k数据集上,SAR模型的表现如下:

  • MAP: 0.106959
  • NDCG: 0.379533
  • Precision@K. 0.331071
  • Recall@K. 0.176837
  • RMSE: 1.229246
  • MAE: 1.033912

这些结果表明,SAR模型在推荐相关性和排序质量方面表现不错,但在评分预测方面还有提升空间。

我们还可以查看特定用户的推荐结果:

user_id = 54
ground_truth = test[test["userID"] == user_id].sort_values(by="rating", ascending=False)[:TOP_K]
prediction = model.recommend_k_items(pd.DataFrame(dict(userID=[user_id])), remove_seen=True)
df = pd.merge(ground_truth, prediction, on=["userID", "itemID"], how="left")

这让我们能够直观地比较模型的推荐结果和用户的实际偏好。

5. 总结与展望

SAR模型作为一种简单高效的协同过滤算法,在MovieLens数据集上展现了不错的性能。它的优势在于:

  1. 训练和预测速度快
  2. 可解释性强
  3. 能够处理冷启动问题

然而,SAR模型也存在一些局限性:

  1. 不使用用户和物品特征,可能在某些场景下处于劣势
  2. 对于大规模数据集,内存消耗较大

未来的改进方向可以包括:

  1. 结合内容特征,构建混合推荐系统
  2. 使用更高级的相似度计算方法
  3. 探索模型集成,如将SAR与矩阵分解方法结合

总的来说,SAR模型为协同过滤推荐系统提供了一个简单而有效的baseline,值得在实际应用中尝试和优化。


简单算法推荐 (SAR) 在 MovieLens 数据集上的应用

简单算法推荐 (SAR) 是一种快速且可扩展的个性化推荐算法,它基于用户交易历史进行推荐。SAR 生成的推荐易于解释和理解,并能处理“冷启动物品”和“半冷启动用户”场景。SAR 属于一种基于邻域的算法,如 Aggarwal 的推荐系统 中所述,旨在为每个用户排名最顶级的物品。有关 SAR 的更多详细信息,请参阅 深入研究笔记本

SAR 推荐与用户已有 亲和力 的物品最 相似 的物品。如果与一个物品交互的用户也可能与另一个物品交互,则这两个物品是 相似 的。如果用户过去与某个物品交互过,则该用户对该物品具有 亲和力

SAR 的优势:

  • 对于易于训练和部署的算法,具有很高的准确性。
  • 快速训练,只需要简单的计数来构建预测时使用的矩阵。
  • 快速评分,只需要将相似度矩阵与亲和度向量相乘。

正确使用 SAR 的注意事项:

  • 由于它不使用物品或用户特征,因此在与使用特征的算法相比可能处于劣势。
  • 它需要大量的内存,需要创建一个 $mxm$ 的稀疏方阵(其中 $m$ 是物品的数量)。这对于许多矩阵分解算法来说也是一个问题。
  • SAR 倾向于隐式评分场景,它不预测评分。

本篇文章将以 Python 在 CPU 上为例,展示如何使用和评估 SAR。

1. 加载数据

SAR 旨在用于以下模式的交互:<用户 ID>, <物品 ID>,<时间>,[<事件类型>], [<事件权重>]

每行代表用户和物品之间的一次交互。这些交互可能是电子商务网站上不同类型的事件,例如用户点击查看物品、将物品添加到购物车、点击推荐链接等等。每个事件类型可以分配不同的权重,例如,我们可以将“购买”事件的权重分配为 10,而“查看”事件的权重可能只有 1。

MovieLens 数据集格式良好,包含用户对电影的评分(电影评分用作事件权重)——我们将使用它作为本篇文章的示例。

1.1 下载并使用 MovieLens 数据集

# top k 个推荐的物品
TOP_K = 10

# 选择 MovieLens 数据集大小:100k、1m、10m 或 20m
MOVIELENS_DATA_SIZE = "100k"

# 下载并加载 MovieLens 数据集
data = movielens.load_pandas_df(
    size=MOVIELENS_DATA_SIZE
)

# 将浮点精度转换为 32 位以减少内存消耗
data["rating"] = data["rating"].astype(np.float32)

1.2 使用实用程序提供的 Python 随机拆分器拆分数据

我们将完整数据集拆分为 traintest 数据集,以评估算法在训练期间未见过的保留集上的性能。由于 SAR 根据用户偏好生成推荐,因此测试集中所有用户也必须存在于训练集中。在这种情况下,我们可以使用提供的 python_stratified_split 函数,该函数从每个用户中保留一定比例(在本例中为 25%)的物品,但确保所有用户都存在于 traintest 数据集中。dataset.python_splitters 模块中提供了其他选项,可以更详细地控制拆分方式。

train, test = python_stratified_split(data, ratio=0.75, col_user="userID", col_item="itemID", seed=42)

2. 训练 SAR 模型

2.1 实例化 SAR 算法并设置索引

我们将使用 SAR 的单节点实现,并指定列名以匹配我们的数据集(时间戳是一个可选列,如果您的数据集不包含它,可以删除)。

其他选项用于控制算法的行为,如 深入研究笔记本 中所述。

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)-8s %(message)s')

model = SAR(
    col_user="userID",
    col_item="itemID",
    col_rating="rating",
    col_timestamp="timestamp",
    similarity_type="jaccard",
    time_decay_coefficient=30,
    timedecay_formula=True,
    normalize=True
)

2.2 在我们的训练数据上训练 SAR 模型,并为我们的测试数据获取 top-k 推荐

SAR 首先计算一个物品到物品的 共现矩阵。共现表示两个物品在任何给定用户中同时出现的次数。一旦我们有了共现矩阵,我们就可以通过给定指标(本例中为 Jaccard 相似度)重新缩放共现来计算 物品相似度矩阵

我们还计算一个 亲和度矩阵 来捕获每个用户与每个物品之间关系的强度。亲和度由不同的类型(如 评分观看 电影)以及事件发生的时间驱动。

推荐是通过将亲和度矩阵 $A$ 与相似度矩阵 $S$ 相乘来实现的。结果是一个 推荐评分矩阵 $R$。我们在下面看到的 recommend_k_items 函数中计算了 test 数据集中每个用户的 top-k 结果。

SAR 算法的完整演练可以在这里找到 here

with Timer() as train_time:
    model.fit(train)

print("Took {} seconds for training.".format(train_time.interval))

with Timer() as test_time:
    top_k = model.recommend_k_items(test, top_k=TOP_K, remove_seen=True)

print("Took {} seconds for prediction.".format(test_time.interval))

2.3 评估 SAR 的性能

我们评估 SAR 在 python_evaluation 模块中提供的几个常见排名指标上的性能。我们将考虑平均平均精度 (MAP)、归一化折损累积增益 (NDCG)、精确度和召回率,这些指标是针对我们使用 SAR 计算的每个用户的 top-k 物品。用户、物品和评分列名在每个评估方法中都已指定。

# 排名指标
eval_map = map(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_ndcg = ndcg_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)
eval_precision = precision_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K. eval_recall = recall_at_k(test, top_k, col_user="userID", col_item="itemID", col_rating="rating", k=TOP_K)

# 评分指标
eval_rmse = rmse(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_mae = mae(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_rsquared = rsquared(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")
eval_exp_var = exp_var(test, top_k, col_user="userID", col_item="itemID", col_rating="rating")

positivity_threshold = 2
test_bin = test.copy()
test_bin["rating"] = binarize(test_bin["rating"], positivity_threshold)

top_k_prob = top_k.copy()
top_k_prob["prediction"] = minmax_scale(top_k_prob["prediction"].astype(float))

eval_logloss = logloss(
    test_bin, top_k_prob, col_user="userID", col_item="itemID", col_rating="rating"
)
print("Model:\t",
      "Top K. \t%d" % TOP_K,
      "MAP:\t%f" % eval_map,
      "NDCG:\t%f" % eval_ndcg,
      "Precision@K. \t%f" % eval_precision,
      "Recall@K. \t%f" % eval_recall,
      "RMSE:\t%f" % eval_rmse,
      "MAE:\t%f" % eval_mae,
      "R2:\t%f" % eval_rsquared,
      "Exp var:\t%f" % eval_exp_var,
      "Logloss:\t%f" % eval_logloss,
      sep='\n')
# 现在让我们看看特定用户的结果
user_id = 54

ground_truth = test[test["userID"] == user_id].sort_values(
    by="rating", ascending=False
)[:TOP_K]
prediction = model.recommend_k_items(
    pd.DataFrame(dict(userID=[user_id])), remove_seen=True
)
df = pd.merge(ground_truth, prediction, on=["userID", "itemID"], how="left")
df.head(10)

上面,我们看到测试集中评分最高的物品之一被模型的 top-k 推荐所恢复,但其他物品则没有。离线评估很困难,因为它们只能使用测试集中以前看到的内容,可能无法代表用户在整个物品集中的实际偏好。对数据拆分方式、算法使用方式和超参数的调整可以改善这里的结果。

参考文献

希望这篇文章能帮助您更好地理解 SAR 算法及其在 MovieLens 数据集上的应用。

recommenders/examples/00_quick_start/sar_movielens.ipynb at main · recommenders-team/recommenders · GitHub

0 0 投票数
Article Rating
订阅评论
提醒
0 评论
最多投票
最新 最旧
内联反馈
查看所有评论
人生梦想 - 关注前沿的计算机技术 acejoy.com
0
希望看到您的想法,请您发表评论x