返回列表

3rd Place - Target Encoding and 3 Levels

649. Playground Series - Season 5, Episode 4 | playground-series-s5e4

开始: 2025-04-01 结束: 2025-04-30 音视频处理 数据算法赛
第三名 - 目标编码与三层架构

第三名 - 目标编码与三层架构

作者: Johannes Heller (stopwhispering)
发布时间: 2025-05-01
竞赛排名: 第 3 名
竞赛: Playground Series S5E4

感谢这场有趣且精彩的比赛——数据集足够大以进行有意义的交叉验证(CV),但又足够小,可以在标准本地硬件上舒适地工作。祝贺 @cdeotte 再次取得 exceptional 的表现,以及 @greysky 仅用单个(!!!)LGBM 模型就取得了令人印象深刻的第二名!

我的方法主要依赖于目标编码(Target Encoding)以及一个具有多样化特征和超参数的大型模型集成。

在比赛的大部分时间里,我使用通过 Nelder-Mead 或爬山算法(Hill Climbing)进行的加权平均。作为最后一分钟的实验,我尝试了堆叠(Stacking)——这在 Kaggle 比赛中从未对我起作用过——但仅在第一次也是唯一一次尝试中,我就立即获得了 CV 从 11.66 到 11.62 的提升。我应该更早地探索和优化它。我怀疑堆叠在这里效果更好是因为单个最重要特征中存在高比例的缺失值。

最后,我将我的堆叠集成(80%)与我得分最高的爬山算法集成(20%)进行了混合,有效地将其转变为一种三层方法。

所有模型均使用 5 折交叉验证(简单 KFold)进行训练。我认为使用 7 折或 10 折可能会略微提高分数,但运行时间的权衡对我来说似乎不值得。

我用 Optuna 做了一些快速的超参数调优,但有趣的是,最终的集成受益于包含一些较旧的、未优化的模型。多样性似乎在这场比赛中效果特别好。

模型概览

第一层:

  • 10 × LGBM(各种特征和参数)
  • 5 × XGB
  • 4 × CatBoost
  • 2 × RandomForest
  • 1 × ExtraTrees
  • 4 × HistGradientBoostingRegressor

第二层:

  • 爬山算法 (Hill Climbing)
  • LGBM

第三层:

  • 加权平均 (Weighted Averaging)

有趣的是,HistGradientBoostingRegressor 在爬山算法中始终获得负权重(-0.08 到 -0.21),但从未被丢弃。有人能解释这是为什么吗?其他模型(线性模型)在爬山算法中被拒绝了。

最佳单模型 CV 分数

模型 CV 分数
LGBM 11.79
XGB 11.81
CatBoost 11.93
ExtraTrees 11.96
HistGB 11.99
RandomForest 12.05

有效的策略

  • 目标编码 (Target Encoding): 这是我大部分特征工程的 backbone。我尝试了中位数、最小值、最大值、唯一值计数(nunique),但均值 TE 得分最好。
    • 我将所有列转换为字符串后,连接了 2 到 7-grams。
    • 我丢弃了基数非常高或非常低的 TE 特征。
    • 为了加快速度,我将 TE 特征每折保存为 Parquet 文件。这迫使我在整个比赛过程中使用相同的 KFold 设置以避免泄露。
    • 我的顶级模型使用了大约 270 个 TE 特征。
    • 我使用了自定义的 TE 实现(无平滑,无 fillna),尽管使用 Scikit-learn 版本可能会产生类似的结果。
  • 修复 Number_of_Ads 和 Episode_Length_minutes 的极端异常值有帮助,详见 https://www.kaggle.com/code/stopwhispering/podcast-eda
  • 将字符串格式的 Episode_Length_minutes 的小数位数作为特征添加。感谢 @AngelosMar 的这个有趣发现。将其作为特征添加比手动修正具有高小数位数的预测效果稍好。
  • 一些 除/减/加/组合 交互特征
  • 原始数据集: 这次对于原始数据集,我采用了连接方法,只是将原始数据添加到训练数据集中。对于 CV 评分,我忽略了原始数据集记录。我还添加了一个标志 'is_original'。

无效的策略

  • 预测比率(Target / Episode_Length_minutes)而不是目标,并为 Episode_Length_minutes 为 NaN 的情况使用单独的模型
  • 任何类型的线性模型或神经网络 (NN)
  • 插补 (Imputation)
  • 分箱 (Binning), 聚类 (Clustering)
  • 分类变量的标签编码 (Label encoding)

特征选择

对于特征选择(这次主要是目标编码),我使用了一个非常贪婪的序列特征选择(Sequential Feature Selection)变体,使用具有高 learning_rate 和低 n_estimators 的 LGBM:在对所有候选特征评分后,我选择了得分最高的约 10-20 个特征并重新开始——远非最优,但我的本地硬件不允许更复杂的选择。之后我尝试了一些递归特征消除(Recursive Feature Elimination),但这 simply 耗时太长且没有产生好的结果。不过,我确实移除了与其他特征具有极高相关性的特征。

更新:添加了关于 TE、原始数据集和特征选择的一些细节。

同比赛其他方案