Refactor AUC evaluation scripts to support model target modes and improve distribution handling

This commit is contained in:
2026-06-12 11:33:32 +08:00
parent 0fa8bbbb9a
commit 3125b6119f
3 changed files with 378 additions and 119 deletions

View File

@@ -261,11 +261,17 @@ python train.py --extra_info_types_file extra_info_types_smoking_alcohol_bmi.txt
`evaluate_auc.py` 评估的是 **next-step / token-level 预测位置上的疾病 AUC**。
查询方式由 `train_config.json` 中的 `model_target_mode` 决定:
- `model_target_mode="next_token"`:使用训练 readout 对应的历史 token hidden 作为预测点。
- `model_target_mode="all_future"`:不使用 readout token直接把每个预测点年龄作为 `t_query` 传入模型,取 query hidden 作为预测点。
核心流程:
- 按训练配置重新构建 `HealthDataset` 和 `DeepHealth`。
- 对评估 split 中的患者做一次模型推理,缓存每个 disease-token readout hidden。
- 对评估 split 中的患者做模型推理,缓存每个预测点的 hidden。
- 对疾病 token 分块投影到 `risk_head`,避免一次性保存全词表 logits。
- AUC score 使用疾病对应的 eta/logit 排序分数;`dist_mode` 只用于正确构建模型,不会把分数转换成 horizon-specific risk probability。
- 对每个疾病、性别、年龄段、prediction offset 分别计算 AUC。
- 输出未池化分层结果和按疾病汇总后的结果。
@@ -294,13 +300,20 @@ python evaluate_auc.py \
`evaluate_auc_v2.py` 评估的是 **landmark fixed-horizon incident disease AUC**。
它不是使用已有序列中的普通 readout 位置,而是在指定 landmark age 人工插入一个 `<NO_EVENT>` query token,然后评估该 landmark 后固定 horizon 内是否发生 incident disease。
它不是使用已有序列中的普通 readout 位置,而是在指定 landmark age 构造一个 landmark query,然后评估该 landmark 后固定 horizon 内是否发生 incident disease。
查询方式由 `train_config.json` 中的 `model_target_mode` 决定:
- `model_target_mode="next_token"`:在 landmark age 人工插入一个 `<NO_EVENT>` token取该 token 的 hidden 做风险分数。
- `model_target_mode="all_future"`:不插入 `<NO_EVENT>`,直接把 landmark age 作为 `t_query` 传入模型,取 query hidden 做风险分数。
核心流程:
- 为每个患者和 landmark age 构造 landmark query 样本。
- 在 landmark age 插入 `<NO_EVENT>` token,取该位置 hidden。
- 对疾病 token 分块投影到 `risk_head`。
- 根据模型模式插入 `<NO_EVENT>` token 或直接传 `t_query`,取 landmark/query hidden。
- 对疾病 token 分块投影到 `risk_head``score_mode="risk"` 时会根据 `dist_mode` 把线性输出转换为固定 horizon 风险概率
- 分布转换规则与 all-future 训练损失一致:`exponential` 使用 `1 - exp(-rate * horizon)``weibull` 使用 `1 - exp(-rate * horizon ** rho)``mixed` 中普通疾病使用 exponential死亡 endpoint 使用 Weibull death rho。
- `score_mode="eta"` 是诊断用排序分数,不使用 `rho`,因此不区分不同分布的风险曲线。
- 按疾病、性别、landmark age、horizon 计算 incident disease AUC。
- 可选择排除 horizon 内先于目标疾病发生的死亡竞争风险。
@@ -333,8 +346,9 @@ python evaluate_auc_v2.py \
| 项目 | `evaluate_auc.py` | `evaluate_auc_v2.py` |
| --- | --- | --- |
| 评估口径 | next-step/token-level 预测点 | landmark fixed-horizon incident risk |
| 查询位置 | 原始序列中满足 offset 条件的最新 readout token | 人工插入的 `<NO_EVENT>` landmark token |
| 查询位置 | next-token 用满足 offset 条件的最新 readout tokenall-future 直接用该预测点年龄作为 `t_query` | next-token 用人工插入的 `<NO_EVENT>` landmark tokenall-future 直接用 `t_query` |
| 时间参数 | `offsets`:预测点至少早于目标事件多少年 | `landmark_*` 和 `horizons`:固定年龄点与未来窗口 |
| score 与分布 | 使用 eta/logit 排序分数;不按 `dist_mode` 转换风险概率 | `score_mode="risk"` 按 `dist_mode` 区分 exponential / Weibull / mixed`score_mode="eta"` 不区分分布 |
| 病例定义 | target table 中出现目标疾病的患者/事件 | landmark 后 horizon 内首次发生目标疾病 |
| 对照定义 | 从未出现该疾病的患者的 eligible target occurrence | landmark 时未患病,且 horizon 内未发病并有足够随访 |
| 分层 | sex + age bracket + offset | sex + landmark age + horizon |
@@ -380,7 +394,11 @@ python evaluate_auc_v2.py \
- `evaluate_auc.py`
- next-step/token-level 疾病 AUC 评估
- 使用 prediction offset、sex、age bracket 分层
- next-token 模型使用 readout hiddenall-future 模型使用 `t_query` hidden
- score 是疾病 eta/logit不按分布转换为固定 horizon 风险概率
- `evaluate_auc_v2.py`
- landmark fixed-horizon incident disease AUC 评估
- 通过插入 `<NO_EVENT>` landmark token 查询固定年龄点风险
- next-token 模型通过插入 `<NO_EVENT>` landmark token 查询固定年龄点风险
- all-future 模型直接通过 `t_query` 查询固定年龄点风险
- `score_mode="risk"` 按 exponential / Weibull / mixed 分布计算固定 horizon 风险