
机器学习人工智能【免费下载链接】SurpriseA Python scikit for building and analyzing recommender systems项目地址https://gitcode.com/gh_mirrors/su/Surprise点击查看免费下载本篇技术指南以 Surprise 推荐系统库的官方文档 doc/source/slope_one.rst 为主线围绕其中定义的SlopeOne预测算法展开先拆解其简单却准确的协同过滤数学原理再结合 surprise/prediction_algorithms/slope_one.pyx 逐行剖析训练与预测实现最后给出基于 movielens-100k 数据集的完整可运行示例、精度评估方法与测试验证结果。读完本文你将掌握 Slope One 的评分预测机制、它在 Surprise 中的调用方式以及它在基准测试中的真实表现定位。一、Slope One 是什么一种基于物品差异的协同过滤Slope One 是一种经典的基于物品item-based的协同过滤算法由 Lemire 与 Maclachlan 于 2005 年提出。它的核心假设非常朴素如果用户对物品 A 和物品 B 的评分普遍相差某个固定值那么当我们知道该用户对 A 的评分时就可以用这个平均差异来推算他对 B 的评分。在 Surprise 中SlopeOne类位于surprise.prediction_algorithms.slope_one模块并已通过 surprise/init.py 导出到顶层命名空间因此可以直接通过from surprise import SlopeOne使用。类的 docstring 中将其定位为A simple yet accurate collaborative filtering algorithm一种简单而准确的协同过滤算法其公式与实现直接参考了论文lemire2007aLemire, D. Maclachlan, A.,Slope One Predictors for Online Rating-Based Collaborative Filtering。与 k-NN 算法KNNBasic需要维护相似度矩阵不同Slope One 只需要在训练阶段统计物品两两之间的平均评分差预测阶段即可快速给出估计值训练过程不含任何迭代优化实现非常直接。二、核心预测公式基于物品差异的加权平均Surprise 中SlopeOne的预测公式见 slope_one.pyx 的 docstring定义如下$$\hat{r}{ui} \mu_u \frac{1}{|R_i(u)|} \sum{j \in R_i(u)} \text{dev}(i, j)$$其中各符号含义为$\hat{r}_{ui}$用户 $u$ 对物品 $i$ 的预测评分$\mu_u$用户 $u$ 对所有已评分物品的平均分用户均值$R_i(u)$与物品 $i$ 相关的物品集合即用户 $u$ 已评过、并且与物品 $i$ 至少有一个共同评分用户的物品 $j$ 的集合$\text{dev}(i, j)$物品 $i$ 与物品 $j$ 之间的平均评分差异。其中物品间平均差异定义为$$\text{dev}(i, j) \frac{1}{|U_{ij}|} \sum_{u \in U_{ij}} (r_{ui} - r_{uj})$$这里 $U_{ij}$ 是同时给物品 $i$ 和物品 $j$ 都打过分的用户集合$r_{ui}$、$r_{uj}$ 分别是这些用户对两件物品的真实评分。$\text{dev}(i, j)$ 度量的是整体上人们给 $i$ 的评分比给 $j$ 的评分平均高或低多少。公式的直观解读先取用户 $u$ 自己的平均分 $\mu_u$ 作为基准再针对目标物品 $i$把所有 $u$ 已评物品 $j$ 与 $i$ 之间的平均差 $\text{dev}(i, j)$ 加起来取平均作为对 $\mu_u$ 的修正量。换句话说预测值 用户自身评分基准 目标物品相对其已知物品的平均偏差。这一设计既利用了物品间的全局统计规律又保留了用户个人的评分尺度这正是 Slope One 在简洁性下仍能保持不错准确度的关键。三、源码实现剖析训练阶段如何计算 freq 与 devSurprise 的SlopeOne用 Cython 实现.pyx文件训练逻辑集中在 fit() 方法中。整个训练过程可分为三步3.1 初始化两个 n_items × n_items 矩阵cdef Py_ssize_t [:, ::1] freq np.zeros((trainset.n_items, trainset.n_items), np.intp) cdef double [:, ::1] dev np.zeros((trainset.n_items, trainset.n_items), np.double)freq[i, j]统计同时评过物品 $i$ 和 $j$ 的用户数 $|U_{ij}|$dev[i, j]累加所有同时评过 $i$、$j$ 的用户的评分差 $r_{ui} - r_{uj}$。两个矩阵的维度都是物品总数 × 物品总数这也是 Slope One 最主要的空间开销。3.2 三重循环遍历用户评分累加统计for u, u_ratings in trainset.ur.items(): for i, r_ui in u_ratings: for j, r_uj in u_ratings: freq[i, j] 1 dev[i, j] r_ui - r_uj这里trainset.ur是训练集的一个defaultdict键为用户内层 idinner id值为该用户所有评分的(item_inner_id, rating)元组列表见 surprise/trainset.py。对每个用户的评分列表做两两组合每当两个物品同时出现在同一用户的评分中就在freq上 1、在dev上累加两者评分之差。这一步骤以 $O(\sum_u |I_u|^2)$ 的时间代价建立起完整的物品差异统计。3.3 归一化得到最终偏差矩阵for i in range(n_items): dev[i, i] 0 for j in range(i 1, n_items): dev[i, j] / freq[i, j] dev[j, i] -dev[i, j]对角线上dev[i, i]强制置 0物品与自身的差异为零对 $j i$ 的每一对用累加的总差除以共同评分人数freq[i, j]得到平均差异 $\text{dev}(i, j)$利用反对称性直接赋值dev[j, i] -dev[i, j]$i$ 相对 $j$ 的偏差恰好是 $j$ 相对 $i$ 偏差的相反数省去一半重复计算。训练结束时fit把freq、dev以 numpy 数组形式存为实例属性并额外计算每个用户的平均分列表self.user_mean [np.mean([r for (_, r) in trainset.ur[u]]) for u in trainset.all_users()]即公式中的 $\mu_u$。至此训练阶段完成所有可复用的统计量都已就绪。四、源码实现剖析预测阶段如何估计评分预测逻辑集中在 estimate() 方法中if not (self.trainset.knows_user(u) and self.trainset.knows_item(i)): raise PredictionImpossible(User and/or item is unknown.) Ri [j for (j, _) in self.trainset.ur[u] if self.freq[i, j] 0] est self.user_mean[u] if Ri: est sum(self.dev[i, j] for j in Ri) / len(Ri) return est预测过程与公式一一对应边界检查若用户或物品不在训练集中knows_user/knows_item分别检查ur与ir见 surprise/trainset.py则抛出PredictionImpossible异常构造相关物品集合 $R_i(u)$遍历用户 $u$ 的所有评分物品 $j$筛选出freq[i, j] 0的即与目标物品 $i$ 有共同评分用户的物品估计以用户均值user_mean[u]为起点若 $R_i(u)$ 非空则加上目标物品与这些相关物品平均差异的均值。需要说明的是estimate接收的是内层 id。Surprise 的AlgoBase.predict()见 algo_base.py会先把外部传入的**原始 idraw id**通过to_inner_uid/to_inner_iid转换为内层 id再调用estimate若转换失败用户或物品未知则由AlgoBase.predict()捕获PredictionImpossible将估计值回退为训练集全局均值default_prediction()trainset.global_mean并在details[was_impossible]中标记该预测不可用。此外predict()默认会把估计值裁剪clip进评分尺度区间[rating_scale[0], rating_scale[1]]内例如评分尺度为 1~5 时估算出的 5.5 会被截断为 5。五、快速上手在 movielens-100k 上运行 Slope One下面给出与官方 Getting Started 文档风格一致的完整示例展示 Slope One 在 Surprise 中的标准使用流程。5.1 交叉验证评估cross_validatefrom surprise import Dataset, SlopeOne from surprise.model_selection import cross_validate # 加载内置 movielens-100k 数据集若未下载会自动下载到 ~/.surprise_data data Dataset.load_builtin(ml-100k) algo SlopeOne() # 5 折交叉验证评估 RMSE 与 MAE cross_validate(algo, data, measures[RMSE, MAE], cv5, verboseTrue)cross_validate()会输出每一折的 RMSE、MAE、Fit time、Test time 及均值与标准差。这也是 examples/basic_usage.py 所演示的 Surprise 最基础用法只需将示例中的SVD换成SlopeOne即可。5.2 手动划分训练集与测试集train_test_splitfrom surprise import Dataset, SlopeOne, accuracy from surprise.model_selection import train_test_split data Dataset.load_builtin(ml-100k) # 按 75% / 25% 划分训练集与测试集 trainset, testset train_test_split(data, test_size0.25) algo SlopeOne() algo.fit(trainset) # 训练计算 freq / dev 矩阵与用户均值 predictions algo.test(testset) # 在测试集上预测 accuracy.rmse(predictions) # 输出如 RMSE: 1.16xxfit()继承自 AlgoBase.fit()会把 trainset 保存到self.trainsettest()则对测试集中每个(uid, iid, r_ui)调用predict()返回一个Prediction列表Prediction为五元组命名元组见 predictions.py。5.3 训练整个数据集并预测单条评分from surprise import Dataset, SlopeOne data Dataset.load_builtin(ml-100k) trainset data.build_full_trainset() # 用全部数据构建训练集 algo SlopeOne() algo.fit(trainset) # predict 使用原始 idraw id如用户 196、物品 302 pred algo.predict(uid196, iid302, r_ui4, verboseTrue)predict()返回的Prediction对象包含uid、iid、真实评分r_ui、估计值est以及details字典打印结果形如user: 196 item: 302 r_ui 4.00 est 4.06 {...}。当用户或物品不在训练集中时details[was_impossible]为Trueest回退为全局均值。5.4 命令行使用Surprise 支持命令行运行所有内置算法SlopeOne也已注册进 CLI 的算法列表见 surprise/main.pysurprise -algo SlopeOne -load-builtin ml-100k -n-folds 5该命令会在 ml-100k 上执行 5 折交叉验证并打印各折的 RMSE/MAE。可用surprise -h查看完整参数-params、-load-custom、-folds-files、-reader、-seed、--with-dump等。六、基准测试中的表现来自仓库测试的实证Surprise 仓库通过单元测试锁定了各算法在 ml-100k 上第一个折的 RMSE 期望值即健全性检查其中SlopeOne 的期望 RMSE 为 1.1559939123891685见 tests/test_algorithms.py 的test_sanity_checks参数化用例(SlopeOne(), 1.1559939123891685),该测试使用PredefinedKFold的第一次划分训练/测试文件为仓库内的 u1_ml100k_train 与 u1_ml100k_test断言accuracy.rmse(predictions) expected_rmse同时断言预测结果并非全部不可用not all(pred.details[was_impossible] ...)。这意味着你可以用同一套数据复现出确定性的精度结果用于验证本地安装的正确性。横向参照同组测试数据BaselineOnly约为 1.027、SVD约为 1.008、KNNBasic(msd)约为 1.134、CoClustering约为 1.084。可见 Slope One 在不依赖任何超参数调优的前提下精度落在简单基线BaselineOnly与基础 k-NN 之间属于零参数、开箱即用的性价比型算法。另外examples/benchmark.py 展示了如何对所有内置算法含SlopeOne在 ml-100k 上统一执行 5 折交叉验证并汇总 RMSE、MAE 与总耗时表格可作为算法横向对比的参考脚本。七、Slope One 的边界、限制与适用建议7.1 内存与时间开销freq与dev均为 $n_{items} \times n_{items}$ 的稠密矩阵空间复杂度 $O(n_{items}^2)$训练阶段对每个用户的评分做两两遍历时间复杂度为 $O(\sum_u |I_u|^2)$。对于物品数很大的数据集如百万级物品内存占用会迅速膨胀这是 Slope One 最重要的规模化瓶颈。7.2 冷启动与未知实体当用户或物品未出现在训练集中时estimate直接抛出PredictionImpossible预测值回退为全局均值。这一行为被 test_unknown_user_or_item 显式测试覆盖所有内置算法。7.3 与 k-NN 类算法的定位差异k-NN 类算法KNNBasic 等依赖用户-用户或物品-物品相似度需要设置k、min_k、sim_options等参数Slope One 则完全不依赖相似度计算与任何超参数直接用全局物品差异统计做预测因此特别适合作为快速基线baseline或用于需要极低推理延迟、又希望优于全局均值/用户均值这类朴素预测的场景。7.4 补充说明训练集中评分尺度rating_scale由 Reader 定义预测值的裁剪与精度计算均受其约束SlopeOne的预测本身不基于bsl_options或sim_options其构造函数仅调用AlgoBase.__init__(self)见 slope_one.pyx因此无需配置这两类选项在 CHANGELOG.md 中可以看到 Slope One 作为独立算法随早期版本加入属于仓库长期稳定支持的算法之一。八、总结Slope One 是 Surprise 中最具极简主义气质的协同过滤算法之一训练阶段只需统计物品两两评分差dev矩阵与共同评分人数freq矩阵预测阶段用用户均值 相关物品平均偏差即可给出估计。其公式简洁、无超参数、实现透明适合作为推荐系统的快速基线与教学案例。通过 slope_one.pyx 的源码、test_algorithms.py 的确定性精度断言以及 basic_usage.py 等示例脚本开发者可以快速复现、验证并评估它在自己数据集上的表现。赞分享机器学习人工智能【免费下载链接】SurpriseA Python scikit for building and analyzing recommender systems项目地址https://gitcode.com/gh_mirrors/su/Surprise点击查看免费下载相关推荐Surprise 矩阵分解算法完全指南SVD、SVD 与 NMF 的原理、参数与实战Surprise 矩阵分解算法完全指南SVD、SVD 与 NMF 的原理、参数与实战 导读 Surprise 是一个面向推荐系统的 Python 工具库机器学习人工智能PaddleNLP Metrics API 完全指南内置评估指标的实现原理与实战用法PaddleNLP Metrics API 完全指南内置评估指标的实现原理与实战用法 导读 本文围绕 PaddleNLP 提供的模型评估指标Metrics人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLPSurprise 推荐系统库实战指南数据集加载、算法评估与交叉验证全解析Surprise 推荐系统库实战指南数据集加载、算法评估与交叉验证全解析 导读 SurpriseSimple Python RecommendatIon S机器学习人工智能上一篇Web 安全 Payload 实战手册PayloadsAllTheThings 从上手到用好下一篇终极Reactide文件树管理指南轻松驾驭复杂React项目结构创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考