🧠 第九章 模型评估和优化
📄 一句话概括

200 个正类、800 个负类,扫完所有阈值画出的 ROC 曲线 AUC 是 0.7984,随机猜是 0.5000。 TPR 减 FPR 的最大值 0.483(KS 统计量)出现在阈值 0.5 附近。

📝 本节和前面几节的关系

上一节的精确率、召回率都依赖阈值。 这一节讲一个不看阈值的工具:把阈值从头扫到尾,把结果画成一条曲线。

一、ROC 怎么画

两个轴:横轴是 FPR(负类里被误判为正的比例),纵轴是 TPR(也就是召回率,正类里被抓到的比例)。 画法:把阈值从高到低扫一遍。阈值极高时一个都不判正,点在 (0, 0);阈值极低时全判正,点在 (1, 1)。 中间每调一次得到一个点,连起来就是曲线。 左上角 (0, 1) 是理想点:一个误报都没有,全都抓到了。曲线越靠近左上角越好。 曲线下的面积就是 AUC。0.5 是瞎猜(对角线),1.0 是完美。

二、实测:AUC 0.7984

Demo 造了 200 个正类(打分均值 1)和 800 个负类(均值 0),标准差都是 1。 两类有重叠,所以不可能是完美分类器。 扫完所有阈值,AUC 算出来是 0.7984。 AUC 的含义很好记:随机抽一个正样本和一个负样本,模型给正样本打分更高的概率。 0.7984 就是「八成的概率能排对」。 表里给了六个阈值的具体值。 可以看到 TPR 和 FPR 一起涨,但 TPR 涨得更快——这就是模型有区分能力的意思。 TPR 减 FPR 的最大值是 0.483,出现在阈值 0.5 附近。 这个差叫 KS 统计量,它对应的阈值常被当成「最佳切点」。

三、AUC 的好处和坑

好处:和阈值无关。换阈值只是在曲线上挪位置,不改面积。 所以它可以用来比较「模型本身的能力」,不用先定阈值。 好处二:不受类别比例影响(严格说是不受先验影响)。 同一个模型在 1:1 和 1:100 的数据上,AUC 差不多。 坑:正因为不受比例影响,类别极不平衡时它会虚高。 FPR 的分母是负类总数,负类有 800 个,误报几十个 FPR 也涨不了多少,曲线看着还是很漂亮。 这时要看 PR 曲线(精确率对召回率)。PR 曲线的基线是正类占比——这里正类只占 20%,基线就是 0.20。 一眼能看出模型到底比瞎猜好多少。 实践中两个都算、两个都报。只看 AUC 会在不平衡数据上自我感觉良好。

四、训练师该怎么用这两个曲线

选模型:AUC 高的通常更好,但要确认两个模型的适用场景一致。 如果两个模型 AUC 差不多,看 PR 曲线——业务关心的是「抓出来的对不对」,那 PR 更贴近。 定阈值:别看曲线,看业务约束。 比如「误报率不超过 5%」,就在 FPR 等于 0.05 的那一列往上找 TPR 最高的点。 汇报:AUC 一个数就够(好解释),但必须补一句「正类占比多少」。不写这个,AUC 的含义会被误解。 排查:如果 AUC 只有 0.5 到 0.6,先别调模型,去看特征是不是漏了关键信息。 0.5 附近的 AUC 通常意味着「模型看到的东西和标签没关系」。

五、动手 Demo:ROC 与 AUC:扫完所有阈值,面积 0.7984

造 200 个正类和 800 个负类的打分(正类均值 1、负类均值 0,标准差都是 1); 按打分从高到低排序,逐步累积真正例和假正例,得到整条 ROC 曲线; 用梯形法算曲线下面积,并列出六个阈值上的 TPR、FPR 和两者之差。

order = np.argsort(-sc)
ysort = y[order]
tp = np.cumsum(ysort)
fp = np.cumsum(1 - ysort)
tpr = np.concatenate([[0.0], tp / float(n_pos)])
fpr = np.concatenate([[0.0], fp / float(n_neg)])
auc = float(np.trapezoid(tpr, fpr))

实跑输出:

--------------------------------------------------------------------
ROC 曲线:把所有阈值扫一遍画成一条线
--------------------------------------------------------------------
  样本                     正类 200 个、负类 800 个
  打分                     正类 ~ N(1, 1),负类 ~ N(0, 1)

  沿着打分从高到低扫,每个位置算一次「抓到的正类比例」和「误报的负类比例」,画出来就是 ROC 曲线。曲线下的面积就是 AUC。
  阈值   TPR(召回)   FPR(误报率)   TPR 减 FPR
  ----------------------------------------------
   2.0         0.175           0.020        0.155
   1.5         0.325           0.059        0.266
   1.0         0.550           0.144        0.406
   0.5         0.710           0.285        0.425
   0.0         0.875           0.480        0.395
  -1.0         0.980           0.829        0.151

  这条曲线的 AUC           0.7984
  随机猜的 AUC             0.5000
  完美分类器的 AUC         1.0000
  TPR 减 FPR 最大处        0.483(这是 KS 统计量,也是常用阈值)

  AUC 的含义是「随机抽一个正样本和一个负样本,正样本打分更高的概率」。所以 0.5 是瞎猜,1.0 是完美。实测 **0.7984**,说明这个模型有明显区分能力,但离完美还远。
  AUC 有个好性质:它和阈值无关。换阈值只会在曲线上挪位置,不改面积。所以它可以用来比较「模型本身的能力」,不用先定阈值。
  它也有个坑:类别极不平衡时 AUC 会虚高。因为 FPR 的分母是负类总数,负类有 800 个,误报几十个 FPR 也涨不了多少。
  这种情况下要看 PR 曲线(精确率对召回率)。PR 曲线的基线是正类占比,这里正类只占 20%,基线就是 0.20,一眼能看出模型到底比瞎猜好多少。
  实践中的做法:两个都算,两个都报。只看 AUC 会在不平衡数据上自我感觉良好。

AUC 0.7984。这个数比 0.5 高得多,说明模型有明确区分能力; 但离 1.0 还远,因为两类分布重叠得厉害。 表里阈值 0.5 那行:TPR 0.710、FPR 0.285,差 0.425。阈值 1.0 那行差 0.406。 两者接近,说明 0.5 到 1.0 这个区间切点都不错。 KS 最大值 0.483 落在阈值 0.5 附近。 这个位置是「TPR 领先 FPR 最多」的地方,常被当成最佳切点——但它只考虑排序能力,不考虑业务代价。 正类只占 20%,AUC 0.7984 看着不错。 但如果算 PR 曲线,基线是 0.20,模型在召回 0.7 时精确率只有 0.5 左右——提升空间比 AUC 暗示的小。 这就是「AUC 虚高」的具体表现。

30 秒实验

  1. 把正类的打分均值从 1 改成 2,看 AUC 涨到多少。
  2. 把负类数量从 800 改成 200(正负 1:1),看 AUC 变不变——想想为什么。
  3. 想一想:AUC 0.8 的模型,在正类只占 1% 的数据上,实际能用吗?

常见误区

  1. 「AUC 高就一定好」——不平衡数据上它虚高,得配合 PR 曲线看。
  2. 「AUC 可以用来定阈值」——它和阈值无关,定阈值要回到 PR 表或代价分析。
  3. 「AUC 0.5 是随机,所以 0.55 也差不多」——0.55 确实很弱,但方向是对的。
自测三问(点开对答案) 1. ROC 曲线的两个轴是什么? —— 横轴是 FPR(负类被误判为正的比例),纵轴是 TPR(也就是召回率)。 2. AUC 的直观含义是什么? —— 随机抽一个正样本和一个负样本,模型给正样本打分更高的概率。 3. 为什么不平衡数据上 AUC 会虚高? —— FPR 的分母是负类总数,负类多时误报几十个 FPR 也涨不了多少,曲线看起来仍然漂亮。

五个指标讲完了。下一节开始讲优化:怎么用验证集判断模型是不是真的学到了东西。

相关笔记