问题与目标

PR 曲线观察所有候选阈值的排序表现,混淆矩阵则描述一个具体阈值下的四类结果。
同一模型用不同指标可能得到相反判断。评估必须从错误代价和类别分布出发,而不是默认选择准确率。
完成标准:根据混淆矩阵解释精确率、召回率和 F1,比较 ROC-AUC 与 PR-AUC,并在验证集选择阈值。
核心概念
混淆矩阵包含真正、假正、假负和真负。精确率回答“预测为正的有多少正确”,召回率回答“真实正类找回多少”,F1 是两者调和平均。类别极不平衡时,PR 曲线通常比准确率更能反映正类识别质量。
ROC-AUC 衡量正样本排序在负样本之前的能力;平均精确率概括 PR 曲线。AUC 不给出具体决策点,最终仍要按错误成本选阈值。
回归常用 MAE、RMSE 和 R²,还应按业务分组查看误差,避免总体均值掩盖局部失败。
从混淆矩阵推导指标
| 实际/预测 | 预测负 | 预测正 |
|---|---|---|
| 实际负 | TN | FP |
| 实际正 | FN | TP |
- 精确率
TP/(TP+FP):报警中多少是真的。 - 召回率
TP/(TP+FN):真实风险找回多少。 - 特异度
TN/(TN+FP):负类正确排除多少。 - F1:精确率和召回率的调和平均。
F1 不考虑 TN,在正类关注度高时有用,但不能表达所有业务成本。若一次漏报成本是误报的十倍,可以直接计算不同阈值下的期望成本。
多分类平均方式
Macro 对每个类别指标等权平均,能暴露小类别问题;Weighted 按类别样本数加权,可能被大类别主导;Micro 先汇总所有类别的 TP/FP/FN。报告时说明平均方式,不能只写“F1”。
ROC 与 PR 曲线
ROC 曲线横轴是假正率、纵轴是真正率;PR 曲线横轴召回、纵轴精确率。正类稀少时,即使假正率很低,也可能产生大量误报,因此 PR 曲线更直观。
from sklearn.metrics import precision_recall_curve
precision, recall, thresholds = precision_recall_curve(y_true, scores)
for index in range(0, len(thresholds), max(1, len(thresholds) // 5)):
print(
round(float(thresholds[index]), 3),
round(float(precision[index]), 3),
round(float(recall[index]), 3),
)
曲线用于验证集选择工作点;最终测试集只报告选定阈值结果。
可运行实现
import numpy as np
from sklearn.metrics import (
average_precision_score, confusion_matrix, f1_score,
precision_score, recall_score, roc_auc_score,
)
y_true = np.array([0] * 90 + [1] * 10)
scores = np.concatenate([
np.linspace(0.01, 0.65, 90),
np.array([0.18, 0.31, 0.44, 0.52, 0.58, 0.66, 0.73, 0.81, 0.9, 0.96]),
])
print("ROC-AUC:", round(roc_auc_score(y_true, scores), 3))
print("PR-AUC:", round(average_precision_score(y_true, scores), 3))
for threshold in (0.3, 0.5, 0.7):
prediction = (scores >= threshold).astype(int)
print(threshold, confusion_matrix(y_true, prediction).tolist())
print(
"precision", round(precision_score(y_true, prediction), 3),
"recall", round(recall_score(y_true, prediction), 3),
"f1", round(f1_score(y_true, prediction), 3),
)
输入含 10% 正类及连续得分,输出显示阈值变化如何移动误报与漏报。实际阈值不能在最终测试集上挑选。
总体指标之外的稳定性
按时间、数据来源、任务类型和输入规模分群评估,可以发现总体平均掩盖的失败。小分群指标波动很大,应同时报告样本数,并通过重采样置信区间或多次切分观察不确定性。
模型更新前后必须使用相同数据和口径对比。若测试集本身变化,分数提升可能来自样本变简单,而不是模型改善。
用自助重采表达指标不确定性
测试集指标是有限样本上的估计,小分组尤其不稳定。自助重采可反复有放回抽样,得到一个经验波动范围:
rng = np.random.default_rng(42)
bootstrap_f1 = []
prediction = (scores >= 0.5).astype(int)
for _ in range(1000):
indices = rng.integers(0, len(y_true), len(y_true))
if np.unique(y_true[indices]).size < 2:
continue
bootstrap_f1.append(f1_score(y_true[indices], prediction[indices]))
lower, upper = np.quantile(bootstrap_f1, [0.025, 0.975])
print("F1 interval:", round(float(lower), 3), round(float(upper), 3))
这个区间依赖样本独立同分布等假设。对时间序列或同一主体的重复记录,应按时间块或主体分组重采,否则区间会过于乐观。
一份完整评估报告
至少包含:正类定义、样本时间范围、类别占比、基线、排序指标、已锁定阈值、混淆矩阵、分组指标、不确定性和典型错误样本。报告数字同时保留计算脚本,避免手工复制造成口径偏差。
进一步验证
- 由混淆矩阵手算精确率、召回率、特异度和 F1,再与库函数核对。
- 在验证集选定阈值后锁定,只在测试集报告一次对应结果。
- 按两个关键群体报告指标与样本数,对小样本结果附上不确定性说明。
常见问题与排查
- 准确率 90% 就认为很好:全预测负类也可能达到 90%。
- 把 AUC 当准确率:AUC 衡量排序,不对应某个阈值的正确比例。
- 多次查看测试集:测试集逐渐变成验证集。
- 只报告总体指标:按时间、来源和关键群体切片检查稳定性。
小结
评估的核心是把模型错误映射到实际代价。指标负责描述表现,阈值负责形成决策,二者都需要独立数据和明确口径。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


