sklearn分类准确率计算避坑指南:metrics.accuracy_score()在样本不平衡时的陷阱

张开发
2026/4/17 17:49:46 15 分钟阅读

分享文章

sklearn分类准确率计算避坑指南:metrics.accuracy_score()在样本不平衡时的陷阱
样本不平衡场景下分类模型评估的全面指南超越accuracy_score的局限在医疗诊断、金融风控和广告点击预测等实际业务场景中我们经常会遇到正负样本比例严重失衡的数据集。许多刚接触机器学习分类任务的中级开发者往往会直接使用sklearn中的accuracy_score作为模型评估的首选指标却忽略了这一指标在样本不平衡时的致命缺陷。1. 为什么accuracy_score会误导我们的判断想象一下这样的场景在一个包含1000条记录的信用卡欺诈检测数据集中正常交易有990条欺诈交易只有10条。如果一个模型简单地将所有交易都预测为正常它的准确率会高达99%。从accuracy_score的数值来看这似乎是一个优秀的模型但实际上它对欺诈交易的识别率是0%。1.1 accuracy_score的计算原理accuracy_score的计算公式非常简单准确率 (TP TN) / (TP TN FP FN)其中TPTrue Positive正确预测的正例TNTrue Negative正确预测的负例FPFalse Positive错误预测的正例FNFalse Negative错误预测的负例在sklearn中的基本调用方式from sklearn.metrics import accuracy_score y_true [0, 1, 0, 1] # 真实标签 y_pred [0, 1, 1, 0] # 预测标签 acc accuracy_score(y_true, y_pred) print(f准确率: {acc:.2f})1.2 样本不平衡时的陷阱当数据集中某一类样本占比极高时accuracy_score会严重高估模型性能。下表展示了不同样本分布下全预测为多数类的愚蠢模型能达到的准确率少数类占比全预测多数类的准确率1%99%5%95%10%90%20%80%关键问题在医疗诊断等场景中我们通常更关心少数类如患病案例的识别能力而accuracy_score完全无法反映这方面的性能。2. 更全面的评估指标体系2.1 混淆矩阵及其衍生指标一个更全面的评估应该从混淆矩阵出发预测负类 预测正类 实际负类 TN FP 实际正类 FN TP基于混淆矩阵我们可以计算多个关键指标精确率(Precision)预测为正类的样本中实际为正类的比例Precision TP / (TP FP)召回率(Recall)实际正类中被正确预测的比例Recall TP / (TP FN)F1分数精确率和召回率的调和平均F1 2 * (Precision * Recall) / (Precision Recall)在sklearn中的实现from sklearn.metrics import precision_score, recall_score, f1_score precision precision_score(y_true, y_pred) recall recall_score(y_true, y_pred) f1 f1_score(y_true, y_pred) print(f精确率: {precision:.2f}, 召回率: {recall:.2f}, F1分数: {f1:.2f})2.2 ROC曲线与AUCROC曲线通过绘制不同阈值下的真阳性率(TPR)和假阳性率(FPR)来评估模型性能from sklearn.metrics import roc_curve, auc import matplotlib.pyplot as plt fpr, tpr, thresholds roc_curve(y_true, y_scores) roc_auc auc(fpr, tpr) plt.plot(fpr, tpr, labelfROC曲线 (AUC {roc_auc:.2f})) plt.plot([0, 1], [0, 1], k--) plt.xlabel(假阳性率) plt.ylabel(真阳性率) plt.title(ROC曲线) plt.legend() plt.show()AUC曲线下面积提供了一个综合评估0.5随机猜测0.7-0.8有一定区分能力0.8-0.9良好0.9优秀2.3 PR曲线与平均精度对于高度不平衡的数据PR曲线精确率-召回率曲线通常比ROC曲线更有参考价值from sklearn.metrics import precision_recall_curve precision, recall, _ precision_recall_curve(y_true, y_scores) plt.plot(recall, precision, labelPR曲线) plt.xlabel(召回率) plt.ylabel(精确率) plt.title(精确率-召回率曲线) plt.legend() plt.show()平均精度(AP)是PR曲线下的面积特别适合评估不平衡数据。3. 处理样本不平衡的技术方案3.1 数据层面的解决方案过采样增加少数类样本如SMOTE算法欠采样减少多数类样本混合采样结合过采样和欠采样from imblearn.over_sampling import SMOTE smote SMOTE(random_state42) X_res, y_res smote.fit_resample(X, y)3.2 算法层面的解决方案类别权重调整模型对少数类的重视程度from sklearn.linear_model import LogisticRegression model LogisticRegression(class_weightbalanced) model.fit(X_train, y_train)代价敏感学习为不同类别的错误分类设置不同代价集成方法如EasyEnsemble、BalanceCascade3.3 评估指标的调整调整分类阈值默认0.5可能不是最优选择from sklearn.metrics import precision_recall_curve precision, recall, thresholds precision_recall_curve(y_true, y_scores) # 根据业务需求选择最佳阈值业务定制指标如医疗中的挽救生命比例4. 实际案例广告点击预测假设我们有一个广告点击预测数据集点击率约为2%。我们比较三种模型的评估结果模型准确率精确率召回率F1分数AUC全预测负类0.980.000.000.000.50逻辑回归0.970.250.650.360.82随机森林SMOTE0.950.300.750.430.88从这个对比可以明显看出仅看准确率会严重误导判断经过不平衡处理的模型在召回率和F1分数上表现更好AUC提供了更全面的性能评估实现代码示例from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from imblearn.pipeline import make_pipeline from imblearn.over_sampling import SMOTE # 数据准备 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3) # 构建处理不平衡数据的管道 model make_pipeline( SMOTE(random_state42), RandomForestClassifier(class_weightbalanced) ) model.fit(X_train, y_train) # 评估 y_pred model.predict(X_test) y_proba model.predict_proba(X_test)[:, 1] print(准确率:, accuracy_score(y_test, y_pred)) print(F1分数:, f1_score(y_test, y_pred)) print(AUC:, roc_auc_score(y_test, y_proba))在医疗诊断场景中我们可能更关注召回率减少漏诊而在广告推荐中可能更关注精确率减少误推。理解业务需求并选择合适的评估指标是构建有效机器学习模型的关键一步。

更多文章