协同过滤算法是推荐系统中最经典的实现方案,核心思路是通过分析用户的历史行为数据,找到和目标用户兴趣相似的其他用户,或者和目标物品相似的其他物品,进而为目标用户生成推荐结果。根据实现逻辑的不同,协同过滤可以分为基于用户的协同过滤和基于物品的协同过滤两类,本文将以基于用户的协同过滤为例,讲解Python实现的具体过程。

协同过滤算法核心原理
基于用户的协同过滤算法的核心步骤分为三步:首先计算所有用户之间的相似度,找到和目标用户兴趣最相近的K个邻居用户;然后收集这些邻居用户喜欢但目标用户还没接触过的物品;最后根据邻居用户对物品的评分,加权计算出目标用户对这些物品的预测评分,按评分从高到低排序生成推荐列表。
用户相似度的计算通常有多种方式,最常用的是余弦相似度,它通过计算两个用户评分向量的夹角余弦值来衡量兴趣相似程度,值越接近1说明两个用户兴趣越相似。
Python实现步骤
1. 准备测试数据
我们首先构造一个简单的用户-物品评分矩阵,模拟用户对电影的评分数据,评分范围1到5,0表示用户未对该物品评分。
# 构造用户-物品评分矩阵,行代表用户,列代表物品
# 评分范围1-5,0表示未评分
user_item_matrix = {
"user1": {"item1": 5, "item2": 3, "item3": 0, "item4": 1, "item5": 2},
"user2": {"item1": 4, "item2": 0, "item3": 0, "item4": 1, "item5": 3},
"user3": {"item1": 1, "item2": 1, "item3": 5, "item4": 0, "item5": 0},
"user4": {"item1": 0, "item2": 2, "item3": 4, "item4": 0, "item5": 1},
"user5": {"item1": 3, "item2": 3, "item3": 0, "item4": 2, "item5": 4}
}
2. 计算用户余弦相似度
接下来实现余弦相似度计算函数,需要提取两个用户共同评分过的物品,再基于这些物品的评分计算相似度。
import math
def calculate_cosine_similarity(user1_ratings, user2_ratings):
# 找到两个用户共同评分的物品
common_items = set(user1_ratings.keys()) & set(user2_ratings.keys())
# 如果没有共同评分物品,相似度为0
if not common_items:
return 0.0
# 提取共同物品的评分
vec1 = [user1_ratings[item] for item in common_items]
vec2 = [user2_ratings[item] for item in common_items]
# 计算点积
dot_product = sum(a * b for a, b in zip(vec1, vec2))
# 计算两个向量的模长
norm1 = math.sqrt(sum(a * a for a in vec1))
norm2 = math.sqrt(sum(b * b for b in vec2))
# 避免除零错误
if norm1 == 0 or norm2 == 0:
return 0.0
return dot_product / (norm1 * norm2)
3. 生成推荐结果
实现推荐函数,先找到和目标用户最相似的K个邻居,再基于邻居的评分生成推荐列表。
def generate_recommendations(target_user, user_item_matrix, top_k=2):
# 计算目标用户和其他所有用户的相似度
similarity_scores = []
target_ratings = user_item_matrix[target_user]
for user, ratings in user_item_matrix.items():
if user == target_user:
continue
sim = calculate_cosine_similarity(target_ratings, ratings)
if sim > 0:
similarity_scores.append((user, sim))
# 按相似度从高到低排序,取前top_k个邻居
similarity_scores.sort(key=lambda x: x[1], reverse=True)
top_neighbors = similarity_scores[:top_k]
# 收集邻居喜欢但目标用户未评分的物品
candidate_items = {}
for neighbor, sim in top_neighbors:
neighbor_ratings = user_item_matrix[neighbor]
for item, rating in neighbor_ratings.items():
# 物品未被目标用户评分,且邻居评分大于3(认为邻居喜欢该物品)
if item not in target_ratings or target_ratings[item] == 0:
if rating > 3:
if item not in candidate_items:
candidate_items[item] = []
candidate_items[item].append((sim, rating))
# 计算预测评分
recommendations = []
for item, scores in candidate_items.items():
total_sim = sum(sim for sim, _ in scores)
weighted_rating = sum(sim * rating for sim, rating in scores) / total_sim
recommendations.append((item, weighted_rating))
# 按预测评分从高到低排序
recommendations.sort(key=lambda x: x[1], reverse=True)
return recommendations
4. 测试推荐效果
调用上述函数,为目标用户生成推荐结果,查看推荐逻辑是否符合预期。
# 为目标用户user1生成推荐
target_user = "user1"
recommendations = generate_recommendations(target_user, user_item_matrix, top_k=2)
print(f"为用户{target_user}的推荐结果:")
for item, score in recommendations:
print(f"物品:{item},预测评分:{score:.2f}")
运行上述代码后,会输出user1的推荐物品和对应的预测评分,开发者可以根据实际业务需求调整相似度计算方式、邻居数量、评分阈值等参数,优化推荐效果。
算法优化方向
上述实现是基础版本的协同过滤算法,实际落地时还可以做很多优化:比如处理用户评分偏差,将用户评分减去其平均评分后再计算相似度;引入物品热门度惩罚,避免总是推荐热门物品;当数据量较大时,可以使用稀疏矩阵存储评分数据,提升计算效率;也可以结合基于物品的协同过滤算法,混合两种方案的结果提升推荐准确性。