目前回归模型和分类模型目前现状(Claude总结)
回归模型:
一、整套流程总结(从原始数据到最终评估)
1. 数据加载与缺失值审计
读取 dataset_30%.csv,用 audit_missing_values 函数统计每个字段的缺失数量、缺失率、均值、中位数,只打印有缺失的列,做了一次基础的数据质量体检,但这一步只是"审计/打印报告",没有做任何插补处理。
2. 特征工程函数(V2 衍生特征)—— 当前处于禁用状态
generate_v2_enhanced_features 这个函数原本设计用来基于 5 项临床核心指标衍生新特征:胎儿体积估算 Fetal_Vol(AC²×FL/1000)、头腹围比 HC_AC_Ratio、代谢协同效应 Metabolic_Synergy(PPBMI×GWG)、宫高增长率 FH_GA_Rate(FH/GA)、BMI 变化幅度 BMI_Shift(PNBMI−PPBMI)。但你贴出来的版本里,这 5 段计算逻辑全部被注释掉了,函数实际只做了 df.copy(),等于什么也没生成。
3. 特征稳健化截断函数 —— 当前同样处于禁用状态
robust_feature_clipping 原本设计是对指定列做 1%~99% 分位数截断来平滑极端值,但 cols_to_fix 列表是空的,且截断逻辑也被注释掉了,函数同样只返回原数据的拷贝,没有做任何截断。
4. 切分数据集
对(实际上没经过任何衍生和截断的)原始特征做了一次列名特殊字符清洗(替换 []{}:, 为下划线),按 8:2 切出训练/测试集。
5. Stage 1:路由器(Router)训练
用 LightGBM + XGBoost + CatBoost 做 Stacking(Huber 作为元学习器),在训练集上拟合,同时用 5 折 cross_val_predict 得到训练集的 OOF 预测值,再用这批预测值的 15% 和 75% 分位数,把训练样本自适应地切成"低体重 / 正常 / 高体重(巨大儿)"三组。
6. Stage 2:专家集群训练
- 低体重组、高体重组各训练一个 LightGBM,损失函数是自定义非对称损失(残差正负惩罚力度不同),用 Optuna 同时搜索树超参数和非对称惩罚系数 omega(低组 1.2
5.0,高组 2.06.0),目标是 MAE + 0.5×组内偏倚,搜 30 轮后取最优参数重新训练最终专家。 - 正常体重组维持三模型 Stacking集成。
7. 推理 测试集先过 router_model 得到初始预测值,按落在哪个分位数区间分发给对应专家,得到最终预测。
8. 评估与可视化
计算 MAE / RMSE / R² / MAPE、±10% 临床准确率、误差 <=250g 命中率、整体偏倚,并按三个区间分别统计;最后画真实值-预测值回归散点图和按真实体重排序的逐样本残差图。
二、疑点与改进建议
最重要的新发现:特征工程和异常值截断目前实际上完全没有生效
这是这次最关键的一点,建议汇报里重点提一下。generate_v2_enhanced_features 和 robust_feature_clipping 两个函数体里的核心逻辑都被注释掉了,意味着:
- 之前设计的 5 个临床衍生特征(Fetal_Vol、HC_AC_Ratio、Metabolic_Synergy、FH_GA_Rate、BMI_Shift)目前没有被真正生成,模型实际只用了原始字段(只是列名做了清洗)。
- 异常值的 1%~99% 分位数截断目前也没有真正执行,原始极端值原样进入了模型。
- 这也顺带解决了我上次提醒你的"全量数据上算统计量导致泄漏"的担忧——因为现在这两步根本没在算任何统计量,自然就没有泄漏问题。但代价是:模型现在用的特征集合和你研究设计里描述的不一致,如果汇报里提到"做了临床特征衍生和稳健化处理",需要先确认这是不是真实情况,避免汇报内容和实际跑出来的结果对不上。
启用衍生特征前需要确认的几个点
- Fetal_Vol、HC_AC_Ratio 等特征依赖的列名(AC_baby、FL、HC、PPBMI、GWG、FH、GA、PNBMI)需要先确认在
dataset_30%.csv里是否真实存在、命名是否完全一致,否则一旦启用,大概率会走 else 分支被填成全 0,等于做了个无效特征。 - 如果以后要重新启用这两个函数,分位数截断这类"需要从数据里统计的处理"必须放在
train_test_split之后,只用训练集的统计量去 fit,再把同样的边界应用到测试集,不能像现在函数签名暗示的那样在切分前对全量数据处理,否则会重新引入数据泄漏。 robust_feature_clipping里cols_to_fix目前是空列表,即便恢复注释,也需要先把要处理的列名填进去,否则循环不会做任何事情。
缺失值处理目前只停留在审计层面
audit_missing_values 只打印报告,整条流程里没有看到显式的插补(imputation)步骤。目前模型大多是树模型(LightGBM/XGBoost/CatBoost),原生可以处理 NaN,所以流程没有报错,但这属于"隐式依赖模型自身处理缺失值"的设计,建议汇报里明确说明这是有意为之的选择,而不是遗漏,方便老师/评审理解。
路由阈值是统计定义而非临床定义
低/正常/高体重的切分点是 router 预测值的 15%/75% 分位数,不是临床上常用的 <2500g(低体重)、>4000g(巨大儿)这类固定阈值,分组结果会随数据分布漂移,临床解释性上需要补充说明,或者增加一组按临床固定阈值对照的结果。
路由误判的级联放大效应 如果某个真实低体重/巨大儿样本,router 的初始预测值刚好落在分位数边界另一侧,就会被分配给没在这类样本上训练过的专家,误差可能被放大。目前的分区间评估是按 router 自己的分组统计的,无法体现边界误判的损失,建议针对边界附近样本单独做一次误差分析。
Optuna 在低/高体重组上搜索容易过拟合
低体重、巨大儿样本量天然偏小,30 轮 Optuna + 仅 3 折 CV 同时搜超参数和非对称惩罚系数 omega(低组 1.25.0,高组 2.06.0),结果对随机种子可能很敏感,建议做重复 CV 或对 omega 做敏感性分析确认稳定性。
自定义非对称损失里 hessian 是常数 本质是加权 MAE,不是真正二阶信息,LightGBM 在 hessian 退化的情况下叶子更新可能不稳定,且 Optuna 搜索空间里没有正则化参数(reg_alpha/reg_lambda/subsample 等),小样本下风险更高。
评估指标对极端值缺乏防御
MAPE 和 ±10% 准确率的计算里用了 (y_true - y_pred) / y_true,如果 y_true 出现 0 或异常小值会导致除零或异常放大误差,建议加一道防御性检查。
缺少多随机种子重复实验 整条流程都固定用 random_state=42,没有看到多种子重复实验,目前的指标有多少是模型真实能力、有多少是这次种子运气好,无法判断,汇报里如果要强调结果稳健性,建议补充多种子结果的均值±标准差。
分类模型:
一、整体流程总结
1. 环境与目标设定(Cell 1)
设随机种子保证可复现,定义一级模型的召回率硬指标 TARGET_RECALL_L1 = 0.95,即一级模型必须先把 95% 以上的真实巨大儿样本"捞出来",不能漏。
2. 数据准备(Cell 2)
读取 dataset_is_Macrosomia.csv,从 13 项预设临床指标里动态挑出数据集里实际存在的列作为特征池,目标变量是 is_Macrosomia。按 8:2 分层抽样切分训练/测试集(保证两边阳性比例一致),然后把可能的脏数据转成数值型,用训练集的中位数填充缺失值,同步应用到测试集。这一步代码注释里写明是为了修复"之前中位数填充导致信息泄露"的问题,目前这个修复是对的:先切分、再用训练集统计量填充。
3. 特征重要性分析与标准化(Cell 3) 用随机森林在训练集上算一次特征重要性并画图展示,仅作为参考分析,不进入最终预测链路。之后把训练/测试特征转成 numpy 矩阵,用 StandardScaler 在训练集上 fit、测试集上 transform。
4. 一级模型(L1):神经网络高敏感度筛查(Cell 4-5)
搭建一个三层全连接网络(128→64→1,带 BatchNorm 和 Dropout),损失函数用 FocalLoss(alpha=0.45, gamma=2)应对类别不平衡。训练时整个训练集当一个 batch,跑 150 个 epoch,没有验证集监控、没有早停。训练完后用 Optuna 在测试集的预测概率上搜索一个分类阈值,目标是在 Recall >= 95% 的约束下让误诊数(FP)最小,最终得到 L1 的最优阈值 best_t_l1。
5. 二级模型(L2):局部精细化分类(Cell 6-9)
把训练集和测试集里 L1 预测概率超过 best_t_l1 的"疑似阳性"样本单独挑出来,把 L1 的预测概率作为一个新特征拼进原始特征矩阵,在这个子集上训练 XGBoost、LightGBM、CatBoost 三棵树,三者预测概率取平均得到 L2 输出。最终预测规则是:L1 判定阴性的样本直接判 0(不再过一级),L1 判定阳性的样本由 L2 重新分类决定最终结果。之后又做了一轮"特征交叉增强"实验:取 RF 重要性最高的两个特征做乘积当作交互项,重新拼进 L2 特征矩阵又训练了一次三棵树。
6. 性能基线可视化(Cell 10) 画了一级 NN 单模型的 PR 曲线,作为后续对比的基线。
7. 改用横向融合(Blending)策略(Cell 11)
这里是设计思路的一个转折点:放弃了上面 L1→L2 的级联架构,改成另起一个分支——单独在全量训练集上训练一个 CatBoost(tree_full),输出测试集概率 tree_probs,然后把它和 L1 的 NN 概率 l1_probs 按固定权重 0.7/0.3 做加权平均,配合一个手动设的阈值 0.38 做了一次初步测试。
8. 自动寻优融合比例与阈值(Cell 12)
用 Optuna跑 600 轮,同时搜索融合权重 w1(NN 权重)和判定阈值 t,搜索目标是:约束最终 Recall >= 85%,在满足约束的前提下让 FP 最小(即让 Precision 最大化)。这一步是直接拿测试集的真实标签当优化目标跑出来的。
9. 最终效能看板(Cell 13) 用上一步搜出来的最优权重和阈值,对融合后的最终预测计算十项临床指标(灵敏度、特异度、漏诊率、误诊率、准确度、PPV、NPV、约登指数、阳性似然比、阴性似然比),并画混淆矩阵、ROC 曲线、阈值-灵敏度/特异度曲线、概率校准曲线四联图作为最终汇报看板,最后打印总结说之前的历史缺陷(缺失值泄露、特征维度失调、变量未定义、级联过滤报错)都已修复。
二、疑点与改进建议
1.(最关键,建议汇报里务必提前说明或先修正)阈值和融合权重是直接在测试集上调出来的 这是这版代码里最严重的问题,一共出现了三次:
- Cell 5 里,L1 的分类阈值
best_t_l1是 Optuna 在测试集的l1_probs/y_test_np上搜出来的; - Cell 8 里,L2 的阈值同样是在测试集子集
y_test_l2/l2_final_probs上搜的; - Cell 12 里,融合权重 w1 和最终阈值 t 是用 600 轮 Optuna 直接在测试集的
y_test_np上搜出来的。
这三处本质上都是"用测试集的真实标签去挑模型的超参数(阈值/权重)",等于让测试集参与了训练决策,Cell 13 报告的灵敏度、特异度、PPV 等所有指标都会比模型在真正未见数据上的表现更好看,存在系统性虚高。这个问题比之前修复的"中位数填充泄露"更严重,因为它直接作用在最终评估指标上。建议把训练集再切一份验证集(或者对训练集做交叉验证)出来专门做这几处阈值/权重搜索,测试集只在最后报告一次结果,全程不参与任何调参决策。
2. L1→L2 级联架构最终被放弃,但代码还留着,容易造成汇报口径混乱 Cell 6-9 搭建的"L1 筛查 + L2 局部精细分类"级联结构,在 Cell 11 之后被完全绕开了——最终汇报的 Cell 13 指标用的是 Cell 11/12 的"NN 概率 + 全量 CatBoost 概率"加权融合方案,跟 L2 的三棵树模型完全没有关系。也就是说 Cell 6-9 那一整套(包括特征交叉增强实验)目前是"探索过程中留下的分支",没有进入最终结果。建议汇报前明确一下:到底要呈现哪一个架构作为最终方案?如果级联方案不打算用了,建议从代码里挪走或者标注清楚是"对比实验",避免评审误以为最终模型用了三级结构。
3. 不同阶段的 Recall 目标不一致,没有说明取舍逻辑
L1 设计目标是 Recall >= 95%(Cell 1 全局参数),L2 阈值搜索时用的是 Recall >= 88%(Cell 8),最终融合阈值搜索时约束又降到了 Recall >= 85%(Cell 12)。三个阶段的"不能漏诊"标准一路往下调,最终汇报的临床达标线到底是 95% 还是 85%,目前从代码里看不出明确的取舍依据,建议汇报里讲清楚为什么逐级放宽,否则容易被问"一开始定的 95% 目标怎么没达到"。
4. 一级 NN 训练缺少验证监控,全批量训练 150 轮没有任何早停或过程曲线 训练时把整个训练集当一个 batch,跑固定 150 个 epoch,中间没有切验证集看 loss/recall 曲线,也没有早停机制,无法判断模型是否过拟合或者训练不足,只能看最终一次结果。建议至少从训练集里再切一小部分做训练过程中的验证监控,方便判断 epoch 数选得是否合理。
5. 树模型和最终融合模型都没有做类别不平衡处理
NN 用了 FocalLoss 来应对正样本(巨大儿)少的问题,但 L2 的三棵树(XGB/LGB/CatBoost)和最终单独训练的 tree_full CatBoost 都没有设置任何类别权重(如 scale_pos_weight、class_weights),如果巨大儿阳性率本身比较低,这几个树模型在没有调权重的情况下输出的概率可能存在系统性偏置,建议补上对应的不平衡处理参数。
6. FocalLoss 的 alpha 是手动设的固定值 0.45,没有和实际阳性率挂钩
Cell 2 打印了总体阳性率 y.mean(),但 Cell 4 的 FocalLoss alpha 固定写死成 0.45,没有依据实际算出来的阳性率去设置或者纳入搜索,建议让 alpha 跟实际类别比例联动,或者把它也作为一个可调超参数。
7. 全程只做了一次训练/测试切分,没有交叉验证 在已经存在第 1 点测试集泄漏问题的基础上,整个流程也没有用交叉验证或重复多次切分来评估结果的稳定性,单次切分的结果方差未知,建议至少做几次不同随机种子的重复实验,或者上 K 折交叉验证,让最终汇报的指标更有说服力。
8. 特征池存在性筛选是静默处理的
Cell 2 里 available_cols = [c for c in RAW_COLS if c in df_raw.columns],如果 13 项里有缺失的列会被悄悄跳过,没有打印提示是哪些列缺失,建议加一句提示,方便核对最终用了多少、哪些特征,避免汇报时被问起来答不上来。