一、概念
协同过滤(Collaborative Filtering, CF)是推荐系统中最经典的算法之一,通过分析用户行为和偏好(如评分、点击、购买等)来预测用户可能感兴趣的内容,一般用于推荐系统的召回阶段。它的核心思想是“物以类聚,人以群分”,即通过用户之间的相似性或物品之间的相似性来进行推荐。主要分为两类:
- 基于用户的协同过滤(User-Based Collaborative Filtering, UBCF):通过找到与目标用户兴趣相似的其他用户,推荐这些用户喜欢的物品。
- 基于物品的协同过滤(Item-Based Collaborative Filtering, IBCF):通过找到与目标物品相似的其他物品,推荐这些物品给用户。
二、基于用户的协同过滤
假设我们有一个用户物品评分表(“-”表示未评分),现在我们希望预测用户丙对其未购买过的物品B的评分,并以此判断是否向丙推荐物品B:
用户\物品 | A | B | C | D |
---|---|---|---|---|
甲 | 5 | 3 | 4 | - |
乙 | 3 | 4 | - | 4 |
丙 | 4 | - | 5 | 3 |
1、计算用户相似度
为了预测用户丙对其未评分的物品B的评分,一个直观的思路是先看看有没有跟用户丙有相似购买/评分行为的用户(即相似用户)。如果这些用户恰好购买了物品B,那么我们可以预估丙的评分,例如最直接的做法就是求相似用户评分的均值。因此,我们需要计算一下用户相似度,找到与丙相似的Top N个用户:
(1)计算丙和甲的相似度
- 共同评分物品:A、C
- 计算余弦相似度(也可以是其他度量方法):
(2)计算丙和乙的相似度
- 共同评分物品:A、D
- 计算余弦相似度:
2、选择Top N相似用户
这里我们设N为1,那么跟丙最相似的用户就是甲。
3、预测用户丙对物品B的评分
这里,我们假设评分计算公式为:(相似用户1评分*相似度1+相似用户2评分*相似度2+...+相似用户n评分*相似度n)/(相似度1+相似度2+...+相似度n),那么有:
我们就可以得到用户丙对物品B的评分预估值为3,假设这个得分大于等于我们设定的推荐阈值,那么物品B可以推荐给用户丙,反之不推荐。
三、基于物品的协同过滤
基于物品的协同过滤计算方式同基于用户的协同过滤,只不过将基于用户的相似度计算和筛选转为了基于物品的相似度计算和筛选。
四、python实现
这里我们简单地实现一个python示例辅助理解。
1、数据源
假设我们有一个用户-物品评分矩阵:
import pandas as pd
import numpy as np
# 用户-物品评分矩阵
data = {
'User1': {'Item1': 5, 'Item2': 3, 'Item3': 0, 'Item4': 0},
'User2': {'Item1': 4, 'Item2': 0, 'Item3': 0, 'Item4': 2},
'User3': {'Item1': 0, 'Item2': 0, 'Item3': 4, 'Item4': 5},
'User4': {'Item1': 0, 'Item2': 3, 'Item3': 0, 'Item4': 4},
}
ratings = pd.DataFrame(data).T
print(ratings)
2、用户相似度计算
计算得出用户相似度矩阵。
from sklearn.metrics.pairwise import cosine_similarity
# 填充缺失值为0
ratings_filled = ratings.fillna(0)
# 计算用户之间的余弦相似度
user_similarity = cosine_similarity(ratings_filled)
user_similarity_df = pd.DataFrame(user_similarity, index=ratings.index, columns=ratings.index)
print(user_similarity_df)
3、评分函数构建及应用
def predict_ratings(user_similarity, ratings):
# 填充缺失值为0
ratings_filled = ratings.fillna(0).values
# 计算加权评分
pred_ratings = user_similarity.dot(ratings_filled) / np.array([np.abs(user_similarity).sum(axis=1)]).T
return pd.DataFrame(pred_ratings, index=ratings.index, columns=ratings.columns)
predicted_ratings = predict_ratings(user_similarity, ratings)
print(predicted_ratings)
4、物品推荐
这里我们根据评分对每一个用户没有购买过的物品进行排序,这样一来就可以推荐预估评分最高的Top K个物品给对应用户了。
def recommend_items(predicted_ratings, original_ratings, top_n=2):
recommendations = {}
for user in predicted_ratings.index:
# 找到用户未评分的物品
user_ratings = original_ratings.loc[user]
user_predicted = predicted_ratings.loc[user]
unscored_items = user_ratings[user_ratings == 0].index
# 按预测评分排序
recommended_items = user_predicted[unscored_items].sort_values(ascending=False).head(top_n).index
recommendations[user] = recommended_items.tolist()
return recommendations
recommendations = recommend_items(predicted_ratings, ratings)
print(recommendations)
五、总结
协同过滤算法无需依赖物品的具体内容信息,适用于各种类型的数据,因此在推荐系统发展的早期成为了最常用的推荐算法。然而,协同过滤算法对稀疏数据敏感,存在冷启动问题。本文简单地给出了协同过滤算法的计算实例,而在实际应用场景中的算法设计要更为复杂,因为用户、物品的数据量往往是巨大的,如何处理数据稀疏性并考虑计算开销成为重中之重。