跳到主要内容

05 模型评估

04 章训出了 4 个分类器。这一章讲怎么"公平评估" — 不只是看 Accuracy,而是 5 个诊断视角组合起来。05 + 04 在 ml-classifier 工具里是同一份输出,本章给你读懂工具输出的报告所需的全部背景。

5 个诊断视角

视角关键指标回答的问题论文必报?
判别力ROC AUC模型区分两类的整体能力
不平衡敏感PR AUC(AUPR)类不平衡时的真实性能✓(类比例 < 1:5)
概率可靠性Calibration(Brier / 校准曲线)模型说 "70% 概率患癌" 是不是真的 70%✓(临床预测模型)
临床决策DCA(Net Benefit)用模型 vs 不用模型的净获益✓(临床预测模型)
不确定性Bootstrap 95% CI性能数字的置信区间

光报 Accuracy 在生信论文里几乎不被接受。ROC 是最低标配,临床预测模型必加 Calibration + DCA

ROC vs PR — 哪个该看

ROC 横轴 FPR 纵轴 TPR,对类比例不敏感(改变正负样本比例,ROC 几乎不变)。这听起来好,实际是缺点 — 在 1:100 极度不平衡时,ROC 仍可能 0.95,但实际 PR-AUC 可能只有 0.3,模型在精确率上很差。

类比例看哪个
1:1 - 1:5ROC 即可,PR 作为辅助
1:5 - 1:20同时报 ROC + PR
< 1:20PR 更重要,ROC 会过度乐观

ml-classifier 工具默认两图都出。看 PR 曲线时记得 baseline = 测试集正例占比,位于基线之上 = 比随机预测好

Calibration — 临床决策的命门

ROC AUC = 0.95 的模型能用吗?不一定。如果模型把所有"高风险"病人的预测概率都给到 0.6 而不是真实的 0.95,医生看到 60% 的数字可能就不开始干预了。这就是 Calibration(校准)的问题。

校准曲线把样本按预测概率分箱(10 bins),每箱算实际正例比例,画在对角线上对比:

  • 完美校准:所有点在对角线上
  • 过度自信:高概率区点低于对角线(预测 90% 但实际只有 70% 是正例)
  • 过度保守:相反方向

实务约定:

library(rms)
val.prob(prob_test, y_test, m = 30) # m = 每个箱最少样本

或者直接报 Brier score:

Brier = (1/n) Σ(p_i - y_i)²

Brier 越小越好,完美预测 = 0,随机猜测 ≈ 0.25(50% prevalence)。临床论文里 Brier < 0.2 是底线。

DCA — 临床预测模型的"漂亮度"

ROC、Calibration 都告诉你 "模型本身好不好",DCA 告诉你 "用模型 vs 不用模型,病人能多救多少"。

横轴 = 阈值概率(超过这个概率就干预),纵轴 = 净获益(true positives 干预获益 - false positives 误干预成本)。三条曲线对比:

  • 模型曲线:用模型决定干预的获益
  • Treat all:无脑全干预
  • Treat none:全不干预

模型曲线高于灰色基线 = 临床有用。如果模型曲线在所有阈值下都不如 "Treat all" 或 "Treat none",这个模型在临床上没价值,即使 AUC = 0.99。

library(dcurves)
dca(Surv(time, status) ~ pred_model, data = df) |> plot()

ml-classifier 工具的 04-dca.png 就是这个。

5-fold CV + Bootstrap CI — 不确定性量化

单次跑出 AUC = 0.85 不够 — 下次跑可能是 0.79。两个互补技巧:

5-fold CV(训练时)

把 train set 切 5 份,轮流当 fold,得 5 个 fold-level AUC,取平均 + 标准差。caret::train(method = "cv", number = 5) 自动做。

Bootstrap 95% CI(测试时)

在 test 集上 bootstrap N 次(默认 N = 200),每次抽 N 个有放回样本,计算性能,得性能分布。95% CI = 2.5 / 97.5 分位数

library(pROC)
roc_obj <- roc(y_test, prob_test)
ci.auc(roc_obj, method = "bootstrap", boot.n = 200, conf.level = 0.95)

ml-classifier 工具的 08-bootstrap-auc-forest.png 把 4 算法的 CI 画在一张森林图,CI 不重叠 → 算法间差异显著

DeLong 检验 — 两个 AUC 差异是否显著

经常被问:"我的模型 AUC 0.85 比对照的 0.82 高,显著吗?" 用 DeLong:

roc.test(roc_a, roc_b, method = "delong")

p < 0.05 才能说"显著高于对照"。

Accuracy 的三大陷阱

不平衡数据假阳性 — 9:1 不平衡,全猜多数类 Acc = 90%,模型零价值

阈值漂移 — Accuracy 隐含 0.5 阈值;改成 0.3 / 0.7 整个数字变。报 AUC / PR-AUC 才是阈值无关的

不同人群比较 — A 数据集 Acc 85%,B 数据集 Acc 80%,不能说 A 模型更好(可能 B 数据集本身更难)

常见坑

train 集报性能 — 几乎是过拟合的"漂亮幻觉"。永远报 CV 平均 + test 集独立验证

没固定 seed 导致结果不可复现set.seed(42)train() 之前

类不平衡用 over-sampling 后再算 ROC — 这会把 ROC 算高,但本质是评估失真。不平衡处理在训练阶段做,评估永远在原始 test 比例上

混淆矩阵忘报 Sensitivity / Specificity — 阈值固定后两者一定要报。临床更看重 Sensitivity(避免漏诊),筛查更看重 Specificity(避免假阳性导致过度治疗)

拿 5-fold CV AUC 当 test AUC 报 — CV 是训练阶段的调参指标,test AUC 是终验,两者要分别报

pROC 算 95% CI 用了 method='delong' 在小样本 — DeLong 假设大样本,< 50 样本用 bootstrap 更稳

Methods 段写法模板

We trained four classifiers (LR via glmnet, SVM with RBF kernel via e1071,
Random Forest with 500 trees, XGBoost with default hyperparameters) using
caret v6.0 with 5-fold cross-validation on the training set (n = 105) for
hyperparameter selection. Final models were evaluated on a held-out test set
(n = 45). Performance metrics included AUROC (95% CI by DeLong), AUPR,
calibration (Brier score and 10-bin calibration curve via rms::val.prob),
and decision curve analysis (dcurves package). Bootstrap (n = 200) was used
to compute confidence intervals for AUROC differences across algorithms.

把这段直接拷贝到投稿,把数字替换上来即可。

在线工具

ml-classifier

ml-classifier 工具的输出报告 完整覆盖本章 5 个评估视角(8 张 SCI 双格式图)。教程 + 工具是 1:1 配套的。

本章状态

✅ Wave 4 正文完成(2026-05-27)。配套 ml05_eval_sci.R 在产(实际功能并入 ml04_classify 脚本)。

AI 陪学

让 AI 陪我学这一篇

AI 会读这篇文章后给你 3-5 步学习计划, 逐步陪你学完,最后出 1-3 道题验证你掌握得怎么样。 登录后 AI 才能记住你的进度。

静态文件

离线资料下载

手册 HTML / PDF 已在后台预生成,点击后直接下载网站静态资源。