返回列表

#1st place solution

609. Playground Series - Season 4, Episode 5 | playground-series-s4e5

开始: 2024-05-01 结束: 2024-05-31 公共安全 数据算法赛
第1名解决方案

第1名解决方案

作者:aldparis(Kaggle Master)

发布日期:2024-06-01

比赛: Playground Series S4E5 - 洪水预测

感谢Kaggle组织此类表格类竞赛。我从这些比赛中学到了很多。也从公开的 notebooks 和讨论中学到了很多,感谢大家的分享。

由于该数据集包含泊松分布的和,本次比赛的冠军一定来自法国。感谢西蒙·丹尼斯·泊松先生为我们提供了这样的工具,也感谢他在比赛期间给了我额外的动力。

感谢所有参赛者,你们真的很有挑战性,和你们较量是一种乐趣。祝贺 @mdoroch(我会联系你,你非常出色)、@lashfire@mattop@tilii7:你们最后几天的提交让我非常紧张!

我的解决方案

  • 使用岭回归(ridge regression)进行集成,参数为 positive = False, fit_intercept = False
  • 使用 3 次重复的 OOF 预测来调整各种模型,这些模型由 catboostxgboostlightgbm 以及两个公开的 notebook 生成:

EDA(探索性数据分析)

EDA 帮助我认识到原始数据集与训练集完全不同。EDA 还帮助我发现在训练集中,16 个原始特征的和仍然是泊松分布,但 18、19、20 个原始特征的和不再是泊松分布(在测试集中也不是)。并且 EDA 帮助我找到了与目标相关的有趣特征(感谢 @ambrosm 提供最重要的特征)。

特征选择

我为自己的 GBM 模型进行了以下特征选择:

  • 有用的特征:每行的和、每行的标准差、每行的最大值、排序后的原始特征(感谢 @siukeitin 关于「沿特征轴排序作为特征工程」的讨论),以及值大于 6、7、8 的变量数量(计数特征)。
  • 无用的特征:原始特征、每行的偏度、每行的峰度、冗余特征。我把它们都删掉了。
  • 神奇特征:由于目标可以视作离散变量,我使用了目标编码,并且 train.groupby("sum")["FloodProbability"].std() 是一个有趣的特性(其中 train["sum"] = train[test.columns].sum(axis=1))。
  • 我使用了置换特征重要性scikit-learn)和后向特征消除(backward)技术来检测无用特征。

多样的模型

我训练了超过 30 个 GBM 模型,使用不同的特征组合:有时使用排序后的原始特征,有时使用计数特征 nb_inf4nb_inf3nb_inf2nb_sup6nb_sup7nb_sup8,有时使用目标编码,有时不使用。

我还使用了目标转换:存在强信号(和)以及噪声信号(与和的偏差)。我的转换目标是:

train["target_transf"] = train["FloodProbability"] - df[original_features].mean(axis=1) * 0.1

train["target_transf"] = (train["FloodProbability"]*400 - train[original_features].mean(axis=1) * 40).astype(np.int16)

(感谢 @act18l

在前 10 天,我仅使用默认参数(带早停),未对任何 GBM 进行优化,专注于特征与集成循环。随后,我使用 Kaggle 的 GPU 配额通过 Optuna 优化超参数,最长超时 5400 秒,仅优化以下超参数:

  • depth(catboost、xgboost)
  • num_leaves(lightgbm)
  • alpha、lambda、min_child_weight/min_child_samples(xgboost、lightgbm)
  • bagging_temperature、random_strength(catboost)
  • subsample、colsample_by_node(xgboost、lightgbm)

我使用了各 GBM 默认的 grow_policy(不同 GBM 的默认值各不相同,因而产生预测多样性),使用默认学习率 0.1(或 0.1),并使用早停(catboost 中的 od_wait)来控制迭代次数。

集成

在最初的两周,我使用线性回归(LinearRegression)进行集成,参数为 positive = True, fit_intercept = False。后来尝试了岭回归(Ridge),参数 positive = False(同样 fit_intercept = False),获得了小幅提升。为了获得稳健的集成,我对所有模型使用了3 次重复的 K 折交叉验证,并通过交叉验证选择用于集成的特征。

在第二周结束时,我使用 Auto Gluon Starter 的输出进行盲融合提交,获得了公开分数 0.86939,优于之前的 0.96934。几天后,我获得了第一份完整的 AutoGluon OOF 文件。随后我仔细拟合了一个新集成,在第三周结束时得到分数 0.86941

随后,我决定获取 3 份 AutoGluon OOF 文件,并用其它特征再生成 3 份 OOF。我在并行模式下训练 AutoGluon(链接),共得到 6 份 OOF 文件。最终的集成在公开 LB 上取得了 0.86943 的分数。

结论

总之,我的成功源于以下组合:

  • EDA(探索性数据分析)
  • 特征工程
  • 多样的 GBM 模型
  • AutoGluon
  • 稳健的交叉验证岭回归集成

我自豪的是,在 5 月 18 日到比赛结束之间仅提交了 2 次,就获得了公开和 Private LB 的第一名。我的交叉验证从第一天起就与公开 LB 高度吻合,我信任自己的 CV,无需再提交。

我的最终集成可在此处查看:https://www.kaggle.com/code/adaubas/pss4e05-ensemble-with-ridge

我非常开心!哇哦!

同比赛其他方案