如何将Surprise库中的餐厅评分任务转换为分类问题?
问题描述
我有用户对餐厅的1、2、3分评分数据,当前用Surprise库实现的是回归任务,采用RMSE、MAE等指标。想通过Surprise的Reader方法将其指定为分类任务,转换后测试accuracy和precision指标。当前代码如下:
reader = Reader(rating_scale=(1,3)) rating_data = Dataset.load_from_df(userrating[['userID', 'placeID', 'rating']], reader) KNN = KNNWithMeans(verbose=True, n_epochs=100) KNN_results = cross_validate(KNN, rating_data, measures=['RMSE', 'MAE', 'fcp'], cv=3, verbose=True)
解决方案
Surprise本身没有直接将回归任务转为分类任务的内置参数,但可以通过把预测的连续评分映射到离散类别,再手动计算分类指标来实现,具体步骤如下:
1. 保留Reader的评分范围设置
Reader的rating_scale=(1,3)无需修改,它仅用于定义数据中评分的取值范围,和任务类型无关。
2. 自定义分类指标计算函数
Surprise的cross_validate不直接支持accuracy、precision这类分类指标,需要自行编写计算逻辑:
from sklearn.metrics import accuracy_score, precision_score import numpy as np def compute_classification_metrics(predictions): # 提取真实评分和模型预测的连续值 y_true = np.array([pred.r_ui for pred in predictions]) y_pred = np.array([pred.est for pred in predictions]) # 将连续预测值四舍五入映射到1-3的离散类别,同时确保不超出评分范围 y_pred_round = np.round(y_pred).clip(1, 3) # 计算多分类下的accuracy和precision(用macro平均适配多分类场景) acc = accuracy_score(y_true, y_pred_round) prec = precision_score(y_true, y_pred_round, average='macro') return {'accuracy': acc, 'precision': prec}
3. 手动执行交叉验证并计算指标
放弃cross_validate,改用KFold拆分数据集,遍历每个折完成训练、预测和指标计算:
from surprise.model_selection import KFold # 初始化交叉验证器和模型(注意:KNNWithMeans没有n_epochs参数,需移除) kf = KFold(n_splits=3) knn = KNNWithMeans(verbose=True) # 存储各折的指标结果 fold_metrics = {'accuracy': [], 'precision': []} for trainset, testset in kf.split(rating_data): # 训练模型 knn.fit(trainset) # 生成测试集预测结果 predictions = knn.test(testset) # 计算当前折的分类指标 current_metrics = compute_classification_metrics(predictions) # 记录结果 fold_metrics['accuracy'].append(current_metrics['accuracy']) fold_metrics['precision'].append(current_metrics['precision']) # 输出各指标的平均值 print(f"平均Accuracy: {np.mean(fold_metrics['accuracy']):.4f}") print(f"平均Precision: {np.mean(fold_metrics['precision']):.4f}")
可选:适配二分类场景
如果你的需求是二分类(比如将1、2分归为“差评”,3分归为“好评”),可以修改映射逻辑:
# 二分类映射:1-2→0,3→1 y_true_bin = np.where(y_true == 3, 1, 0) y_pred_bin = np.where(y_pred_round == 3, 1, 0) acc = accuracy_score(y_true_bin, y_pred_bin) prec = precision_score(y_true_bin, y_pred_bin)
内容的提问来源于stack exchange,提问作者antoine larousse
相关产品推荐
相关产品推荐

