Python实现itemCF协同过滤推荐算法并计算召回率、准确率、F1分数和覆盖率

一个完整的Python实现,包括ItemCF协同过滤算法的实现以及召回率、准确率、F1分数和覆盖率等评估指标的计算。将使用Pandas进行数据处理,Scikit-learn进行相似度计算,并编写函数来生成推荐列表和评估模型性能。

1. 数据准备

首先,需要准备数据。假设有一个用户-物品评分矩阵(可以是显式评分或隐式反馈),表示用户对不同酒店的喜好程度。这里可以使用Pandas来处理数据。

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# 假设有以下用户-酒店评分数据
data = {
    'user': [1, 1, 1, 2, 2, 3, 3, 3, 4, 5],
    'hotel': ['A', 'B', 'C', 'A', 'D', 'B', 'C', 'E', 'F', 'G'],
    'rating': [5, 4, 3, 4, 5, 2, 4, 5, 3, 4]
}

df = pd.DataFrame(data)

# 构建用户-酒店评分矩阵
user_hotel_matrix = df.pivot(index='user', columns='hotel', values='rating').fillna(0)

2. 计算物品相似度

在ItemCF中,通常使用余弦相似度来衡量酒店之间的相似度。

# 计算酒店之间的相似度矩阵
hotel_sim_matrix = cosine_similarity(user_hotel_matrix.T)
hotel_sim_df = pd.DataFrame(hotel_sim_matrix, index=user_hotel_matrix.columns, columns=user_hotel_matrix.columns)

3. 生成推荐列表

接下来,需要根据用户的历史行为和酒店相似度来生成推荐列表。对于每个用户,将他之前交互过的酒店与其相似的酒店进行加权求和,得到一个预测评分,然后选择评分最高的几个酒店作为推荐结果。

def recommend_hotels(user_id, user_hotel_matrix, hotel_sim_df, top_n=5):
    # 获取用户已经评分过的酒店
    user_ratings = user_hotel_matrix.loc[user_id].copy()
    rated_hotels = user_ratings[user_ratings > 0].index
    
    # 初始化推荐分数
    recommendations = pd.Series(0, index=user_hotel_matrix.columns)
    
    for hotel in rated_hotels:
        # 找到与当前酒店相似的其他酒店
        similar_hotels = hotel_sim_df[hotel].drop(hotel).sort_values(ascending=False)
        
        # 更新推荐分数
        for sim_hotel, similarity in similar_hotels.items():
            if user_ratings[sim_hotel] == 0:  # 只考虑用户未评分的酒店
                recommendations[sim_hotel] += similarity * user_ratings[hotel]
    
    # 排除用户已经评分过的酒店
    recommendations.drop(rated_hotels, errors='ignore', inplace=True)
    
    # 返回推荐列表
    return recommendations.sort_values(ascending=False).head(top_n).index.tolist()

# 为用户1生成推荐
recommended_hotels = recommend_hotels(1, user_hotel_matrix, hotel_sim_df, top_n=3)
print("Recommended hotels for user 1:", recommended_hotels)

4. 评估模型

为了评估推荐系统的性能,可以使用召回率(Recall)、准确率(Precision)、F1分数(F1 Score)和覆盖率(Coverage)等指标。假设有一个测试集,其中包含用户的实际偏好(即用户真正喜欢但没有评分的酒店)。可以比较推荐列表与测试集中的酒店,计算这些指标。

# 假设这是用户1的真实偏好(测试集)
true_hotels = ['D', 'E']

# 计算召回率和准确率
def evaluate_recommendations(recommended_hotels, true_hotels):
    num_recommended = len(recommended_hotels)
    num_true = len(true_hotels)
    num_hit = len(set(recommended_hotels).intersection(set(true_hotels)))
    
    precision = num_hit / num_recommended if num_recommended > 0 else 0
    recall = num_hit / num_true if num_true > 0 else 0
    
    return precision, recall

# 计算F1分数
def f1_score(precision, recall):
    if precision + recall == 0:
        return 0
    return 2 * (precision * recall) / (precision + recall)

# 计算覆盖率
def item_coverage(recommended_hotels, all_hotels):
    return len(set(recommended_hotels)) / len(all_hotels)

# 评估用户1的推荐结果
precision, recall = evaluate_recommendations(recommended_hotels, true_hotels)
f1 = f1_score(precision, recall)
coverage = item_coverage(recommended_hotels, user_hotel_matrix.columns)

print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
print(f"F1 Score: {f1:.2f}")
print(f"Coverage: {coverage:.2f}")

5. 扩展评估指标

为了更全面地评估推荐系统的性能,还可以计算其他指标,如多样性(Diversity)、新颖性(Novelty)等。

5.1. 多样性 (Diversity)

多样性衡量的是推荐列表中酒店之间的差异程度。一个多样化的推荐系统可以为用户提供更广泛的选择,避免推荐过于相似的酒店。

def intra_list_diversity(recommendation_list, similarity_matrix):
    n = len(recommendation_list)
    if n <= 1:
        return 0
    diversity = 0
    for i in range(n):
        for j in range(i + 1, n):
            diversity += 1 - similarity_matrix.loc[recommendation_list[i], recommendation_list[j]]
    return 2 * diversity / (n * (n - 1))

# 计算推荐列表的多样性
diversity = intra_list_diversity(recommended_hotels, hotel_sim_df)
print(f"Diversity: {diversity:.2f}")
5.2. 新颖性 (Novelty)

新颖性衡量的是推荐系统推荐的新酒店的比例。新酒店是指那些不常见或用户不太熟悉的酒店。推荐新酒店可以增加用户的兴趣和探索欲望。

# 假设有一个酒店流行度字典,表示每个酒店的历史交互次数
hotel_popularity = {'A': 10, 'B': 8, 'C': 6, 'D': 5, 'E': 4, 'F': 3, 'G': 2}

def average_popularity(recommended_hotels, hotel_popularity):
    return np.mean([hotel_popularity.get(hotel, 0) for hotel in recommended_hotels])

# 计算推荐列表的平均流行度(越低越好)
novelty = average_popularity(recommended_hotels, hotel_popularity)
print(f"Novelty (Average Popularity): {novelty:.2f}")

通过上述代码,实现了一个简单的ItemCF协同过滤算法,并计算了召回率、准确率、F1分数、覆盖率、多样性和新颖性等评估指标。这些指标可以帮助更全面地了解推荐系统的性能,并根据需要进行优化。

你可能感兴趣的:(机器学习,python,推荐算法,开发语言)