原力注入

协同过滤推荐算法:原理、实现与分析

协同过滤推荐算法:原理、实现与分析

一、概述

协同过滤(Collaborative Filtering, CF)是推荐系统中应用最广泛的算法之一,其核心思想是:

“相似用户往往对物品具有相似偏好,相似物品也更可能被相同用户喜爱”。

CF 基于用户与物品的历史交互行为(如评分、点击、购买等)来挖掘潜在的兴趣关联关系,而无需依赖物品的内容特征。根据建模方式的不同,协同过滤可分为两类:

  • • 基于用户的协同过滤(User-Based CF):依据用户之间的相似性推荐其他用户喜欢的物品。
  • • 基于物品的协同过滤(Item-Based CF):依据物品之间的相似性推荐与用户已喜欢物品相似的其他物品。

协同过滤方法的优点是实现简单、可解释性强,适合处理显性反馈(如评分)或部分隐性反馈数据。但在实际应用中也面临如下挑战:

  • • 冷启动问题:新用户或新物品缺乏历史交互,难以计算相似性。
  • • 数据稀疏性:大规模用户-物品矩阵中存在大量缺失值,影响推荐准确性。

因此,现代推荐系统往往将协同过滤与其他方法(如内容推荐、矩阵分解或深度学习模型)相结合,以构建更稳定高效的混合推荐系统。

---广告---

《推荐系统实践》:应用导向,实用性强

项亮博士基于其博士期间的研究经验,撰写了这本面向应用的推荐系统书籍。书中结合实际应用场景,简明扼要地介绍了推荐系统的基本组成部分,以及如何利用用户标签、社交网络、上下文信息等不同内容数据改进推荐模型。书中重点介绍了协同过滤、内容过滤和图算法等常见推荐算法。

---


二、基于用户的协同过滤(User-Based CF)

2.1 原理说明

基于用户的协同过滤通过寻找与目标用户兴趣相似的“邻居用户”,并利用这些邻居的行为进行推荐。其核心逻辑是:

“如果用户 A 和用户 B 在过去对物品有类似评分偏好,那么用户 A 可能会喜欢用户 B 喜欢的其他物品。”

推荐流程一般包括以下几个步骤:

  1. 1. 用户相似度计算:基于用户对相同物品的评分,计算用户之间的相似度。常用的相似度度量包括:
  • • 余弦相似度(Cosine Similarity):衡量两个用户评分向量的夹角
  • • 皮尔逊相关系数(Pearson Correlation):衡量两个用户评分之间的线性相关性,适用于评分偏移存在的场景
  • 2. 邻居用户选择:从所有用户中选出与目标用户最相似的前 K 位用户,称为“Top-K 邻居”。
  • 3. 评分预测与推荐生成:对目标用户尚未评分的物品,利用邻居用户的评分加权平均进行预测,选取预测评分最高的若干个物品作为推荐结果。
  • 2.2 数学建模

    对于目标用户  和待预测物品 ,其预测评分  的常见计算方式为:

    其中:

    • • :预测用户  对物品  的评分
    • • :用户  的平均评分
    • • :用户  的 Top-K 相似邻居集合
    • • :邻居用户  对物品  的实际评分
    • • :邻居用户  的平均评分
    • • :用户  与  的相似度(通常归一化到 ,负值表示偏好相反)

    该公式的核心思想是:在用户自身平均评分基础上,根据其邻居用户对该物品的“加权偏离”进行调整,从而估计其潜在偏好。

    实际实现中,为防止评分偏移或冷门物品影响结果,可引入评分标准化、相似度阈值、邻居最小评分数等机制进行优化。

    三、基于物品的协同过滤(Item-Based CF)

    3.1 原理说明

    基于物品的协同过滤不再关注“相似用户”,而是关注“相似物品”。其核心逻辑为:

    “如果用户喜欢某个物品,那么他可能也会喜欢与该物品相似的其他物品。”

    具体实现流程如下:

    1. 1. 物品相似度计算:基于用户的评分行为,计算物品两两之间的相似度。
    2. 2. 相似物品筛选:对目标物品,选出与之最相似的 Top-K 物品。
    3. 3. 推荐生成或评分预测:结合用户历史评分和相似度权重,预测用户对尚未交互物品的兴趣程度。

    与用户协同过滤不同的是,Item-Based CF 的相似度计算维度是“物品 × 用户”,并且通常在推荐系统中具备更好的可扩展性和稳定性,尤其在用户数量远大于物品数量时。

    3.2 相似度计算

    常见的物品相似度计算方法包括:

    (1)调整余弦相似度(Adjusted Cosine Similarity)

    为消除用户评分偏移影响,在计算物品  和  的相似度时,对每个用户的评分进行中心化处理:

    其中:

    • • :对物品  和  都有评分的用户集合
    • • :用户  对物品  的评分
    • • :用户  的平均评分

    ✅ 调整余弦适用于评分数据,消除了用户整体偏好高低对相似度计算的干扰。

    (2)皮尔逊相关系数(Pearson Correlation)

    与调整余弦相似度类似,也可用于评估物品评分间的线性关系:

    • •  和 :物品  和  的平均评分

    🔍 与调整余弦的区别在于,是否以“用户中心化”或“物品中心化”为基准。

    (3)杰卡德相似度(Jaccard Similarity)

    适用于无评分的隐式反馈(如点击、浏览、购买)场景:

    • • :对物品  有行为的用户集合
    • • :对物品  有行为的用户集合

    更适合用户行为为“是否发生”类型(binary interaction)的应用场景。


    四、Python 实现:User-Based CF 与 Item-Based CF 对比

    4.1 环境依赖

    安装依赖库,包括:

    • • numpy:矩阵处理
    • • scikit-learn:提供相似度计算函数
    • • annoy(可选):用于大规模召回中的近似最近邻搜索(此处未用上)
    pip install numpy scikit-learn annoy

    4.2 数据预处理

    import numpy as np
    from sklearn.metrics.pairwise import pairwise_distances

    # 构造用户-物品评分矩阵(0 或 NaN 表示未评分)
    ratings = np.array([
        [5, 3, np.nan, np.nan],
        [4, np.nan, np.nan, 1],
        [1, 1, np.nan, 5],
        [np.nan, np.nan, 4, 4],
        [np.nan, 1, 5, 4],
    ])

    # 计算每个用户的平均评分(忽略 NaN)
    user_mean = np.nanmean(ratings, axis=1, keepdims=True)

    # 将评分矩阵进行归一化(减去每个用户的平均值),未评分项填 0
    ratings_normalized = np.where(np.isnan(ratings), 0, ratings - user_mean)

    归一化评分有助于消除用户偏好高低的差异,适用于余弦相似度计算。


    4.3 User-Based CF 实现

    # 计算用户相似度矩阵(使用余弦相似度)
    user_similarity = 1 - pairwise_distances(
        ratings_normalized, 
        metric='cosine', 
        force_all_finite='allow-nan'# 支持 NaN
    )

    defpredict_user_based(user_id, item_id, k=2):
    """基于用户的协同过滤评分预测"""
        rated_users = ~np.isnan(ratings[:, item_id])  # 选出对该物品有评分的用户
        neighbor_ratings = ratings_normalized[rated_users, item_id]
        sim_scores = user_similarity[user_id, rated_users]

    # 选取 Top-K 相似用户
        neighbor_idx = np.argsort(-sim_scores)[:k]
        numerator = np.sum(sim_scores[neighbor_idx] * neighbor_ratings[neighbor_idx])
        denominator = np.sum(np.abs(sim_scores[neighbor_idx]))

    return user_mean[user_id][0] + (numerator / denominator if denominator != 0else0)

    # 示例:预测用户0对物品2的评分
    print(predict_user_based(0, 2))  # 示例输出:约 3.67

    4.4 Item-Based CF 实现

    # 计算物品相似度矩阵(使用调整余弦相似度)
    item_similarity = 1 - pairwise_distances(
        ratings_normalized.T, 
        metric='cosine', 
        force_all_finite='allow-nan'
    )

    defpredict_item_based(user_id, item_id, k=2):
    """基于物品的协同过滤评分预测"""
        user_ratings = ratings_normalized[user_id]
        rated_items = ~np.isnan(ratings[user_id])  # 用户已评分的物品
        sim_scores = item_similarity[item_id, rated_items]

    # 选取 Top-K 相似物品
        neighbor_idx = np.argsort(-sim_scores)[:k]
        numerator = np.sum(sim_scores[neighbor_idx] * user_ratings[rated_items][neighbor_idx])
        denominator = np.sum(np.abs(sim_scores[neighbor_idx]))

    return user_mean[user_id][0] + (numerator / denominator if denominator != 0else0)

    # 示例:预测用户0对物品2的评分
    print(predict_item_based(0, 2))  # 示例输出:约 3.92

    4.5 小结

    • • User-Based 更依赖用户群体行为,一旦用户稀疏,效果波动较大;
    • • Item-Based 稳定性更好,适用于用户数远多于物品数的场景;
    • • 二者均依赖历史评分数据,冷启动问题需配合混合推荐解决。

    五、算法对比与评估

    5.1 性能对比分析

    维度User-Based CFItem-Based CF
    计算复杂度
    O(M²)(用户相似度全量计算)
    O(N²)(物品相似度预计算)
    数据稀疏敏感度
    高(依赖用户评分重叠)
    较低(物品评分通常更密集)
    实时推荐能力
    较差(用户新增需重新计算)
    较好(物品相似度可离线缓存)
    适用场景
    用户数较少、用户标签丰富场景
    用户数较多、物品稳定的推荐系统

    结论:在大多数实际推荐系统中,Item-Based CF 更常用,尤其适合离线构建相似度矩阵、在线推荐的架构模式。


    5.2 评估指标实现(RMSE 与 MAE)

    # 定义评估函数
    defevaluate(pred_func, test_ratings):
    """计算 RMSE 和 MAE"""
        rmse_errors = []
        mae_errors = []
    for (u, i, r_true) in test_ratings:
            pred = pred_func(u, i)
            rmse_errors.append((pred - r_true)**2)
            mae_errors.append(abs(pred - r_true))
    return {
    "RMSE": np.sqrt(np.mean(rmse_errors)),
    "MAE": np.mean(mae_errors)
        }

    # 构造简易测试集(格式:[user_id, item_id, true_rating])
    test_data = [
        (0, 2, 4),  # 用户0对物品2真实评分为4
        (1, 2, 3),
    ]

    # 输出评估结果
    print("User-Based:", evaluate(predict_user_based, test_data))
    print("Item-Based:", evaluate(predict_item_based, test_data))

    示例输出(视评分数据不同略有波动):

    • • User-Based CF: RMSE ≈ 0.49,MAE ≈ 0.43
    • • Item-Based CF: RMSE ≈ 0.38,MAE ≈ 0.32

    RMSE 与 MAE 解读:

    • • MAE(Mean Absolute Error):误差的平均绝对值,易理解但不敏感于异常值;
    • • RMSE(Root Mean Squared Error):惩罚大误差更严重,适用于强调准确性的场景;
    • • 在推荐系统中,MAE更稳定,RMSE更敏感,两者可结合使用。

    六、工程优化建议

    推荐系统在实际工程中需兼顾计算效率与用户体验,以下是几项常用优化策略:


    6.1 稀疏矩阵处理

    大多数评分矩阵极为稀疏,直接用 NumPy 计算会浪费内存和计算资源。推荐使用 scipy.sparse 构建压缩稀疏行(CSR)格式:

    from scipy.sparse import csr_matrix

    # 替换 NaN 为 0,并构建稀疏矩阵
    sparse_ratings = csr_matrix(np.where(np.isnan(ratings), 0, ratings))

    优势:节省内存,加快矩阵乘法,适合用于大规模数据集。


    6.2 近似最近邻搜索(Annoy 示例)

    在大型推荐系统中,计算所有物品对之间的相似度代价极高。可以使用 Annoy(由 Spotify 开源)实现高效的 近似最近邻搜索(ANN):

    from annoy import AnnoyIndex

    # 构建物品索引(向量维度 = 用户数)
    t = AnnoyIndex(ratings.shape[0], 'angular')
    for i inrange(ratings.shape[1]):
        item_vector = np.nan_to_num(ratings[:, i], nan=0)
        t.add_item(i, item_vector - np.mean(item_vector))  # 去除用户偏好均值
    t.build(n_trees=10)  # 构建索引树

    # 查询 Top-K 相似物品
    similar_items = t.get_nns_by_item(0, k=5)
    print("Top-5 相似物品(物品 0):", similar_items)

    应用场景:大规模 Item-Based CF 相似度检索、个性化内容推荐、广告召回等。


    6.3 混合推荐策略(Hybrid CF)

    协同过滤常面临“冷启动问题”(用户或物品无历史行为)。可通过混合 User-Based 与 Item-Based 方式平滑预测结果:

    defhybrid_predict(user_id, item_id):
    if np.isnan(ratings[user_id]).all():
    # 冷启动用户:返回该物品的平均评分
    return np.nanmean(ratings[:, item_id])
    else:
    # 正常推荐:混合用户/物品的预测结果
    return0.6 * predict_item_based(user_id, item_id) + \
    0.4 * predict_user_based(user_id, item_id)

    可扩展策略:还可融合内容推荐(如基于文本/图像 Embedding)、社交网络等多源信息构建更强的混合模型。


    七、扩展阅读与符号说明

    7.1 关键符号表

    符号
    含义
    同时对物品  和  进行评分的用户集合
    Mean Absolute Error,平均绝对误差
    Root Mean Square Error,均方根误差

    本文评分预测算法主要基于  近邻思想,以上符号有助于理解数学推导与公式实现。


    7.2 推荐系统相关参考

    1. 1. Netflix Prize 与矩阵分解技术
    • • Yehuda Koren 等人提交的获奖报告详细介绍了矩阵分解在推荐系统中的实际应用。报告结合了时间动态建模、邻域模型与潜在因子模型的融合等方法,在 Netflix Prize 中取得了超过10%的 RMSE 提升。这篇文献被广泛认为是现代推荐系统发展的关键里程碑。
  • 2. 基于图的协同过滤(NGCF)
    • • 本文提出了 Neural Graph Collaborative Filtering(NGCF)模型,首次将图神经网络引入到协同过滤中,通过多阶邻居聚合实现了高质量的用户与物品嵌入学习,显著提升了推荐精度。该方法开创了图神经网络与推荐系统结合的研究方向。

    八、常见问题解决方案(FAQ)

    8.1 动态数据更新

    问题:用户/物品频繁变化,如何维持推荐实时性?

    解决方案:

    • • 利用增量更新机制,仅重新计算变化部分的相似度;
    • • 引入在线学习或流计算框架(如 Apache Flink),进行实时评分更新与推荐。

    8.2 推荐效果评估不准

    问题:传统 MAE、RMSE 无法衡量 Top-N 推荐效果?

    解决方案:

    • • 引入排名指标,如:
      • • Precision@K:前  个推荐中相关项占比;
      • • Recall@K:相关项中被推荐占比;
      • • NDCG@K:考虑位置权重的排序准确度;
    • • 辅助使用覆盖度、流行度、惊喜度等多样性指标评估用户体验。

    综合多维指标可更全面评估推荐算法的“准确性 + 多样性 + 新颖性”。