如何绘制推荐系统的Precision-Recall曲线?
推荐系统Precision-Recall曲线可视化解决方案
问题分析
你遇到的核心问题有三个:
- 未正确初始化
SparkRankingEvaluation评估器,导致precision_at_k()和recall_at_k()调用失败 - Scikit-learn的
precision_recall_curve和PrecisionRecallDisplay仅支持本地数据(如Pandas DataFrame/Numpy数组),无法直接处理Spark DataFrame - 推荐系统排序任务的Precision-Recall曲线,是基于不同Top-K阈值下的precision和recall值绘制,而非二分类任务的阈值曲线
解决方案步骤
1. 修正评估器初始化
首先需要正确创建SparkRankingEvaluation实例,关联真实标签与预测结果数据:
# 初始化排序评估器 spark_rank_eval = SparkRankingEvaluation( dfs_true, dfs_pred, **HEADER )
2. 定义正例规则(可选)
排序任务需明确正样本定义,比如将评分≥3标记为正例(可根据业务调整),评估器默认按此逻辑计算,也可通过rating_threshold参数修改阈值。
3. 计算多k值下的precision和recall
选择一系列k值(如1到10),遍历计算每个k对应的precision@k和recall@k:
import matplotlib.pyplot as plt # 定义要计算的k值范围 k_values = range(1, 11) precisions = [] recalls = [] for k in k_values: prec = spark_rank_eval.precision_at_k(k=k) rec = spark_rank_eval.recall_at_k(k=k) precisions.append(prec) recalls.append(rec)
4. 绘制Precision-Recall曲线
用Matplotlib将计算出的precision和recall值绘制成曲线:
plt.figure(figsize=(8, 6)) plt.plot(recalls, precisions, marker='o', linestyle='-', color='b') plt.xlabel('Recall@k') plt.ylabel('Precision@k') plt.title('推荐系统Precision-Recall曲线') plt.grid(True) plt.show()
完整可运行代码
import pandas as pd import pyspark import sklearn import matplotlib.pyplot as plt from recommenders.utils.spark_utils import start_or_get_spark from recommenders.evaluation.spark_evaluation import SparkRankingEvaluation, SparkRatingEvaluation COL_USER = "UserId" COL_ITEM = "MovieId" COL_RATING = "Rating" COL_PREDICTION = "Rating" HEADER = { "col_user": COL_USER, "col_item": COL_ITEM, "col_rating": COL_RATING, "col_prediction": COL_PREDICTION } df_true = pd.DataFrame( { COL_USER: [1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], COL_ITEM: [1, 2, 3, 1, 4, 5, 6, 7, 2, 5, 6, 8, 9, 10, 11, 12, 13, 14], COL_RATING: [5, 4, 3, 5, 5, 3, 3, 1, 5, 5, 5, 4, 4, 3, 3, 3, 2, 1], } ) df_pred = pd.DataFrame( { COL_USER: [1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], COL_ITEM: [3, 10, 12, 10, 3, 5, 11, 13, 4, 10, 7, 13, 1, 3, 5, 2, 11, 14], COL_PREDICTION: [14, 13, 12, 14, 13, 12, 11, 10, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5] } ) # 初始化Spark环境 spark = start_or_get_spark("EvaluationTesting", "local") # 转为Spark DataFrame dfs_true = spark.createDataFrame(df_true) dfs_pred = spark.createDataFrame(df_pred) # 初始化排序评估器 spark_rank_eval = SparkRankingEvaluation( dfs_true, dfs_pred, **HEADER, rating_threshold=3 # 自定义正例阈值,评分≥3视为正样本 ) # 计算多k值下的precision和recall k_values = range(1, 11) precisions = [] recalls = [] for k in k_values: precisions.append(spark_rank_eval.precision_at_k(k=k)) recalls.append(spark_rank_eval.recall_at_k(k=k)) # 绘制Precision-Recall曲线 plt.figure(figsize=(8, 6)) plt.plot(recalls, precisions, marker='o', linestyle='-', color='#1f77b4') plt.xlabel('Recall@k') plt.ylabel('Precision@k') plt.title('推荐系统Precision-Recall曲线') plt.grid(alpha=0.3) plt.show()
关键说明
- 推荐系统的Precision-Recall曲线与二分类任务不同:它展示的是不同Top-K推荐列表长度下,模型的精准度和召回率变化趋势,而非分类阈值的影响
- 若需要更平滑的曲线,可以增加k值的密度(如k从1到20)
rating_threshold参数可根据业务场景调整,比如将评分≥4视为正样本
内容的提问来源于stack exchange,提问作者Rachel Tran
相关产品推荐
相关产品推荐

