637. Playground Series - Season 5, Episode 1 | playground-series-s5e1
首先,让我感谢比赛的组织者和所有参与者带来的有趣讨论!
在这次比赛中,我的解决方案基于连续构建乘法模型、其微调和交叉验证。我很幸运很快就获得了 leaderboard 第 1 名的位置,我的努力集中在如何防止过拟合上。
我已经公开了基础模型,它达到了约 0.05 的公共分数,在没有集成学习的情况下优于大多数公共 notebook。该模型在 notebook 中有完整描述。简而言之,它包含了以下因子:
基础模型通过跨年份平均销售额来考虑节假日。这是不正确的,因为许多节假日的确切日期每年都不同。
为了克服这个困难,使用了 holidays 库。然而,虽然这个库很棒,但并不完美。它没有包含肯尼亚的几个节假日(开斋节、莫伊日、牺牲节);对同一个节假日使用不同的名称(肯雅塔日和 Mashujaa 日);并且当同一天有两个节假日时需要小心处理。此外,它输出“正常”以及“观测到”的节假日。我的实验表明,最好将这两种类型的节假日视为单独的节假日。结果,使用该库后,数据框中的每个国家的每个节假日都由单独的列表示,其中节假日日期处为 1,其他处为 0。
有人注意到,‘节假日效应’发生在实际节假日几天之后。我的实验表明,这可以用一个简单的高斯曲线来描述:
$$H(t) = \exp\left(- \dfrac{(d-d_h-d_0)^2}{2\sigma_0^2} \right),$$
其中 \(d\) 是当前日期;\(d_h\) 是节假日日期;\(d_0=4.5\) 是响应偏移,\(\sigma_0=2\) 是高斯曲线的宽度。整个响应计算为 \(H(t)\) 与相应节假日列数据的卷积,并乘以需要确定的幅度因子。
提交分数乘以约 1.06 的因子后会变得足够好,感谢 @cabaxiom 发现了这一点。如果肯尼亚的预测也乘以约 1.03,甚至可以进一步改进。这对我来说非常奇怪,因为很难描述这个因子,并且使用它在交叉验证期间充分降低了分数。我认为这个因子及其理解是比赛的关键。
最后,在 accounted for 所有因子后,我发现销售额以复杂的方式依赖于时间,我们需要做出预测(见下图)。我 efforts 试图用某种经济指标或数据集中已有的特征来解释它,但失败了。模式是不确定的,因为它不是线性的,这是由于 2010-2012 年的波动。虽然 2017 年后的线性延续相当精确地解释了 1.06 和 1.03 因子,但我们不能确定这种线性增长存在于 2018-2019 年。所以,我决定在 linear trend 的假设下进行第一次最终提交,而第二次假设它在 2018-01-01 之后是恒定的。
查看私有分数,这是一个好的决定:第二次提交取得了更好的分数!
在基础模型中,参数是使用顺序回归优化的。这似乎不是最优的,最好同时优化它们。此外,比赛中使用的 MAPE 指标不同于 MSE。
所以,取而代之的是,我构建了一个 predict 函数:
$$
\text{predict}(\hat X, \vec\alpha) = \alpha_0\prod\limits_{n=1}^N(\hat 1 + \hat X_n \vec\alpha_n),
$$
其中整个数据框 \(\hat X\) 被分为 \(N\) 组列 \(\hat X_n\):\(\hat X = [\hat X_1, \hat X_2, \dots, \hat X_N ]\),并且 \(\hat 1\) 是全 1 列向量。
开始时,所有参数初始化为零或某些合理的值。然后使用一组或多组列进行训练。最后,使用所有列进行训练。这对所有国家和仅肯尼亚都这样做。
我使用了简单但强大的 scipy.optimize 中的 minimize 来执行优化。这使我能够快速实验许多因子和函数依赖关系,而无需创建深度学习框架所需的整个基础设施。
6 折交叉验证是在每年基础上进行的,最终模型是在整个数据上训练的。
我发现如果我们丢弃肯尼亚 2010-2012 年的数据,本地交叉验证和公共 leaderboard 分数都会显著提高。所以我在最终模型中这样做了。
不幸的是,这是一个提高公共分数的好主意,但对私有分数不好。未丢弃数据的 notebook 实现了 0.04369 的私有分数,对应第 1 名。
目前,我不知道 @georgekoussa 在比赛中使用了什么。
然而,@cdeotte 非常 kindly 分享了他的深度学习 notebooks。对我来说,特别有趣的是,在这种类型的比赛中,哪种解决方案会更好,即人类可以“手动”执行特征提取。好吧,我们可以得出结论,两种解决方案大约处于同一水平。然而,我相信,深度学习方法在更复杂的任务中会更好。