题目
实现基于用户的协同过滤推荐算法
信息
- 类型:问答
- 难度:⭐
考点
协同过滤原理,相似度计算,最近邻搜索
快速回答
基于用户的协同过滤推荐算法主要包含三个核心步骤:
- 计算用户相似度:使用余弦相似度衡量用户间的兴趣相似程度
- 选择最近邻:找出与目标用户最相似的K个用户
- 生成推荐:根据相似用户的喜好预测目标用户可能喜欢的物品
公式表示:用户相似度 = cos(θ) = (A·B) / (||A|| ||B||)
解析
原理说明
基于用户的协同过滤(User-Based Collaborative Filtering)通过分析用户行为数据,发现相似用户群体,并基于"相似用户喜欢的内容你也可能喜欢"的原理进行推荐。核心流程:
- 构建用户-物品交互矩阵(如评分、点击等)
- 计算用户间的相似度(常用余弦相似度)
- 为每个用户选择Top-K相似用户(最近邻)
- 根据相似用户的偏好预测目标用户对未交互物品的兴趣
代码示例(Python)
import numpy as np
# 用户-物品评分矩阵(5个用户,4部电影)
ratings = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4]
])
def cosine_similarity(user1, user2):
"""计算余弦相似度"""
mask = (user1 > 0) & (user2 > 0) # 仅计算共同评分的维度
if np.sum(mask) == 0: return 0
dot_product = np.dot(user1[mask], user2[mask])
norm1 = np.linalg.norm(user1[mask])
norm2 = np.linalg.norm(user2[mask])
return dot_product / (norm1 * norm2)
# 计算用户0与其他用户的相似度
user0 = ratings[0]
similarities = [cosine_similarity(user0, user) for user in ratings]
# 获取最近邻(排除自己)
k_neighbors = np.argsort(similarities)[-3:-1] # 取Top2
# 预测用户0对物品2的评分(加权平均)
numerator = denominator = 0
for neighbor in k_neighbors:
if ratings[neighbor, 2] > 0: # 邻居对物品2有评分
numerator += similarities[neighbor] * ratings[neighbor, 2]
denominator += abs(similarities[neighbor])
pred_rating = numerator / denominator if denominator != 0 else 0
print(f"预测评分: {pred_rating:.2f}")最佳实践
- 数据预处理:处理缺失值(如用全局平均填充),归一化评分消除用户评分偏差
- 相似度计算优化:仅计算共同评分项,使用Jaccard相似度解决数据稀疏问题
- 邻居选择:动态K值(相似度大于阈值的用户)优于固定K值
- 冷启动缓解:新用户可结合基于内容的推荐
常见错误
- 未处理数据稀疏:当共同评分项过少时仍计算相似度导致噪声
- 忽略评分偏差:未考虑用户评分尺度差异(严厉型vs宽容型)
- 邻居权重滥用:使用负相似度用户进行预测
- 效率问题:全量计算用户相似度(O(N²)复杂度),应使用局部敏感哈希优化
扩展知识
- 相似度替代方案:皮尔逊相关系数(解决评分偏差)、调整余弦相似度
- 变体算法:基于物品的协同过滤(Item-CF)更适合用户数远大于物品数的场景
- 实时更新:增量更新相似度矩阵避免全量重算
- 混合推荐:结合矩阵分解(MF)处理高稀疏数据