直接用scipy.spatial.distance.cosine易出错,因其默认对齐全部维度(含大量0)、不处理nan、未中心化,导致稀疏数据下相似度失真;应先构建用户-物品矩阵并保留nan,再基于共同评分项子集计算余弦相似度。

为什么直接用 scipy.spatial.distance.cosine 算用户相似度容易出错?
协同过滤的核心是衡量用户偏好向量的相似性,但原始评分数据稀疏、维度不一致、未归一化,直接套用余弦距离会放大零值干扰。比如用户 A 评了 5 部电影,B 评了 20 部,两人共同评分项可能只有 2 个——此时 cosine 默认对齐所有维度(含大量 0),结果失真。
实操建议:
- 先用
pandas.DataFrame.pivot_table构建用户-物品矩阵,缺失值留为NaN,别填 0 - 计算相似度前,对每行(即每个用户)只取「两人共同评分过的物品」子集,用
np.intersect1d找交集索引 - 用
sklearn.metrics.pairwise.cosine_similarity更稳妥,它自动跳过NaN(需先用.fillna(0)或更优:用均值填充 + 中心化) - 避免用
scipy.spatial.distance.cosine返回标量后手动转相似度(1 - distance),它不处理NaN,易报ValueError: Input contains NaN
如何给目标用户生成 Top-N 推荐而不遍历全部物品?
暴力法对每个未评分物品都算加权预测分,复杂度高且包含大量无效计算。关键不是“怎么算”,而是“哪些物品值得算”。
实操建议:
- 只考虑「相似用户评过分、且目标用户没评过」的物品:用布尔索引筛选,例如
~user_item_matrix.loc[target_id].isna() & user_item_matrix.loc[sim_users].notna().any() - 预测公式用标准加权平均:
pred = Σ(sim[u, target] × (rating[u, i] − mean_rating[u])) / Σ|sim[u, target]|,注意减去用户均值(中心化),否则高分用户会系统性拉高预测 - 用
numpy.nanmean替代np.mean处理稀疏行,避免除零或全NaN报错 - 最后用
pd.Series.nlargest(N)取 top 结果,别用sort_values(ascending=False).head(N),前者更快
surprise 库的 KNNBasic 和手写逻辑差在哪?
表面上都是基于用户的 KNN,但 surprise 默认启用偏差项(user bias + item bias + global mean),且相似度计算时自动做中心化、支持不同相似度度量(MSD、Pearson)、内置邻居剪枝和缓存。手写时若忽略这些,推荐质量会明显下降。
实操建议:
- 调试阶段先禁用偏差:传参
bsl_options={'biased': False},和手写逻辑对齐 - 指定
sim_options={'name': 'pearson_baseline', 'user_based': True},比默认的msd更适合用户协同场景 - 训练后别直接调
algo.predict(uid, iid)测单点——先用trainset.to_inner_iid()转换 ID,否则报KeyError - 如果要复现手写结果,必须设
k=100(不限制邻居数)并关闭所有正则项,否则surprise默认k=40且带shrinkage=100
冷启动用户没历史行为,还能用用户协同过滤吗?
不能。用户协同过滤完全依赖已有评分向量计算相似度,新用户向量全 NaN,相似度无定义,所有预测值都会是 nan 或触发异常。
实操建议:
- 检测冷启动:检查
user_item_matrix.loc[new_user].notna().sum() == 0,成立则跳过协同步骤 - 降级策略优先用热门物品(
user_item_matrix.sum(axis=0).nlargest(10)),别用全局平均分排序——热门 ≠ 高分 - 如果业务允许,强制收集至少 3 条显式反馈(如“喜欢/不喜欢”按钮),再进入协同流程
- 不要试图用物品协同(ItemCF)临时补位:两者数据结构不同,用户矩阵转物品矩阵需
.T,但冷启动用户在转置后仍是空行,问题未解
实际部署时最容易被忽略的是相似度矩阵的更新时机——它不能每次请求都重算,但用户新增一条评分后,相关行的相似度就过期了。要不要增量更新、更新几行、用 LRU 缓存还是定期全量重建,取决于 QPS 和数据更新频率,这个权衡点往往比算法本身更影响线上效果。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











