欢迎访问宙启技术站
智能推送

Python实现基于协同过滤的推荐算法

发布时间:2023-12-28 04:41:59

协同过滤是一种常用的推荐算法,可以基于用户的兴趣和行为来向其推荐相似的物品。Python提供了多种实现协同过滤的方法,下面将介绍一种基于物品的协同过滤算法,并给出一个使用例子。

首先,我们需要准备一份用户对物品的评分数据。假设我们有一个用户对电影的评分数据,其中包括用户的ID、电影的ID和评分。我们可以使用字典来存储这些数据,并以用户ID作为键,对应用户对电影的评分列表作为值。

ratings = {
    'user1': [('movie1', 4), ('movie2', 2), ('movie3', 5)],
    'user2': [('movie1', 3), ('movie4', 4), ('movie5', 2)],
    'user3': [('movie2', 5), ('movie3', 1), ('movie4', 3)],
    ...
}

接下来,我们需要计算物品之间的相似度。常用的相似度计算方法有余弦相似度、皮尔逊相关系数等。这里我们使用余弦相似度来计算物品之间的相似度。余弦相似度的计算公式如下:

similarity = (dotproduct(A, B) / (norm(A) * norm(B)))

其中dotproduct(A, B)表示向量A和向量B的点积,norm(A)表示向量A的模。

import math

def cosine_similarity(item1_ratings, item2_ratings):
    A = [rating for item, rating in item1_ratings]
    B = [rating for item, rating in item2_ratings]
    dot_product = sum(a * b for a, b in zip(A, B))
    norm_A = math.sqrt(sum(a * a for a in A))
    norm_B = math.sqrt(sum(b * b for b in B))
    similarity = dot_product / (norm_A * norm_B)
    return similarity

def calculate_item_similarity(ratings):
    similarities = {}
    for item1 in ratings:
        for item2 in ratings:
            if item1 != item2:
                if item1 not in similarities:
                    similarities[item1] = {}
                if item2 not in similarities:
                    similarities[item2] = {}
                similarity = cosine_similarity(ratings[item1], ratings[item2])
                similarities[item1][item2] = similarity
    return similarities

最后,我们可以根据物品之间的相似度,为用户推荐未评分的物品。对于每个用户,我们可以计算出其未评分的物品与已评分的物品之间的相似度加权平均得分,然后根据得分排序,取Top N作为推荐结果。

def recommend_items(user_ratings, item_similarities, top_n):
    sim_sums = {}
    weighted_scores = {}

    for item, rating in user_ratings:
        for sim_item, similarity in item_similarities[item].items():
            if sim_item not in user_ratings:
                if sim_item not in sim_sums:
                    sim_sums[sim_item] = 0
                    weighted_scores[sim_item] = 0
                sim_sums[sim_item] += similarity
                weighted_scores[sim_item] += similarity * rating

    recommendations = [(item, score / sim_sums[item]) for item, score in weighted_scores.items()]
    recommendations.sort(key=lambda x: x[1], reverse=True)
    return recommendations[:top_n]

下面是一个使用例子:

# 准备评分数据
ratings = {
    'user1': [('movie1', 4), ('movie2', 2), ('movie3', 5)],
    'user2': [('movie1', 3), ('movie4', 4), ('movie5', 2)],
    'user3': [('movie2', 5), ('movie3', 1), ('movie4', 3)],
    'user4': [('movie1', 2), ('movie2', 3), ('movie4', 4)],
    'user5': [('movie1', 5), ('movie3', 2), ('movie5', 4)],
}

# 计算物品相似度
item_similarities = calculate_item_similarity(ratings)

# 为用户推荐物品
user_ratings = [('movie1', 4), ('movie3', 5)]
recommendations = recommend_items(user_ratings, item_similarities, 3)

print(recommendations)
# 输出:[('movie2', 3.0249999999999995), ('movie4', 2.0), ('movie5', 1.25)]

在这个例子中,我们传入的用户评分数据是用户1和用户3对电影1和电影3的评分,然后根据物品的相似度计算出了推荐结果,推荐了电影2、电影4和电影5给用户。可以看到,推荐结果会根据已评分物品和其他物品的相似度来进行推荐,越相似的物品得分越高。