664. Playground Series - Season 5, Episode 8 | playground-series-s5e8
非常感谢 Kaggle 组织了如此精彩的 Playground 竞赛!这个月的数据集非常出色,我真的很享受这个过程并学到了很多。
特别感谢 @mulicmu 的"Dive into Deep Learning",AutoGluon 库,@optimistix 在 第一名解决方案 中分享的想法,@cdeotte 的热情分享,以及社区中所有公开分享工作和想法的人。
我的主要想法是使用迭代式 OOF(Out-of-Fold)堆叠结合 AutoGluon。工作流程如下:
| 版本 | 模型 / 备注 | 私有榜 (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 |
关键洞察:
| 版本 | 模型 / 备注 | 评估指标 (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 个新特征,主要包括:
特征交互
目标/类别编码 (TE & CE)
手动工程特征
| 版本 | 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 |
分析:
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",
)
总结:
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 | ✅ 已选 |
| 版本 / 混合 | 描述 / 备注 | 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 |
很遗憾没能运行更多有趣的实验,我的 Notebook 最终也有点乱 —— 但这里是 Notebook 链接。
“道可道,非常道。名可名,非常名。”
学习是一个不断积累的过程 —— 量变最终会导致质变。
享受接下来的学习旅程,不断突破你的界限!
祝好运!