FunRec中的UserCF:用户协同过滤算法详解
1. UserCF核心原理:物以类聚,人以群分
在电商平台购物时,我们常发现这样的现象:当用户A和用户B购买了相同的T恤和裤子并给出好评,系统会向用户A推荐用户B购买的其他商品。这种"相似用户喜欢相似物品"的朴素思想,正是用户协同过滤(User Collaborative Filtering, UserCF) 的核心逻辑。
UserCF是最早提出的协同过滤算法 :cite:resnick1994grouplens,其工作流程可概括为:
- 找到相似用户:计算目标用户与其他用户的行为相似度
- 生成推荐结果:基于相似用户的偏好预测目标用户兴趣
1.1 算法直观理解
如上图所示,当两个用户对同一批商品表现出相似偏好时,他们被判定为"相似用户",其未交集的行为将作为推荐依据。
2. 相似度计算:量化用户相似性
2.1 常用相似度指标对比
| 指标 | 公式 | 适用场景 | 优缺点 | ||||||
|---|---|---|---|---|---|---|---|---|---|
| 杰卡德相似系数 | $w_{uv} = \frac{ | N(u) \cap N(v) | }{ | N(u) \cup N(v) | }$ | 无评分数据 | 计算简单,丢失行为强度信息 | ||
| 余弦相似度 | $w_{uv} = \frac{ | N(u) \cap N(v) | }{\sqrt{ | N(u) | \cdot | N(v) | }}$ | 隐式反馈 | 考虑用户活跃度差异 |
| 皮尔逊相关系数 | $w_{uv} = \frac{\sum_{i \in I}(r_{ui} - \bar{r}u)(r{vi} - \bar{r}v)}{\sqrt{\sum{i \in I}(r_{ui} - \bar{r}u)^2}\sqrt{\sum{i \in I}(r_{vi} - \bar{r}_v)^2}}$ | 显式评分 | 消除评分偏置,反映相对偏好 |
皮尔逊系数优势:通过中心化处理(减去用户平均分),有效消除"评分宽容度"差异。例如严格用户B给4分相当于宽松用户A给5分的实际偏好。
2.2 相似度计算优化
直接计算所有用户对的相似度时间复杂度为$O(|U|^2)$,在百万级用户规模下不可行。实际实现中采用物品倒排表优化:
优化后时间复杂度降至$O(R \cdot \bar{n})$($R$为交互总数,$\bar{n}$为物品平均用户数),在稀疏数据场景下效率提升显著。
3. 推荐生成:从相似用户到推荐结果
3.1 评分预测公式
基础加权平均模型: $$\hat{r}{u,p} = \frac{\sum{v \in S_u} w_{uv} , r_{v,p}}{\sum_{v \in S_u} w_{uv}}$$
带偏置修正的改进模型: $$\hat{r}{u,p} = \bar{r}{u} + \frac{\sum_{v \in S_u} w_{uv} , (r_{v,p} - \bar{r}{v})}{\sum{v \in S_u} w_{uv}}$$
其中:
- $\hat{r}_{u,p}$:用户u对物品p的预测评分
- $S_u$:与用户u最相似的K个用户集合
- $\bar{r}_u$:用户u的平均评分
- $w_{uv}$:用户u和v的相似度
3.2 推荐生成流程
4. 算法实现:从理论到代码
4.1 基础实现(Python)
import numpy as np
import pandas as pd
# 1. 数据准备
user_data = {
'user1': {'item1': 5, 'item2': 3, 'item3': 4, 'item4': 4},
'user2': {'item1': 3, 'item2': 1, 'item3': 2, 'item4': 3, 'item5': 3},
'user3': {'item1': 4, 'item2': 3, 'item3': 4, 'item4': 3, 'item5': 5},
'user4': {'item1': 3, 'item2': 3, 'item3': 1, 'item4': 5, 'item5': 4},
'user5': {'item1': 1, 'item2': 5, 'item3': 5, 'item4': 2, 'item5': 1},
}
# 2. 构建相似度矩阵
def build_similarity_matrix(user_data):
users = list(user_data.keys())
n = len(users)
sim_matrix = pd.DataFrame(np.identity(n), index=users, columns=users)
for i in range(n):
u = users[i]
for j in range(i+1, n):
v = users[j]
# 提取共同评分物品
common_items = set(user_data[u].keys()) & set(user_data[v].keys())
if not common_items:
sim = 0
else:
vec_u = [user_data[u][item] for item in common_items]
vec_v = [user_data[v][item] for item in common_items]
sim = np.corrcoef(vec_u, vec_v)[0][1]
sim_matrix.loc[u, v] = sim
sim_matrix.loc[v, u] = sim
return sim_matrix
similarity_matrix = build_similarity_matrix(user_data)
# 3. 生成推荐
def recommend_items(target_user, similarity_matrix, user_data, top_n=2, rec_n=1):
# 获取相似用户
sim_users = similarity_matrix[target_user].sort_values(ascending=False)[1:top_n+1].index
# 预测评分
target_mean = np.mean(list(user_data[target_user].values()))
weighted_sum = 0
sim_sum = 0
for user in sim_users:
sim = similarity_matrix.loc[target_user, user]
user_mean = np.mean(list(user_data[user].values()))
# 寻找该用户交互过的、目标用户未交互的物品
for item, rating in user_data[user].items():
if item not in user_data[target_user]:
weighted_sum += sim * (rating - user_mean)
sim_sum += sim
pred_score = target_mean + weighted_sum / sim_sum
return pred_score
# 预测用户1对物品5的评分
predicted_score = recommend_items('user1', similarity_matrix, user_data)
print(f"预测评分: {predicted_score:.4f}") # 输出: 4.8700
4.2 FunRec框架实现
import funrec
from funrec.utils import build_metrics_table
# 加载配置
config = funrec.load_config('user_cf')
# 数据准备与模型训练
train_data, test_data = funrec.load_data(config.data)
feature_columns, processed_data = funrec.prepare_features(config.features, train_data, test_data)
model = funrec.train_model(config.training, feature_columns, processed_data)
# 模型评估
metrics = funrec.evaluate_model(model, processed_data, config.evaluation)
print(build_metrics_table(metrics))
评估结果示例:
+---------------+--------------+----------------+---------------+
| hit_rate@10 | hit_rate@5 | precision@10 | precision@5 |
+===============+==============+================+===============+
| 0.6912 | 0.5927 | 0.1643 | 0.2063 |
+---------------+--------------+----------------+---------------+
5. 算法优化与工程实践
5.1 时间复杂度优化
UserCF在用户量大时面临性能挑战,常用优化手段包括:
- 用户聚类:通过K-means等算法将用户分组,仅计算组内相似度
- 采样优化:随机采样部分用户计算相似度,降低计算量
- 倒排表优化:通过物品-用户倒排表减少冗余计算
优化效果对比:
| 优化方法 | 时间复杂度 | 空间复杂度 | 精度损失 |
|---|---|---|---|
| 原始算法 | O(U²) | O(U²) | 无 |
| 倒排表优化 | O(R·n̄) | O(R) | <5% |
| 聚类+采样 | O((U/k)² + k·U) | O((U/k)²) | ~10% |
5.2 参数调优指南
| 参数 | 推荐范围 | 影响 |
|---|---|---|
| K(相似用户数) | 20-100 | K太小易过拟合,太大引入噪声 |
| 相似度阈值 | 0.3-0.6 | 过滤低相似度用户,减少噪声 |
| 评分衰减因子 | 0.7-0.9 | 降低旧数据权重,适应兴趣变化 |
6. 适用场景与局限性
6.1 适用场景
- 用户数较少的应用(如企业内部系统)
- 兴趣变化快的领域(如新闻推荐)
- 需要解释性的场景(可提供"相似用户也喜欢"的解释)
6.2 局限性
- 用户数量扩展性差:用户数超过10万时计算成本显著上升
- 数据稀疏性问题:新用户缺乏行为数据难以找到相似用户
- 流行物品偏差:倾向推荐热门物品,多样性不足
7. 算法变种与演进
7.1 改进算法对比
| 算法 | 核心改进 | 性能提升 |
|---|---|---|
| UserCF-IIF | 对活跃用户的相似度进行惩罚 | 热门物品推荐占比降低20% |
| 基于模型的UserCF | 用神经网络学习相似度 | 准确率提升15-20% |
| 时序UserCF | 引入时间衰减因子 | 时效性指标提升25% |
7.2 与ItemCF的对比选择
| 维度 | UserCF | ItemCF |
|---|---|---|
| 计算复杂度 | O(U²) | O(I²) |
| 推荐多样性 | 较高 | 较低 |
| 实时性 | 较差 | 较好 |
| 适用场景 | 新闻、社交 | 电商、视频 |
8. 总结与实践建议
UserCF作为协同过滤的开山鼻祖,其"相似用户"的核心思想影响深远。在实际应用中:
- 中小规模用户场景:直接使用UserCF可获得良好效果
- 大规模系统:建议与ItemCF或模型融合使用
- 冷启动处理:结合内容特征缓解新用户问题
通过合理的参数调优和工程优化,UserCF依然是推荐系统领域的重要基础算法,尤其在解释性和实现复杂度方面具有独特优势。
参考文献
- Resnick, P., et al. (1994). GroupLens: An open architecture for collaborative filtering of netnews.
- Sarwar, B., et al. (2001). Item-based collaborative filtering recommendation algorithms.
- Koren, Y., et al. (2009). Matrix factorization techniques for recommender systems.
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



