619. Playground Series - Season 4, Episode 7 | playground-series-s4e7
大家好,
我想感谢 Kaggle 社区和各位参赛者带来了令人难以置信的 Playground Series episode。这是一个资源密集且耗时的挑战,需要极大的耐心才能取得胜利。公共 leaderboard 的频繁变动,尤其是在最后 2-3 天,反映了激烈的竞争。
以下是我分为几个迭代的旅程。
在最初的尝试中,我在配备 RTX 4070 的本地 PC 上训练了一组快速、轻微调优的模型(XGB、LGBM 和 SnapML)。
0.88448,CV 得分为 0.8833。0.8880。在这次迭代结束时,我的得分大约在 0.88。为了突破 0.89 大关,我需要进一步的改进。我还没有探索 CatBoost,因为公共论坛表明其默认设置可以产生超过 0.895 的得分。
决心调优 XGB、LGBM 和 SnapML 以匹配 CatBoost 的性能:
train_df['Insured_Vehicle_Damage']= train_df['Previously_Insured'].astype(str) + train_df['Vehicle_Damage'].astype(str)
train_df['Insured_Vehicle_Age'] = train_df['Previously_Insured'].astype(str) + train_df['Vehicle_Age'].astype(str)
train_df['Insured_License'] = train_df['Previously_Insured'].astype(str) + train_df['Driving_License'].astype(str)
train_df['Insured_License'] = train_df['Previously_Insured'].astype(str) + train_df['Driving_License'].astype(str)
train_df['Insured_Gender'] = train_df['Previously_Insured'].astype(str) + train_df['Gender'].astype(str)
0.89387,CV 得分为 0.89113。0.89344,CV 得分为 0.89302。在 Kaggle 上使用 TPU 的一个挑战是,当 TPU 未被消耗时,3 小时后会自动关闭,但分布式调优允许我快速恢复训练。0.890,因此在这次迭代后我将其过滤掉了 ☹️。TABNET 和 GANDALF,它们的 CV 得分也达到了 ~0.8910,但它们的训练成本非常高,并且与 GBDT 相比没有提供更好的性能。在这个阶段结束时,我的 LB 得分约为 ~0.8930,所以下一阶段是尝试一些不同的技术来缩小差距。
CategoryEmbedding 模型的神经嵌入来提高 LightGBM 和 XGBoost 的得分。这是一个错误,因为嵌入维度接近 300 维,需要高 RAM。CV 得分最初飙升到 0.895 是由于种子不匹配导致的 bug,我在耗尽 Colab 积分后才发现这一点 ☹️。此时,我考虑跳过这一期,因为几乎耗尽了所有计算资源和时间,且没有成功的保证。在大约 30 次提交后,我决定最后尝试一次 CatBoost。
在这个阶段,我只调优了一个 CatBoost 模型(就一个),再次使用相同的策略,在 3 台机器上分布式 Optuna,接近 50 轮 HPO,耗时约 10 小时,因为不幸的是,与 XGB 和 LightGBM 相比,CatBoost GPU 不支持 pruner。以下是 HPO 调优后的参数:
'learning_rate': 0.11913236771124495,
'reg_lambda': 0.5423732686916918,
'max_depth': 6,
'subsample': 0.9996168133883909, # 我在训练完整模型时将其改为 1.0。
'leaf_estimation_iterations': 10,
'log_max_bin': 15
以下是我用于 HPO 的固定参数:
"loss_function": "Logloss",
"eval_metric": "AUC",
"iterations": 3000,
"random_state": 56315,
"bootstrap_type": "Bernoulli",
"grow_policy": "SymmetricTree",
"task_type": "GPU",
"early_stopping_rounds": 100,
"leaf_estimation_method": "Newton",
"use_best_model": True,
上述参数在训练 5000 次迭代并进行一些调整时,公共 LB 得分为 0.89666,但这还不足以获胜。
通过在 Kaggle 笔记本上的小实验,我观察到了两件重要的事情:
0.085 并将迭代次数增加到 10000。score_function 优于基于 Gradient 的。我想这是大多数公共笔记本忽略的。一旦我切换到 NewtonCosine 或 NewtonL2 并使用 12 次 leaf_estimation_iterations,我的 CV 本身就接近 0.8960。此外,我首先从原始数据中移除对比重复项,然后在合并后从训练集和原始数据中移除,正如本讨论中所讨论的:https://www.kaggle.com/competitions/playground-series-s4e7/discussion/520253。我还对 Age 和 Premium 特征进行了分箱,因为我发现这略微提高了我的验证得分。
在尝试了所有方法后,我将数据集分为 4 折。我无法一起训练所有折,甚至无法在 Kaggle 上训练单个折,因为 CatBoost 训练后需要接近 (48 GB) 的 RAM。
我用剩余的计算资源在 Colab 上训练了前 3 折,这次提交取得了 0.89720 的 LB 得分,使我进入前 10 名,但在按照 @paddykb 提到的技巧操作后,它提升到了 0.89780。
为了最终确定得分,我在 Kaggle 上训练了具有相同参数但减少迭代次数的小型 CatBoost 版本,使用不同的 CV 分割和随机状态,并仅基于验证得分进行平均(因为此时我没有 OOF 折来 properly 混合),这使得我的最终得分在没有技巧的情况下为 0.89728,有技巧的情况下为 0.89788,这是获胜解决方案,私有 LB 得分为 0.89753。
以下是没有任何技巧的折的最终 CV-LB 得分:
| 折 (Fold) | CV 得分 | LB 得分 |
|---|---|---|
| Fold-0 | 0.8960367441 | 0.89625 |
| Fold-1 | 0.8962229192 | 0.89629 |
| Fold-2 | 0.8962465823 | 0.89632 |
| Fold-3 | 0.8959594369 | 0.89620 |
| **Fold-4 | 0.8958430433 | - |
**Fold-4 是我所有小型模型的平均值。 |
||
max_ctr_complexity 导致过拟合。特别感谢 @ravi20076, @arunklenin, @tilii7, 和 @optimistix 带来的良性竞争,以及 @paddykb, @ivanmitriakhin, @rzatemizel 提供的技巧。