
个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 我想学python了 其他栏目: iOS项目总结大全 其他栏目: iOS UI 文章目录模型评估指标实战——为什么 99% 准确率的模型其实一文不值一、一个真实踩过的坑二、混淆矩阵一切指标的源头三、四个核心指标各自到底在衡量什么四、代码实战亲手复现99% 准确率的废模型五、ROC-AUC跨阈值衡量模型的排序能力六、指标对比与选型表七、几个常见的坑八、小结模型评估指标实战——为什么 99% 准确率的模型其实一文不值一、一个真实踩过的坑某次做信用卡欺诈检测同事兴冲冲跑来说“模型准确率 99.8%可以上线了”结果一查测试集里 1000 条交易只有 2 条是欺诈。模型做了什么它把所有样本都预测成正常。于是 998 条预测正确准确率 99.8%。但这条模型一条欺诈都没抓出来。它和永远输出 0没有区别。准确率Accuracy之所以骗人是因为它把两类错误当成了一回事。而在真实业务里漏掉一个欺诈用户和误拦一个正常用户代价相差可能上千倍。所以判断模型好坏必须先搞清楚我要的到底是抓全还是抓准二、混淆矩阵一切指标的源头所有分类指标都来自一个 2×2 的表——混淆矩阵。以欺诈正例为例预测正常 预测欺诈 ┌───────────────────────┬───────────────────────┐ 真实 │ │ │ 正常 │ TN │ FP │ │ 真负例猜对了 │ 假正例误伤好人 │ ├───────────────────────┼───────────────────────┤ 真实 │ │ │ 欺诈 │ FN │ TP │ │ 假负例漏抓坏人 │ 真正例抓对了 │ └───────────────────────┴───────────────────────┘四个格子四种含义全部指标都由它们组合而成预测为正 预测为负 实际为正 TP FN 实际为负 FP TN理解了这四个字母剩下的指标都是小学除法。三、四个核心指标各自到底在衡量什么精确率 Precision TP / (TP FP) → 预测为欺诈的里面有多少是真欺诈挑得准不准 召回率 Recall TP / (TP FN) → 真实欺诈里有多少被抓出来抓得全不全 准确率 Accuracy (TP TN) / 总数 → 全部样本里预测对的比例最容易被分布带偏 F1 2PR / (P R) → Precision 与 Recall 的调和平均用一句话记住Precision 和 Recall 的取舍提高阈值模型更有把握才判正→ Precision ↑Recall ↓降低阈值稍微像就判正→ Recall ↑Precision ↓这个此消彼长的关系用代码跑一遍最直观。四、代码实战亲手复现99% 准确率的废模型importnumpyasnpfromsklearn.datasetsimportmake_classificationfromsklearn.model_selectionimporttrain_test_splitfromsklearn.linear_modelimportLogisticRegressionfromsklearn.metricsimport(confusion_matrix,classification_report,precision_score,recall_score,f1_score,roc_auc_score,roc_curve)fromsklearn.dummyimportDummyClassifier# 构造一份极度不平衡的数据正例只占 2%X,ymake_classification(n_samples10000,n_features20,n_informative8,weights[0.98,0.02],# 98% 负例2% 正例flip_y0.01,random_state42,)X_train,X_test,y_train,y_testtrain_test_split(X,y,test_size0.3,stratifyy,random_state42)print(测试集正例比例,f{y_test.mean():.3%})# ① 一个永远输出多数类的傻瓜模型dummyDummyClassifier(strategymost_frequent).fit(X_train,y_train)dummy_preddummy.predict(X_test)# ② 一个真正训练过的逻辑回归clfLogisticRegression(max_iter1000,class_weightbalanced).fit(X_train,y_train)predclf.predict(X_test)probclf.predict_proba(X_test)[:,1]forname,pin[(傻瓜模型,dummy_pred),(逻辑回归,pred)]:print(f\n{name})print(准确率 Accuracy :,round((py_test).mean(),4))print(精确率 Precision:,round(precision_score(y_test,p),4))print(召回率 Recall :,round(recall_score(y_test,p),4))print(F1 :,round(f1_score(y_test,p),4))典型输出测试集正例比例 2.233% 傻瓜模型 准确率 Accuracy : 0.9777 ← 看着很高 精确率 Precision: 0.0 ← 一个正的都没预测 召回率 Recall : 0.0 ← 一个正的都没抓到 F1 : 0.0 逻辑回归 准确率 Accuracy : 0.9023 ← 反而更低 精确率 Precision: 0.1737 召回率 Recall : 0.8507 ← 抓到了 85% 的欺诈 F1 : 0.2887结论一目了然傻瓜模型的准确率更高但它毫无价值。逻辑回归准确率低了 7 个百分点却抓出了 85% 的欺诈样本。这就是为什么在不平衡数据上只看 Accuracy 等于自欺欺人。五、ROC-AUC跨阈值衡量模型的排序能力前面几个指标都需要先定一个阈值。但阈值是我们人为选的不同阈值下指标会变。有没有一个指标能描述模型本身的排序能力有就是AUC。它衡量的是随机抽一个正例和一个负例模型给正例打的分比负例高的概率。AUC 0.5 表示瞎猜AUC 1.0 表示完美排序。fromsklearn.metricsimportroc_curveimportmatplotlib.pyplotasplt aucroc_auc_score(y_test,prob)fpr,tpr,thresholdsroc_curve(y_test,prob)print(f逻辑回归 ROC-AUC {auc:.4f})# 找一个业务可接受的阈值要求召回 ≥ 0.9取精确率最高者masktpr0.90best_idxnp.argmax(precision_score(y_test,(probthresholds[mask][0]))ifFalseelse-fpr[mask])thrthresholds[mask][best_idx]pred_at_thr(probthr).astype(int)print(f阈值{thr:.3f}时 → P{precision_score(y_test,pred_at_thr):.3f}fR{recall_score(y_test,pred_at_thr):.3f})plt.plot(fpr,tpr,labelfAUC {auc:.3f})plt.plot([0,1],[0,1],k--,label随机猜测)plt.xlabel(False Positive Rate);plt.ylabel(True Positive Rate)plt.legend();plt.title(ROC Curve)plt.show()AUC 最大的好处是阈值无关模型上线前用它比较不同模型的排序能力上线后再根据业务成本去调阈值。这一步解耦非常关键——模型选型看 AUC线上决策看阈值。六、指标对比与选型表指标计算口径适用场景何时会骗你Accuracy预测对的 / 总数类别均衡且两类错误代价相当类别极度不平衡时PrecisionTP/(TPFP)误报代价高垃圾邮件拦截、推荐系统只关心准、不在意漏RecallTP/(TPFN)漏报代价高疾病筛查、欺诈检测只关心全、不在意误伤F1P、R 调和平均需要 P/R 平衡的单一指标对 P/R 具体取舍不可控ROC-AUC排序能力模型选型、阈值无关比较正例极少时仍偏乐观PR-AUCP-R 曲线面积极度不平衡正例 1%计算成本略高特别提醒一个容易被忽略的点当正例比例极低比如万分之一时ROC-AUC 依然可能很高因为它主要受负例数量的影响。这种情况下应该改用PR-AUC平均精确率 AP它对正例更敏感更能反映实际业务效果。七、几个常见的坑坑 1用 Accuracy 汇报不平衡数据的结果。这是最经典的错误。只要正例占比低于 10%就应该同时汇报 Precision / Recall / F1 / AUC只报 Accuracy 会被内行一眼看穿。坑 2在训练集上算指标。训练集指标永远好看。所有评估必须在划分出来的测试集或交叉验证的验证折上做。坑 3先过采样再划分数据集。如果先 SMOTE 再train_test_split同一份样本的合成副本会同时进入训练集和测试集造成数据泄漏指标虚高。正确顺序先划分只在训练集上做过采样。坑 4默认阈值 0.5。predict()默认用 0.5 做阈值但 0.5 只对两类错误代价相同成立。风控、医疗场景必须用predict_proba手动扫阈值找到业务最优点。坑 5混淆class_weight和过采样。两者都能缓解不平衡但class_weightbalanced只是加权损失不改变样本数量开销更小过采样会真的增加样本量。数据量小时优先用class_weight。八、小结记住这条决策链评估指标就不会选错首先问数据平衡吗 ├─ 平衡 → Accuracy 可用配合 AUC 一起看 └─ 不平衡 ├─ 更怕漏召回优先 → 看 Recall / PR-AUC ├─ 更怕误伤精确优先→ 看 Precision └─ 两者都要平衡 → 看 F1 / ROC-AUC指标不是越高越好而是和业务成本对得上才好。一个 90% 召回、20% 精确率的模型对欺诈检测可能非常划算同样这个模型放到垃圾邮件拦截就会因为误杀大量正常邮件而被投诉到下架。选指标本质是在选你要承担哪种错误。