返回列表

3rd Place Solution — OOF Stacking + AutoGluon

664. Playground Series - Season 5, Episode 8 | playground-series-s5e8

开始: 2025-08-01 结束: 2025-08-31 信贷风控 数据算法赛
三等奖解决方案 — OOF 堆叠 + AutoGluon
作者: bestwater (EXPERT)
发布日期: 2025-09-01
竞赛排名: 第 3 名

🥉 三等奖解决方案 — OOF 堆叠 + AutoGluon

非常感谢 Kaggle 组织了如此精彩的 Playground 竞赛!这个月的数据集非常出色,我真的很享受这个过程并学到了很多。

特别感谢 @mulicmu 的"Dive into Deep Learning",AutoGluon 库,@optimistix 在 第一名解决方案 中分享的想法,@cdeotte 的热情分享,以及社区中所有公开分享工作和想法的人。

📌 解决方案思路

我的主要想法是使用迭代式 OOF(Out-of-Fold)堆叠结合 AutoGluon。工作流程如下:

  1. 收集 OOF 和提交文件:收集高质量 Notebook 和我自己模型的 OOF 预测及提交文件,同时过滤掉那些存在数据泄露或 CV 分数虚高的文件。
  2. 使用 AutoGluon 训练:将选定的 OOF 文件作为特征输入 AutoGluon,训练新模型,生成新的 OOF 和提交文件,同时记录特征重要性。
  3. 筛选特征:分析特征重要性,为下一轮选择高质量特征。
  4. 迭代过程:重复步骤 1-3,不断添加新模型和 OOF,稳步提升集成性能。

🏆 模型开发概览

版本 模型 / 备注 私有榜 (Private) 公开榜 (Public) 类型 与最佳私有榜差距
Baseline AutoGluon 基线 0.96677 0.96691 多模型 (time_limit=1000) -0.00947
V1 GPU 配合 KNN 0.97085 0.97111 多模型 (best_quality) -0.00539
V2 添加伪标签数据 0.97085 0.97106 多模型 (伪标签) -0.00539
V3 GBM 0.97082 0.97100 单模型 -0.00542
V4 NN_TORCH 0.96528 0.96559 单模型 -0.01096
V5 CATBoost 0.96910 0.96951 单模型 -0.00714
V6 XGB 0.97008 0.97046 单模型 -0.00616
V7 FASTAI 0.96505 0.96512 单模型 -0.01119
V9 双 GPU, 移除 KNN 0.97096 0.97113 多模型 (best_quality) -0.00528
V10 Random Forest (RF) 0.96650 0.96694 单模型 -0.00974
V11 Extra Trees (快,2 小时) 0.96478 0.96516 单模型 -0.01146
V12 多次 OOF 重训练 0.97624 0.97663 OOF / 堆叠 (CV ROC AUC: 0.97589771) 0.00000

关键洞察:

  • 单模型和标准的 AutoGluon 多模型表现相当不错(≈0.971)。
  • OOF/堆叠集成进一步将分数提升至 0.976,表明先进的集成策略明显优于单模型或标准多模型。
版本 模型 / 备注 评估指标 (eval_metric) CV ROC AUC 私有榜 公开榜
V34 AutoGluon, 50 个 OOF 文件 'roc_auc' 0.977498 0.97772 0.97806
V41 AutoGluon, 调整评估指标 'pac' 0.977486 0.97772 0.97807
V39 AutoGluon, 调整评估指标 'nll' 0.977486 0.97771 0.97805
V38 AutoGluon, 调整评估指标 'mcc' 0.976961 0.97770 0.97805
  • eval_metric'roc_auc' 改为 'pac''nll' 对 CV 或 LB 分数几乎没有影响。
  • 使用 'mcc' 会略微降低 CV ROC AUC,但保持 LB 稳定。
  • 总体而言,指标的选择并没有显著提高榜单分数。
  • 有趣的是,'pac' 给出了最好的私有榜分数,这符合我当时的直觉,但我不敢赌它,坚持使用了官方的 'roc_auc' 指标。

🏆 最佳单模型演进

模型 / 版本 备注 / 演进 CV ROC AUC 私有榜 公开榜
Baseline 基于 @mahoganybuttstrings 的原始 Notebook 0.97578 0.97636 0.97681
V1 - 单 XGB 添加类别型 3 路组合 (Cat 3) 0.97576 0.97633 0.97681
V2 - 单 XGB 添加数值型 3 路组合 (Num 3) 0.97577 0.97638 0.97676
V9 - 单 XGB 添加高重要性特征并应用 TE & CE 0.97592 0.97645 0.97684
V10 - 单 XGB 添加高重要性特征 (无额外 TE/CE) 0.97602 0.97660 0.97702
V13 - 单 XGB 调整参数 0.97618 0.97683 0.97716
V19 - 单 XGB 移除 2 个最低重要性特征 0.97621 0.97687 0.97717
V28 - 单 XGB 选择最高相关性特征并创建乘积交互;CV 略有变化,但私有和公开榜均下降。 0.97632 0.97646 0.97685
V30 - 单 XGB 最高私有榜单模型 (修改版 XGB), 10 折 CV 0.97639 0.97693 0.97727
V32 - 单 XGB 40 折 CV 0.97637 0.97683 0.97722
V34 - 单 XGB 20 折 CV 0.97644 0.97688 0.97725

# 乘积交互
df['duration_div_duration_rank'] = df['duration'] / (df['duration_rank'] + 1e-5)
df['duration_minus_log_duration'] = df['duration'] - df['log_duration']
df['log_duration_mul_age'] = df['log_duration'] * df['age']
df['duration_relmean_minus_std'] = df['duration_rel_mean'] - df['duration_rel_std']
df['duration_per_campaign_mul_age'] = df['duration_per_campaign'] * df['age']

df['duration_mul_age_squared'] = df['duration'] * df['age_squared']
df['balance_log_mul_campaign'] = df['balance_log'] * df['campaign']
    

📌 特征工程总结

基于原始数据,我从 duration (持续时间), balance (余额), age (年龄), month (月份), 和 day (日期) 中设计并构建了大约 30 个新特征,主要包括:

  1. 非线性变换:log, sqrt, square, cube, 和指数变换。
  2. 分箱特征:基于分位数的分箱 (5/10/20/30 箱) 以生成类类别特征。
  3. 统计特征:长/非常长持续时间的指示器,绝对余额和平方项。
  4. 比率特征:持续时间与活动次数之比,余额与持续时间之比。
  5. 周期性特征:日期变量的正弦和余弦编码。
  6. 季节性特征:业务高峰月份指示器 (3 月,4 月,5 月,9 月,10 月,11 月)。

总体结论

  • 特征交互

    • 成对组合 (长度 = 2):提供了一致且明显的改进,是迄今为止最有效的交互策略。
    • 三路组合 (长度 = 3):尝试过,但收益微乎其微,有时还会引入噪声,导致益处有限。
  • 目标/类别编码 (TE & CE)

    • 非常有效,是对性能提升影响最大的技术之一。
  • 手动工程特征

    • 增加了一些价值,但总体影响弱于特征交互TE/CE
  • 对于单模型,增加交叉验证的折数通常有助于提高性能,但过多的折数可能会适得其反。
  • 最佳前进路径:专注于强大的成对交互,然后整合 TE/CE。
  • 其他工程特征可以作为补充添加,但不是性能的主要驱动力。
  • 这可能部分归因于 Kaggle Playground 数据集的性质,它们是合成生成的。在此类数据中,与系统性的交互和编码方法相比,手工特征工程往往效果有限。

🔹 预设 (Presets) 比较

版本 OOF 文件数 预设 (Presets) CV ROC AUC 私有榜 公开榜
V46 52 best 0.97752 0.97779 0.97809
V48 52 experimental_quality 0.97751 0.97778 0.97809
V53 48 experimental_quality 0.97754 0.97780 0.97809
V58 48 best 0.97753 0.97779 0.97810

分析:

  1. 使用 experimental_quality 预设对公开榜几乎没有影响,有时会略微降低,而略微提高私有榜。
  2. 这一观察结果来自竞赛的中后期;早期或大部分时间,experimental_quality 在公开榜和私有榜上都表现良好。
  3. 公开榜的结果让我对 experimental_quality 有些怀疑,这影响了我的一些决定。
  4. 由于担心过拟合,我在后期主要选择了 best 预设。

AutoGluon 手动 CV 实验

  • 目标: 测试当 auto_stack=True 时,手动设置 CV 折数是否能提高性能。
版本 基础 auto_stack CV 设置 CV ROC AUC 私有榜 公开榜
V34 default 0.97750 0.97772 0.97806
V35 V34 10-fold 0.97745 0.97765 0.97801
V36 V34 5-fold 0.97745 0.97768 0.97805
V42 default 0.97745 0.97770 0.97805
V44 V42 5-fold 0.97745 0.97769 0.97806

from sklearn.model_selection import KFold

train.loc[:, "fold"] = -1
split = KFold(n_splits=5, random_state=42, shuffle=True).split(train, train["y"])

for i, (_, val_index) in enumerate(split):
    train.loc[val_index, "fold"] = i

TabularPredictor( 
    groups="fold",      
)
    
  • 总结:

    • 手动 5 折或 10 折 CV (V35, V36, V44) 没有提高 分数;在某些情况下 CV ROC AUC 略有下降。
    • AutoGluon 的内置堆叠 (auto_stack=True) 已经有效地处理了 CV。

🏅 最终提交模型

模型 / 版本 备注 / 演进 CV ROC AUC 私有榜 公开榜 最终提交
V103 - AutoGluon CPU 上的 AutoGluon 集成;与最终提交模型工作流相同;seed = 105 0.97761 0.97788 0.97820
V107 - AutoGluon 与 V103 工作流相同,但在 GPU T4 x2 上运行;seed = 105 0.97761 0.97788 0.97819
V109 - AutoGluon 与 V103 工作流相同,但在 GPU T4 x2 上运行;seed = 5781 0.97763 0.97790 0.97821 ✅ 已选

✅ 行之有效的做法

  1. 我最好的公开榜分数也是我最好的私有榜分数 —— 这是最后一天倒数第三次提交,我当时只更改了一个随机种子。这表明运气也起到了一定作用。
  2. 在大多数比赛中,单模型很难超越精心设计的集成模型。对我来说,OOF 堆叠 + AutoGluon 带来了显著提升。
  3. 更多样化的集成往往会提高 CV 分数。

🔹 AutoGluon 混合 (Blending) 实验

版本 / 混合 描述 / 备注 CV ROC AUC 私有榜 公开榜 最终提交
V70 GPU 运行 Best 预设 0.977634 0.97789 0.97820
V76 GPU 运行 Extreme 预设 0.977618 0.97787 0.97817
V79 CPU 运行 Best 预设 0.977610 0.97787 0.97818
V87 GPU 运行 Best 预设 0.977615 0.97789 0.97820
V103 CPU 运行 Best 预设 0.977612 0.97788 0.97820
V108 GPU 运行 Best 预设 0.977634 0.97789 0.97820
V109 GPU 运行 Best 预设 0.977631 0.97790 0.97821
Blend Search2 V70 + V76 平均 0.977644 0.97789 0.97819
Blend Search3 V70 + V76 + V79 平均 0.977644 0.97789 0.97819
Blend Search4 V1 V70 + V76 + V79 + V87 平均 0.977643 0.97789 0.97819
Blend Search4 V2 V70 + V76 + V108 + V109 平均 0.977654 0.97789 0.97820 ✅ 最终提交
Blend Weighted Search4 V4 V70 + V76 + V108 + V109 加权混合 [0.18,0.18,0.27,0.36] 0.977655 0.97790 0.97820

⚠️ 效果不佳的做法

  1. 简单混合和加权混合提高了 CV 分数,但没有提高我的 LB 分数。
  2. 添加更多原始训练数据并没有提高榜单分数。

💡 反思与学习

  1. 这种迭代式 OOF 堆叠方法让我能够记录并利用每一次尝试,确保所有努力都有助于进步,并激励我不断学习。
  2. 阅读和学习其他优秀的解决方案和开源 Notebook 是提高最快的方法之一。

很遗憾没能运行更多有趣的实验,我的 Notebook 最终也有点乱 —— 但这里是 Notebook 链接

“道可道,非常道。名可名,非常名。”
学习是一个不断积累的过程 —— 量变最终会导致质变。
享受接下来的学习旅程,不断突破你的界限!

祝好运!

同比赛其他方案