1. 指标必须回答业务问题
1000 笔交易只有 10 笔欺诈,模型全部判正常,准确率仍有 99%。这个数字没有算错,问题是它没有表达“抓住欺诈”这个目标。
指标是观察结果的不同窗口。先确定正类是什么、漏报和误报的代价是什么,再选指标。
2. 混淆矩阵:先数清四个格子
以欺诈为正类:
| 实际欺诈 | 实际正常 | |
|---|---|---|
| 预测欺诈 | TP=8 | FP=12 |
| 预测正常 | FN=2 | TN=978 |
TP 是真正例,FP 是假正例,FN 是假反例,TN 是真反例。名字容易绕,可以先记“预测是不是正类”和“预测对不对”,再落回格子。
总数 :
Precision(精确率)问:拦下来的交易里,有多少真是欺诈?
Recall(召回率)问:所有欺诈交易里,抓住了多少?
F1 是精确率与召回率的调和平均,对较低的一项敏感。它仍然没有直接包含每笔钱的损失、审核成本或误拦代价。
3. 阈值、ROC 与 PR 曲线
假设模型输出欺诈分数。阈值降得更低,通常会拦更多交易,同时增加 TP 和 FP。不存在脱离业务代价的最佳阈值。
ROC 横轴是假正例率 ,纵轴是真正例率,也就是 Recall。AUC 汇总曲线下的面积;在二分类常见口径中,可理解为随机抽一个正例、一个负例,正例分数更高的概率,并对并列作适当处理。
PR 曲线直接看 Precision 与 Recall。极不平衡问题里,大量负例可能让 ROC 的假正例率看起来很小,而 PR 更直观地暴露人工审核的噪声。
PR-AUC 与 Average Precision 不是所有实现里都同一个计算方式。 报告时应写明具体指标和实现,不能只说“AUC=0.9”而不说明是哪条曲线。
多分类还要区分:
- Macro:各类指标先分别计算,再等权平均,较关注小类别。
- Weighted:按类别样本数加权,大类影响更大。
- Micro:先汇总各类计数,再计算,整体规模影响更大。
指标定义与实现细节可查 scikit-learn 模型评估文档。
4. 回归:测量差了多少
假设真实值为 ,预测为 ,误差是 。
MAE 是平均绝对误差,与原目标同单位。例如目标是万元,MAE 也是万元。
MSE 的单位被平方,RMSE 又变回原单位。平方操作使大误差受到更重惩罚。
比较模型与“总是预测真实值均值”的基准。可以为负,表示还不如该基准;真实值全相同时分母为 0,需特别处理,前面的三个样本恰好不能直接套这个公式。
MAPE 用真实值作分母,目标接近 0 时会特别不稳定。销量含 0 的场景,不能不加检查就使用它。
5. 排序:用户先看到的内容好不好
知识库检索返回文档,用户通常只看前几条。设唯一正确文档在第 3 名:
- Hit@3=1:前三条中命中了。
- Reciprocal Rank=:第一次命中的排名越靠前,得分越高。
- MRR:对多次查询的 Reciprocal Rank 求平均;没命中通常记 0。
如果一个问题有多个相关文档,Recall@K 是前 K 条找到了多少相关文档,占全部相关文档多少。它要求我们知道或近似标注相关集合。
NDCG 还允许“高度相关、部分相关、不相关”:
是第 名的相关性等级。越靠前折扣越小,高相关内容排前面贡献更大。用理想排序得到 IDCG,再令 NDCG=DCG/IDCG,就能相对理想顺序比较。没有任何相关内容时需要约定得分口径。
“搜索结果相关”与“能从中回答问题”也不同。一段主题相关但缺少关键条款的文字,可能检索看似不错,却不足以支撑回答。
6. 80% 比 78% 高,能不能说更好
如果测试集只有 200 题,80% 表示答对 160 题,78% 表示 156 题,差 4 题。一次测试的随机波动可能就有这个规模。
在题目近似独立、简单二项抽样的教学假设下,比例的标准误差近似为:
取 ,,即 2.83 个百分点。正态近似的 95% 区间宽度约为 ,即 个百分点。实际分析可以使用更稳妥的 Wilson 区间或适合任务的其他方法。
这不是两个模型差异的检验公式。 同一批题测试两个模型时,应该保留每题配对结果,检查 A 对 B 错、A 错 B 对的数量,或采用配对 bootstrap 等方法。两个模型在同样的题上共同出错,和各错不同题,对比较的影响不同。
不要把“200 题差两点一律无效”当定理;可靠性还受任务、样本相关性、配对结果和检验设计影响。
7. 用代码把计数与分数连起来
from math import sqrt
tp, fp, fn, tn = 8, 12, 2, 978
precision = tp / (tp + fp)
recall = tp / (tp + fn)
f1 = 2 * precision * recall / (precision + recall)
accuracy = (tp + tn) / (tp + fp + fn + tn)
print(f"accuracy={accuracy:.3f}, P={precision:.3f}, R={recall:.3f}, F1={f1:.3f}")
# accuracy=0.986, P=0.400, R=0.800, F1=0.533
p, n = 0.8, 200
se = sqrt(p * (1 - p) / n)
print(f"教学近似:SE={se:.4f},区间半宽={1.96 * se:.4f}")
# 教学近似:SE=0.0283,区间半宽=0.0554
这段数据的分母都大于 0。通用实现还需要处理“没有预测正例”等零分母情况,并说明约定,而不是静默报一个看似正常的数字。
8. 写结果时至少记录什么
同时记录任务定义、正类含义、数据来源与时间、样本量、划分方式、指标口径、阈值、模型与配置版本,以及失败样本。
若从几十次实验中只挑最高分报告,还要考虑反复挑选造成的乐观偏差。保存实验日志,比背一个高分更有用。
复习卡片与自测
- Precision 看预测正例,Recall 看真实正例。
- 回归指标先看单位与异常值敏感性。
- 排序指标关注前几条、首次命中和相关性等级。
- 分数差异要结合样本量与配对结果判断。
1. 召回率从 80% 提高到 100%,一定更好吗?
参考答案
不一定。若把所有交易都拦下,召回率为 100%,但误拦和审核成本可能无法接受。2. RMSE=20 与 MSE=400 为什么不矛盾?
参考答案
RMSE 是 MSE 的平方根,单位不同,20²=400。3. 比较两个模型,为什么要保存每道题的结果?