606. Playground Series - Season 4, Episode 4 | playground-series-s4e4
我在比赛临近结束时才参赛,以测试我的自动化机器学习(AutoML)工作流程,这套流程本想用于随后开始的AutoML 大奖赛。
出乎意料且令人惊喜的是,我的 AutoML 工作流程在未经任何调整的情况下表现非常出色。实际上,它在该数据集上的效果比在第一次 AutoML 大奖赛数据集上更好,因为该数据集真正受益于自动化特征工程。
我将在大奖赛的总结报告中分享该工作流程的主要代码。如果可能,我会把报告链接贴在下面,或在评论中更新。 编辑:这里是报告。
由于这是我首次积极参加 Kaggle 竞赛,我认为拥有一个额外且可能不可靠的数据源非常有趣。因此,为了决定是否在训练数据中加入原始数据,我针对原始数据、比赛提供的训练集和测试集开展了几组双样本检验。这些检验旨在判断是否存在分布偏移;如果存在偏移,加入原始数据可能会对模型有害。
我使用 AutoGluon 来预测它能否识别出样本来源,并使用 Mann‑Whitney U 检验来评估显著性。
我检验了以下几种组合:
根据这些检验的观察结果,我决定将原始数据纳入训练集。不过,如何自动做出这一决定仍需进一步 formalize。该设置还有改进空间,我希望在未来加入评估「加入数据是否有可能提升性能」的检验。
我认为这部分是获得第二名的关键。简单来说,我的做法是:① 运行定制版的 OpenFE,随后 ② 使用 AutoGluon 的特征选择 对特征进行剪枝。
在步骤②中,我尝试使用 LightGBM 作为代理模型进行特征选择。
在步骤①中,我首先手工挑选潜在的特征候选,以控制 OpenFE 搜索空间,并加入了一种新的特征生成器。随后,我使用默认参数运行 OpenFE,获得了约 200 个特征。最后,利用步骤②在 1 小时的时间限制内自动将这些特征剪枝至更小的集合。
遗憾的是,我无法提供最终特征生成器的全部细节,因为我的流程没有记录这些生成函数的名称。此外,在尝试为首届 AutoML 大奖赛数据实现自动化特征工程时(剧透:并不值得),我的代码库变得相当凌乱,难以追溯。
我使用以下代码控制特征生成器:
all_features = list(train_data.columns)
soft_ordinal = [f for f in all_features if (train_data[f].nunique() <= 100) and (f not in ordinal_columns)]
numerical_features = [f for f in all_features if f not in categorical_columns]
candidate_features = get_candidate_features(
numerical_features=numerical_features,
categorical_features=categorical_columns,
ordinal_features=ordinal_columns + soft_ordinal,
order=1, # 2 is likely impossible to use w/o time estimate.
)
# Restrict Search Space of Candidate Features
candidate_features = [
f
for f in candidate_features
if f.name
in [
# "abs" -> dataset specific, not useful in most cases
# "log" -> can be done by scalers, no need for GBDTs
# "sqrt", -> see above (s.a.)
# "square" , -> s.a.
# "sigmoid" , -> s.a.
"freq", -> # do not like it but giving it a shot.
"round",
"residual",
# "max", -> IMO, trivial to model for first-order features
# "min", -> s.a.
# "+", -> s.a.
# "-", -> s.a.
"/",
"*",
# "GroupByThenMin", -> The essential benefit of GroupBy is captured with any of these, so I filtered this to reduce the search space.
# "GroupByThenMax", -> s.a.
# "GroupByThenMean", -> s.a.
"GroupByThenMedian",
"GroupByThenStd",
# "GroupByThenRank", -> s.a.
"GroupByThenFreq",
"GroupByThenNUnique",
"Combine",
# New Generators
# - Hacked into OpenFE by adding `new_data = int(d < d.quantile(X).max())` to the generator options.
"
最终,我使用了「经过调优」的 AutoGluon 来选择最终模型。完整的细节将在 AutoML 大奖赛的报告中分享。编辑:这里是报告。
在这里值得注意的是,堆叠(Stacking)在该数据集上效果非常好(相关代码涉及动态堆叠)。因此,我将 AutoGluon 配置为最多进行 6 层堆叠。最终它使用了 5 层,但查看我的提交得分时,仅使用 3 层也达到了相同的分数,而第 5 层同样没有出现过拟合。
希望这(以及更详细的报告)能够为您提供解决方案的概览。同时,也期待您和我一样对更高效、更好的自动化特征工程感到兴奋! ;)
祝好,
Lennart